@cleocode/cleo 2026.5.109 → 2026.5.110

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
@@ -1719,10 +1719,10 @@ var init_credentials = __esm({
1719
1719
  }
1720
1720
  });
1721
1721
 
1722
- // packages/core/src/store/db-inventory.json
1722
+ // packages/contracts/src/db-inventory.json
1723
1723
  var db_inventory_default;
1724
1724
  var init_db_inventory = __esm({
1725
- "packages/core/src/store/db-inventory.json"() {
1725
+ "packages/contracts/src/db-inventory.json"() {
1726
1726
  db_inventory_default = {
1727
1727
  $schemaNote: "SSoT machine-readable inventory of every CLEO SQLite database. Consumed by T10307 fleet survey, T10310 pragma drift, T10311 migration coverage, T10312 doctor integrity, T10320 cross-DB invariants. Owned by Saga T10281 SG-BRAIN-DB-RESILIENCE / Epic T10282 E1-DB-INVENTORY (task T10305). Amend together with ADR-068 charter; the CI drift gate (forthcoming under E1) compares entries to disk reality.",
1728
1728
  $pathTokens: {
@@ -14810,7 +14810,38 @@ function validateCanonRegistry(raw, source) {
14810
14810
  for (const [kindId, entryRaw] of Object.entries(kindsRaw)) {
14811
14811
  kinds[kindId] = validateKindEntry(kindId, entryRaw, source);
14812
14812
  }
14813
- return { version, kinds };
14813
+ const similarity = validateSimilarity(obj["similarity"], source);
14814
+ return similarity !== void 0 ? { version, kinds, similarity } : { version, kinds };
14815
+ }
14816
+ function validateSimilarity(raw, source) {
14817
+ if (raw === void 0 || raw === null) {
14818
+ return void 0;
14819
+ }
14820
+ if (typeof raw !== "object" || Array.isArray(raw)) {
14821
+ throw new Error(`${source}: 'similarity' must be an object`);
14822
+ }
14823
+ const obj = raw;
14824
+ const warnThresholdRaw = obj["warnThreshold"];
14825
+ let warnThreshold = 0.85;
14826
+ if (warnThresholdRaw !== void 0) {
14827
+ if (typeof warnThresholdRaw !== "number" || Number.isNaN(warnThresholdRaw) || warnThresholdRaw < 0 || warnThresholdRaw > 1) {
14828
+ throw new Error(
14829
+ `${source}: 'similarity.warnThreshold' must be a number in [0, 1] (got ${String(warnThresholdRaw)})`
14830
+ );
14831
+ }
14832
+ warnThreshold = warnThresholdRaw;
14833
+ }
14834
+ const modeRaw = obj["mode"];
14835
+ let mode = "warn";
14836
+ if (modeRaw !== void 0) {
14837
+ if (modeRaw !== "warn" && modeRaw !== "block") {
14838
+ throw new Error(
14839
+ `${source}: 'similarity.mode' must be 'warn' or 'block' (got ${String(modeRaw)})`
14840
+ );
14841
+ }
14842
+ mode = modeRaw;
14843
+ }
14844
+ return { warnThreshold, mode };
14814
14845
  }
14815
14846
  function validateKindEntry(kindId, raw, source) {
14816
14847
  const where = `${source} kinds.${kindId}`;
@@ -16168,6 +16199,8 @@ import {
16168
16199
  getCleoDirAbsolute,
16169
16200
  getProjectRoot as getProjectRoot5,
16170
16201
  memoryObserve as memoryObserve2,
16202
+ releaseReservedSlug,
16203
+ reserveSlugForDispatch,
16171
16204
  resolveAttachmentBackend,
16172
16205
  SlugCollisionError
16173
16206
  } from "@cleocode/core/internal";
@@ -16683,6 +16716,25 @@ var init_docs2 = __esm({
16683
16716
  return lafsError("E_SLUG_PATTERN_MISMATCH", `${patternCheck.error}${exampleHint}`, "add");
16684
16717
  }
16685
16718
  }
16719
+ if (slug !== void 0) {
16720
+ const reservation = await reserveSlugForDispatch(getProjectRoot5(), {
16721
+ kind: type2 ?? "",
16722
+ slug
16723
+ });
16724
+ if (!reservation.ok) {
16725
+ return {
16726
+ success: false,
16727
+ error: {
16728
+ code: "E_SLUG_RESERVED",
16729
+ message: `slug '${slug}' is already in use in this project`,
16730
+ details: {
16731
+ suggestions: reservation.suggestions,
16732
+ aliases: ["E_SLUG_TAKEN"]
16733
+ }
16734
+ }
16735
+ };
16736
+ }
16737
+ }
16686
16738
  const extras = {};
16687
16739
  if (slug !== void 0) extras.slug = slug;
16688
16740
  if (type2 !== void 0) extras.type = type2;
@@ -16719,13 +16771,17 @@ var init_docs2 = __esm({
16719
16771
  extras
16720
16772
  );
16721
16773
  } catch (err) {
16774
+ if (slug !== void 0) releaseReservedSlug(slug);
16722
16775
  if (err instanceof SlugCollisionError) {
16723
16776
  return {
16724
16777
  success: false,
16725
16778
  error: {
16726
- code: "E_SLUG_TAKEN",
16779
+ code: "E_SLUG_RESERVED",
16727
16780
  message: `slug '${err.slug}' is already in use in this project`,
16728
- details: { suggestions: err.suggestions }
16781
+ details: {
16782
+ suggestions: err.suggestions,
16783
+ aliases: ["E_SLUG_TAKEN"]
16784
+ }
16729
16785
  }
16730
16786
  };
16731
16787
  }
@@ -16797,13 +16853,17 @@ var init_docs2 = __esm({
16797
16853
  extras
16798
16854
  );
16799
16855
  } catch (err) {
16856
+ if (slug !== void 0) releaseReservedSlug(slug);
16800
16857
  if (err instanceof SlugCollisionError) {
16801
16858
  return {
16802
16859
  success: false,
16803
16860
  error: {
16804
- code: "E_SLUG_TAKEN",
16861
+ code: "E_SLUG_RESERVED",
16805
16862
  message: `slug '${err.slug}' is already in use in this project`,
16806
- details: { suggestions: err.suggestions }
16863
+ details: {
16864
+ suggestions: err.suggestions,
16865
+ aliases: ["E_SLUG_TAKEN"]
16866
+ }
16807
16867
  }
16808
16868
  };
16809
16869
  }
@@ -16969,6 +17029,7 @@ import {
16969
17029
  createAttachmentStore as createAttachmentStore2,
16970
17030
  memoryFind as memoryFind2,
16971
17031
  orchestrateReady as orchestrateReady2,
17032
+ sagas,
16972
17033
  taskRelates as taskRelates2,
16973
17034
  taskShow as taskShow2
16974
17035
  } from "@cleocode/core/internal";
@@ -17070,8 +17131,7 @@ async function buildFocusEnvelope(id, projectRoot) {
17070
17131
  };
17071
17132
  }
17072
17133
  const task = showResult.data.task;
17073
- const labels = Array.isArray(task.labels) ? task.labels : [];
17074
- const isSaga = labels.includes("saga");
17134
+ const isSaga = sagas.isSagaType(task);
17075
17135
  const isEpic = task.type === "epic" && !isSaga;
17076
17136
  const entityType = isSaga ? "saga" : isEpic ? "epic" : "task";
17077
17137
  const identity = {
@@ -25211,8 +25271,8 @@ async function loadPlaybookByName(name) {
25211
25271
  return null;
25212
25272
  }
25213
25273
  try {
25214
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core/internal");
25215
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot46();
25274
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25275
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot48();
25216
25276
  const resolved = resolvePlaybook(name, {
25217
25277
  projectRoot,
25218
25278
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -25256,8 +25316,8 @@ async function acquireDb() {
25256
25316
  async function buildDefaultDispatcher() {
25257
25317
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
25258
25318
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
25259
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core/internal");
25260
- const projectRoot = getProjectRoot46();
25319
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25320
+ const projectRoot = getProjectRoot48();
25261
25321
  return {
25262
25322
  async dispatch(input2) {
25263
25323
  try {
@@ -25447,8 +25507,8 @@ var init_playbook2 = __esm({
25447
25507
  projectRoot = __playbookRuntimeOverrides.projectRoot;
25448
25508
  } else {
25449
25509
  try {
25450
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core/internal");
25451
- projectRoot = getProjectRoot46();
25510
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25511
+ projectRoot = getProjectRoot48();
25452
25512
  } catch {
25453
25513
  projectRoot = void 0;
25454
25514
  }
@@ -25512,14 +25572,14 @@ var init_playbook2 = __esm({
25512
25572
  const dispatcher = await buildDefaultDispatcher();
25513
25573
  let result;
25514
25574
  try {
25515
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core/internal");
25575
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25516
25576
  const opts = {
25517
25577
  db,
25518
25578
  playbook: parsed.definition,
25519
25579
  playbookHash: parsed.sourceHash,
25520
25580
  initialContext,
25521
25581
  dispatcher,
25522
- projectRoot: getProjectRoot46()
25582
+ projectRoot: getProjectRoot48()
25523
25583
  };
25524
25584
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
25525
25585
  opts.approvalSecret = __playbookRuntimeOverrides.approvalSecret;
@@ -25884,7 +25944,7 @@ async function orchestrateClassify(request, context, projectRoot) {
25884
25944
  try {
25885
25945
  const { getCleoCantWorkflowsDir } = await import("@cleocode/core/internal");
25886
25946
  const { readFileSync: readFileSync18, readdirSync: readdirSync3, existsSync: existsSync17 } = await import("node:fs");
25887
- const { join: join35 } = await import("node:path");
25947
+ const { join: join34 } = await import("node:path");
25888
25948
  const workflowsDir = getCleoCantWorkflowsDir();
25889
25949
  const combined = `${request} ${context ?? ""}`.toLowerCase();
25890
25950
  const matches = [];
@@ -25892,7 +25952,7 @@ async function orchestrateClassify(request, context, projectRoot) {
25892
25952
  const files = readdirSync3(workflowsDir).filter((f) => f.endsWith(".cant"));
25893
25953
  for (const file of files) {
25894
25954
  try {
25895
- const src = readFileSync18(join35(workflowsDir, file), "utf-8");
25955
+ const src = readFileSync18(join34(workflowsDir, file), "utf-8");
25896
25956
  const teamMatch = /^team\s+(\S+):/m.exec(src);
25897
25957
  if (!teamMatch) continue;
25898
25958
  const teamName = teamMatch[1];
@@ -25907,12 +25967,12 @@ async function orchestrateClassify(request, context, projectRoot) {
25907
25967
  }
25908
25968
  }
25909
25969
  }
25910
- const localCantDir = join35(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
25970
+ const localCantDir = join34(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
25911
25971
  if (existsSync17(localCantDir)) {
25912
25972
  const files = readdirSync3(localCantDir).filter((f) => f.endsWith(".cant"));
25913
25973
  for (const file of files) {
25914
25974
  try {
25915
- const src = readFileSync18(join35(localCantDir, file), "utf-8");
25975
+ const src = readFileSync18(join34(localCantDir, file), "utf-8");
25916
25976
  const teamMatch = /^team\s+(\S+):/m.exec(src);
25917
25977
  if (!teamMatch) continue;
25918
25978
  const teamName = teamMatch[1];
@@ -31307,11 +31367,11 @@ var init_security = __esm({
31307
31367
  });
31308
31368
 
31309
31369
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
31310
- function createSanitizer(getProjectRoot46) {
31370
+ function createSanitizer(getProjectRoot48) {
31311
31371
  return async (req, next) => {
31312
31372
  if (req.params) {
31313
31373
  try {
31314
- const root = getProjectRoot46 ? getProjectRoot46() : void 0;
31374
+ const root = getProjectRoot48 ? getProjectRoot48() : void 0;
31315
31375
  req.params = sanitizeParams(req.params, root, {
31316
31376
  domain: req.domain,
31317
31377
  operation: req.operation
@@ -32903,9 +32963,9 @@ var init_agent = __esm({
32903
32963
  isActive: true
32904
32964
  });
32905
32965
  const { existsSync: existsSync17, mkdirSync: mkdirSync5, writeFileSync: writeFileSync5 } = await import("node:fs");
32906
- const { join: join35 } = await import("node:path");
32907
- const cantDir = join35(CLEO_DIR_NAME, AGENTS_SUBDIR);
32908
- const cantPath = join35(cantDir, `${agentId}.cant`);
32966
+ const { join: join34 } = await import("node:path");
32967
+ const cantDir = join34(CLEO_DIR_NAME, AGENTS_SUBDIR);
32968
+ const cantPath = join34(cantDir, `${agentId}.cant`);
32909
32969
  let cantScaffolded = false;
32910
32970
  if (!existsSync17(cantPath)) {
32911
32971
  mkdirSync5(cantDir, { recursive: true });
@@ -33087,7 +33147,7 @@ agent ${agentId}:
33087
33147
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
33088
33148
  const { createRuntime } = await import("@cleocode/runtime");
33089
33149
  const { existsSync: existsSync17, readFileSync: readFileSync18 } = await import("node:fs");
33090
- const { join: join35 } = await import("node:path");
33150
+ const { join: join34 } = await import("node:path");
33091
33151
  await openCleoDb("tasks");
33092
33152
  const registry = new AgentRegistryAccessor(getProjectRoot24());
33093
33153
  const credential = await registry.get(args.agentId);
@@ -33107,7 +33167,7 @@ agent ${agentId}:
33107
33167
  }
33108
33168
  let profile = null;
33109
33169
  let cantValidation = null;
33110
- const cantPath = args.cant ?? join35(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33170
+ const cantPath = args.cant ?? join34(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33111
33171
  if (existsSync17(cantPath)) {
33112
33172
  profile = readFileSync18(cantPath, "utf-8");
33113
33173
  try {
@@ -33633,7 +33693,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33633
33693
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
33634
33694
  const { createRuntime } = await import("@cleocode/runtime");
33635
33695
  const { existsSync: existsSync17 } = await import("node:fs");
33636
- const { join: join35 } = await import("node:path");
33696
+ const { join: join34 } = await import("node:path");
33637
33697
  await openCleoDb("tasks");
33638
33698
  const registry = new AgentRegistryAccessor(getProjectRoot24());
33639
33699
  const credential = await registry.get(args.agentId);
@@ -33650,7 +33710,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33650
33710
  }
33651
33711
  await registry.update(args.agentId, { isActive: true });
33652
33712
  await registry.markUsed(args.agentId);
33653
- const cantPath = join35(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33713
+ const cantPath = join34(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33654
33714
  const hasProfile = existsSync17(cantPath);
33655
33715
  const runtime = await createRuntime(registry, {
33656
33716
  agentId: args.agentId,
@@ -34593,8 +34653,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34593
34653
  process.exitCode = 4;
34594
34654
  return;
34595
34655
  }
34596
- const { join: join35 } = await import("node:path");
34597
- const personaPath = join35(resolvedDir, "persona.cant");
34656
+ const { join: join34 } = await import("node:path");
34657
+ const personaPath = join34(resolvedDir, "persona.cant");
34598
34658
  if (!existsSync17(personaPath)) {
34599
34659
  cliOutput(
34600
34660
  {
@@ -34642,7 +34702,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34642
34702
  if (entry.isFile()) {
34643
34703
  fileCount++;
34644
34704
  } else if (entry.isDirectory()) {
34645
- countFiles(join35(dirPath, entry.name));
34705
+ countFiles(join34(dirPath, entry.name));
34646
34706
  }
34647
34707
  }
34648
34708
  };
@@ -34891,7 +34951,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34891
34951
  async run({ args }) {
34892
34952
  try {
34893
34953
  const { existsSync: existsSync17, readFileSync: readFileSync18, mkdirSync: mkdirSync5 } = await import("node:fs");
34894
- const { resolve: resolve7, join: join35 } = await import("node:path");
34954
+ const { resolve: resolve7, join: join34 } = await import("node:path");
34895
34955
  const specPath = resolve7(args.spec);
34896
34956
  if (!existsSync17(specPath)) {
34897
34957
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
@@ -34900,7 +34960,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34900
34960
  }
34901
34961
  const specContent = readFileSync18(specPath, "utf-8");
34902
34962
  const projectRoot = getProjectRoot24();
34903
- const outputDir = args["output-dir"] ? resolve7(args["output-dir"]) : join35(projectRoot, ".cleo", "cant", "agents");
34963
+ const outputDir = args["output-dir"] ? resolve7(args["output-dir"]) : join34(projectRoot, ".cleo", "cant", "agents");
34904
34964
  mkdirSync5(outputDir, { recursive: true });
34905
34965
  if (args["dry-run"]) {
34906
34966
  cliOutput(
@@ -36311,12 +36371,8 @@ __export(backup_recover_exports, {
36311
36371
  backupRecoverBrainLeaf: () => backupRecoverBrainLeaf,
36312
36372
  backupRecoverSubCommand: () => backupRecoverSubCommand
36313
36373
  });
36314
- import { join as join11 } from "node:path";
36315
- import { getCleoDirAbsolute as getCleoDirAbsolute2, getLogger as getLogger20, getProjectRoot as getProjectRoot27 } from "@cleocode/core";
36316
- import {
36317
- BackupRecoverBrainError,
36318
- runBackupRecoverBrain
36319
- } from "@cleocode/core/store/backup-recover-brain.js";
36374
+ import { getLogger as getLogger20, getProjectRoot as getProjectRoot27 } from "@cleocode/core";
36375
+ import { BackupRecoverError, runBackupRecover } from "@cleocode/core/store/backup-recover.js";
36320
36376
  function readBoolFlag(args, key) {
36321
36377
  return args[key] === true;
36322
36378
  }
@@ -36324,6 +36380,68 @@ function readStringFlag(args, key) {
36324
36380
  const v = args[key];
36325
36381
  return typeof v === "string" ? v : "";
36326
36382
  }
36383
+ function executeRecover(role, args) {
36384
+ const projectRoot = getProjectRoot27();
36385
+ const dryRun = readBoolFlag(args, "dry-run");
36386
+ const fromSnapshot = readStringFlag(args, "from-snapshot");
36387
+ const noDelta = readBoolFlag(args, "no-delta");
36388
+ const operation = `backup.recover.${role}`;
36389
+ try {
36390
+ const result = runBackupRecover({
36391
+ role,
36392
+ projectRoot,
36393
+ logger: getLogger20(`backup-recover-${role}`),
36394
+ dryRun,
36395
+ fromSnapshot: fromSnapshot.length > 0 ? fromSnapshot : void 0,
36396
+ noDelta
36397
+ });
36398
+ cliOutput(result, {
36399
+ command: "backup",
36400
+ operation
36401
+ });
36402
+ if (result.dryRun) {
36403
+ humanInfo(
36404
+ `[dry-run] Would restore role "${role}" from ${result.restoredFrom} (${result.dataLossWindowHours !== null ? `~${result.dataLossWindowHours}h data-loss window` : "data-loss window unknown"}). Re-run without --dry-run to execute (project root: ${projectRoot}).`
36405
+ );
36406
+ } else {
36407
+ humanInfo(
36408
+ `Recovered "${role}" DB from ${result.restoredFrom}. Corrupt DB quarantined at ${result.quarantinedTo}.`
36409
+ );
36410
+ }
36411
+ } catch (err) {
36412
+ if (err instanceof BackupRecoverError) {
36413
+ cliError(
36414
+ err.message,
36415
+ err.code,
36416
+ {
36417
+ name: err.codeName,
36418
+ ...err.fix ? { fix: err.fix } : {}
36419
+ },
36420
+ { operation }
36421
+ );
36422
+ process.exitCode = err.code;
36423
+ return;
36424
+ }
36425
+ const message = err instanceof Error ? err.message : String(err);
36426
+ cliError(message, 1 /* GENERAL_ERROR */, { name: "E_RECOVERY_FAILED" }, { operation });
36427
+ process.exitCode = 1 /* GENERAL_ERROR */;
36428
+ }
36429
+ }
36430
+ function parseRoleArg(value) {
36431
+ const trimmed = value.trim();
36432
+ for (const entry of DB_INVENTORY) {
36433
+ if (entry.role === trimmed) {
36434
+ return entry.role;
36435
+ }
36436
+ }
36437
+ const validRoles = DB_INVENTORY.map((e) => e.role).join(", ");
36438
+ throw new BackupRecoverError(
36439
+ `Unknown DB role "${trimmed}". Valid roles: ${validRoles}.`,
36440
+ 6 /* VALIDATION_ERROR */,
36441
+ "E_UNKNOWN_ROLE",
36442
+ "Run `cleo backup recover --help` for the list of valid roles."
36443
+ );
36444
+ }
36327
36445
  var backupRecoverBrainLeaf, backupRecoverSubCommand;
36328
36446
  var init_backup_recover = __esm({
36329
36447
  "packages/cleo/src/cli/commands/backup-recover.ts"() {
@@ -36359,43 +36477,67 @@ var init_backup_recover = __esm({
36359
36477
  }
36360
36478
  },
36361
36479
  async run({ args }) {
36362
- const projectRoot = getProjectRoot27();
36363
- const cleoDir = getCleoDirAbsolute2();
36364
- const corruptPath = join11(cleoDir, "brain.db");
36365
- const snapshotDir = join11(cleoDir, "backups", "snapshot");
36366
- const vacuumSnapshotDir = join11(cleoDir, "backups", "sqlite");
36367
- const quarantineRoot = join11(cleoDir, "quarantine");
36368
36480
  const argsBag = args;
36369
- const dryRun = readBoolFlag(argsBag, "dry-run");
36370
- const fromSnapshot = readStringFlag(argsBag, "from-snapshot");
36371
- const noDelta = readBoolFlag(argsBag, "no-delta");
36481
+ executeRecover("brain", argsBag);
36482
+ }
36483
+ });
36484
+ backupRecoverSubCommand = defineCommand({
36485
+ meta: {
36486
+ name: "recover",
36487
+ description: "Recover a malformed CLEO database from snapshot \u2014 accepts any role from DB_INVENTORY (T10318)"
36488
+ },
36489
+ args: {
36490
+ role: {
36491
+ type: "positional",
36492
+ description: `Canonical DB role (one of: ${DB_INVENTORY.map((e) => e.role).join(", ")})`,
36493
+ required: false
36494
+ },
36495
+ "dry-run": {
36496
+ type: "boolean",
36497
+ description: "Print what would be done without quarantining or copying any files",
36498
+ default: false
36499
+ },
36500
+ "from-snapshot": {
36501
+ type: "string",
36502
+ description: "Pin recovery to a specific snapshot \u2014 absolute path or ISO timestamp prefix (e.g. 2026-05-23)",
36503
+ default: ""
36504
+ },
36505
+ "no-delta": {
36506
+ type: "boolean",
36507
+ description: "Skip the sqlite3 .recover delta-merge step (reserved \u2014 current pipeline does not delta-merge; flag plumbed for forward-compat)",
36508
+ default: false
36509
+ },
36510
+ force: {
36511
+ type: "boolean",
36512
+ description: "Bypass any safety prompts (currently a no-op; reserved)",
36513
+ default: false
36514
+ }
36515
+ },
36516
+ subCommands: {
36517
+ brain: backupRecoverBrainLeaf
36518
+ },
36519
+ async run({ args }) {
36520
+ const argsBag = args;
36521
+ const roleArg = readStringFlag(argsBag, "role");
36522
+ if (roleArg.length === 0) {
36523
+ const validRoles = DB_INVENTORY.map((e) => e.role).join(", ");
36524
+ cliError(
36525
+ `Missing role. Try \`cleo backup recover <role>\` (one of: ${validRoles}).`,
36526
+ 6 /* VALIDATION_ERROR */,
36527
+ {
36528
+ name: "E_VALIDATION",
36529
+ fix: "Run `cleo backup recover --help` to see available roles and flags."
36530
+ },
36531
+ { operation: "backup.recover" }
36532
+ );
36533
+ process.exitCode = 6 /* VALIDATION_ERROR */;
36534
+ return;
36535
+ }
36536
+ let role;
36372
36537
  try {
36373
- const result = runBackupRecoverBrain({
36374
- corruptPath,
36375
- snapshotDir,
36376
- vacuumSnapshotDir,
36377
- legacyArtifactDir: cleoDir,
36378
- quarantineRoot,
36379
- logger: getLogger20("backup-recover-brain"),
36380
- dryRun,
36381
- fromSnapshot: fromSnapshot.length > 0 ? fromSnapshot : void 0,
36382
- noDelta
36383
- });
36384
- cliOutput(result, {
36385
- command: "backup",
36386
- operation: "backup.recover.brain"
36387
- });
36388
- if (result.dryRun) {
36389
- humanInfo(
36390
- `[dry-run] Would restore from ${result.restoredFrom} (${result.dataLossWindowHours !== null ? `~${result.dataLossWindowHours}h data-loss window` : "data-loss window unknown"}). Re-run without --dry-run to execute (project root: ${projectRoot}).`
36391
- );
36392
- } else {
36393
- humanInfo(
36394
- `Recovered brain.db from ${result.restoredFrom}. Corrupt DB quarantined at ${result.quarantinedTo}.`
36395
- );
36396
- }
36538
+ role = parseRoleArg(roleArg);
36397
36539
  } catch (err) {
36398
- if (err instanceof BackupRecoverBrainError) {
36540
+ if (err instanceof BackupRecoverError) {
36399
36541
  cliError(
36400
36542
  err.message,
36401
36543
  err.code,
@@ -36403,44 +36545,89 @@ var init_backup_recover = __esm({
36403
36545
  name: err.codeName,
36404
36546
  ...err.fix ? { fix: err.fix } : {}
36405
36547
  },
36406
- { operation: "backup.recover.brain" }
36548
+ { operation: "backup.recover" }
36407
36549
  );
36408
36550
  process.exitCode = err.code;
36409
36551
  return;
36410
36552
  }
36411
- const message = err instanceof Error ? err.message : String(err);
36412
- cliError(
36413
- message,
36414
- 1 /* GENERAL_ERROR */,
36415
- { name: "E_RECOVERY_FAILED" },
36416
- { operation: "backup.recover.brain" }
36417
- );
36418
- process.exitCode = 1 /* GENERAL_ERROR */;
36553
+ throw err;
36419
36554
  }
36555
+ executeRecover(role, argsBag);
36420
36556
  }
36421
36557
  });
36422
- backupRecoverSubCommand = defineCommand({
36558
+ }
36559
+ });
36560
+
36561
+ // packages/cleo/src/cli/commands/backup-verify.ts
36562
+ import { getProjectRoot as getProjectRoot28 } from "@cleocode/core";
36563
+ import { runBackupVerify } from "@cleocode/core/store/backup-verify.js";
36564
+ var backupVerifySubCommand;
36565
+ var init_backup_verify = __esm({
36566
+ "packages/cleo/src/cli/commands/backup-verify.ts"() {
36567
+ "use strict";
36568
+ init_src2();
36569
+ init_define_cli_command();
36570
+ init_renderers();
36571
+ backupVerifySubCommand = defineCommand({
36423
36572
  meta: {
36424
- name: "recover",
36425
- description: "Recover a malformed CLEO database from snapshot"
36573
+ name: "verify",
36574
+ description: "Walk DB_INVENTORY and report per-DB freshness + integrity for each snapshot in BOTH .cleo/backups/sqlite/ (canonical) and .cleo/backups/snapshot/ (legacy). Exits non-zero on any stale/corrupt finding."
36426
36575
  },
36427
- subCommands: {
36428
- brain: backupRecoverBrainLeaf
36576
+ args: {
36577
+ "per-db-timeout-ms": {
36578
+ type: "string",
36579
+ description: "Per-DB integrity-check timeout in milliseconds (default: 30000).",
36580
+ default: "30000"
36581
+ },
36582
+ json: { type: "boolean", description: "Output as JSON" },
36583
+ human: { type: "boolean", description: "Force human-readable output" },
36584
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
36429
36585
  },
36430
36586
  async run({ args }) {
36431
36587
  const argsBag = args;
36432
- const positional = argsBag["_"];
36433
- if (Array.isArray(positional) && positional.length > 0) return;
36434
- cliError(
36435
- "Missing subcommand. Try `cleo backup recover brain` (currently the only available recovery verb).",
36436
- 6 /* VALIDATION_ERROR */,
36437
- {
36438
- name: "E_VALIDATION",
36439
- fix: "Run `cleo backup recover brain --help` to see available flags."
36440
- },
36441
- { operation: "backup.recover" }
36442
- );
36443
- process.exitCode = 6 /* VALIDATION_ERROR */;
36588
+ const rawTimeout = argsBag["per-db-timeout-ms"];
36589
+ let perDbTimeoutMs = 3e4;
36590
+ if (typeof rawTimeout === "string" && rawTimeout.length > 0) {
36591
+ const parsed = Number.parseInt(rawTimeout, 10);
36592
+ if (!Number.isFinite(parsed) || parsed <= 0) {
36593
+ cliError(
36594
+ `Invalid --per-db-timeout-ms value: ${rawTimeout}`,
36595
+ 6 /* VALIDATION_ERROR */,
36596
+ {
36597
+ name: "E_VALIDATION",
36598
+ fix: "Provide a positive integer number of milliseconds (e.g. --per-db-timeout-ms 30000)."
36599
+ },
36600
+ { operation: "backup.verify" }
36601
+ );
36602
+ process.exitCode = 6 /* VALIDATION_ERROR */;
36603
+ return;
36604
+ }
36605
+ perDbTimeoutMs = parsed;
36606
+ }
36607
+ let result;
36608
+ try {
36609
+ result = runBackupVerify({
36610
+ projectRoot: getProjectRoot28(),
36611
+ perDbTimeoutMs
36612
+ });
36613
+ } catch (err) {
36614
+ const message = err instanceof Error ? err.message : String(err);
36615
+ cliError(
36616
+ message,
36617
+ 1 /* GENERAL_ERROR */,
36618
+ { name: "E_BACKUP_VERIFY_FAILED" },
36619
+ { operation: "backup.verify" }
36620
+ );
36621
+ process.exitCode = 1 /* GENERAL_ERROR */;
36622
+ return;
36623
+ }
36624
+ cliOutput(result, {
36625
+ command: "backup",
36626
+ operation: "backup.verify"
36627
+ });
36628
+ if ((result.summary.corrupt > 0 || result.summary.stale > 0) && (process.exitCode === void 0 || process.exitCode === 0)) {
36629
+ process.exitCode = 1 /* GENERAL_ERROR */;
36630
+ }
36444
36631
  }
36445
36632
  });
36446
36633
  }
@@ -36518,6 +36705,7 @@ var init_backup = __esm({
36518
36705
  init_renderers();
36519
36706
  init_backup_inspect();
36520
36707
  init_backup_recover();
36708
+ init_backup_verify();
36521
36709
  addCommand2 = defineCommand({
36522
36710
  meta: {
36523
36711
  name: "add",
@@ -36601,9 +36789,9 @@ var init_backup = __esm({
36601
36789
  async run({ args }) {
36602
36790
  const scope = args.scope;
36603
36791
  const { packBundle } = await import("@cleocode/core/store/backup-pack.js");
36604
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core");
36792
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core");
36605
36793
  const includesProject = scope === "project" || scope === "all";
36606
- const projectRoot = includesProject ? getProjectRoot46() : void 0;
36794
+ const projectRoot = includesProject ? getProjectRoot48() : void 0;
36607
36795
  let passphrase;
36608
36796
  if (args.encrypt === true) {
36609
36797
  passphrase = process.env["CLEO_BACKUP_PASSPHRASE"];
@@ -36679,12 +36867,12 @@ var init_backup = __esm({
36679
36867
  },
36680
36868
  async run({ args }) {
36681
36869
  const bundlePath = args.bundle;
36682
- const { getProjectRoot: getProjectRoot46, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
36870
+ const { getProjectRoot: getProjectRoot48, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
36683
36871
  const { BundleError, cleanupStaging, unpackBundle } = await import("@cleocode/core/store/backup-unpack.js");
36684
36872
  const { regenerateConfigJson, regenerateProjectContextJson, regenerateProjectInfoJson } = await import("@cleocode/core/store/regenerators.js");
36685
36873
  const { regenerateAndCompare } = await import("@cleocode/core/store/restore-json-merge.js");
36686
36874
  const { buildConflictReport, writeConflictReport } = await import("@cleocode/core/store/restore-conflict-report.js");
36687
- const projectRoot = getProjectRoot46();
36875
+ const projectRoot = getProjectRoot48();
36688
36876
  if (args.force !== true) {
36689
36877
  const existing = checkForExistingData(projectRoot, getCleoHome6());
36690
36878
  if (existing.length > 0) {
@@ -36853,7 +37041,8 @@ var init_backup = __esm({
36853
37041
  export: exportCommand,
36854
37042
  import: importCommand,
36855
37043
  inspect: backupInspectSubCommand,
36856
- recover: backupRecoverSubCommand
37044
+ recover: backupRecoverSubCommand,
37045
+ verify: backupVerifySubCommand
36857
37046
  },
36858
37047
  async run({ cmd, rawArgs }) {
36859
37048
  if (isSubCommandDispatch(rawArgs, cmd.subCommands)) return;
@@ -36903,7 +37092,7 @@ var brain_exports = {};
36903
37092
  __export(brain_exports, {
36904
37093
  brainCommand: () => brainCommand
36905
37094
  });
36906
- import { getProjectRoot as getProjectRoot28 } from "@cleocode/core";
37095
+ import { getProjectRoot as getProjectRoot29 } from "@cleocode/core";
36907
37096
  import {
36908
37097
  backfillBrainGraph,
36909
37098
  exportBrainAsGexf,
@@ -36948,7 +37137,7 @@ var init_brain2 = __esm({
36948
37137
  json: { type: "boolean", description: "Output results as JSON" }
36949
37138
  },
36950
37139
  async run({ args }) {
36951
- const root = getProjectRoot28();
37140
+ const root = getProjectRoot29();
36952
37141
  try {
36953
37142
  const result = await runBrainMaintenance(root, {
36954
37143
  skipDecay: !!args["skip-decay"],
@@ -37019,7 +37208,7 @@ var init_brain2 = __esm({
37019
37208
  json: { type: "boolean", description: "Output results as JSON" }
37020
37209
  },
37021
37210
  async run({ args: _args }) {
37022
- const root = getProjectRoot28();
37211
+ const root = getProjectRoot29();
37023
37212
  try {
37024
37213
  const result = await backfillBrainGraph(root);
37025
37214
  cliOutput(
@@ -37060,7 +37249,7 @@ var init_brain2 = __esm({
37060
37249
  json: { type: "boolean", description: "Output results as JSON" }
37061
37250
  },
37062
37251
  async run({ args: _args }) {
37063
- const root = getProjectRoot28();
37252
+ const root = getProjectRoot29();
37064
37253
  try {
37065
37254
  const result = await purgeBrainNoise(root);
37066
37255
  cliOutput(
@@ -37106,7 +37295,7 @@ var init_brain2 = __esm({
37106
37295
  json: { type: "boolean", description: "Output results as JSON" }
37107
37296
  },
37108
37297
  async run({ args }) {
37109
- const root = getProjectRoot28();
37298
+ const root = getProjectRoot29();
37110
37299
  const limit = Number.parseInt(args.limit, 10) || 20;
37111
37300
  try {
37112
37301
  const stats = await getPlasticityStats(root, limit);
@@ -37156,7 +37345,7 @@ var init_brain2 = __esm({
37156
37345
  json: { type: "boolean", description: "Output results as JSON" }
37157
37346
  },
37158
37347
  async run({ args: _args }) {
37159
- const root = getProjectRoot28();
37348
+ const root = getProjectRoot29();
37160
37349
  try {
37161
37350
  const report = await getMemoryQualityReport(root);
37162
37351
  cliOutput(
@@ -37205,7 +37394,7 @@ var init_brain2 = __esm({
37205
37394
  }
37206
37395
  },
37207
37396
  async run({ args }) {
37208
- const root = getProjectRoot28();
37397
+ const root = getProjectRoot29();
37209
37398
  const format = args.format ?? "gexf";
37210
37399
  if (format !== "gexf" && format !== "json") {
37211
37400
  cliError(`Invalid format: ${format}. Use 'gexf' or 'json'.`, "E_VALIDATION", {
@@ -37286,12 +37475,12 @@ __export(briefing_exports, {
37286
37475
  briefingCommand: () => briefingCommand
37287
37476
  });
37288
37477
  import { existsSync as existsSync9, readFileSync as readFileSync10 } from "node:fs";
37289
- import { join as join12 } from "node:path";
37478
+ import { join as join11 } from "node:path";
37290
37479
  import { pushWarning } from "@cleocode/core";
37291
37480
  import { resolveLegacyCleoDir } from "@cleocode/paths";
37292
37481
  function resolveInjectionTemplatePath() {
37293
37482
  const xdgConfig = resolveLegacyCleoDir(process.env["XDG_CONFIG_HOME"]);
37294
- return join12(xdgConfig, "templates", "CLEO-INJECTION.md");
37483
+ return join11(xdgConfig, "templates", "CLEO-INJECTION.md");
37295
37484
  }
37296
37485
  function extractSection(content, sectionName) {
37297
37486
  const openTag = `<!-- CLEO-INJECTION:section=${sectionName} -->`;
@@ -37530,7 +37719,7 @@ __export(caamp_exports, {
37530
37719
  caampCommand: () => caampCommand
37531
37720
  });
37532
37721
  import { homedir as homedir3 } from "node:os";
37533
- import { join as join13 } from "node:path";
37722
+ import { join as join12 } from "node:path";
37534
37723
  var dedupeCommand, caampCommand;
37535
37724
  var init_caamp = __esm({
37536
37725
  "packages/cleo/src/cli/commands/caamp.ts"() {
@@ -37567,9 +37756,9 @@ var init_caamp = __esm({
37567
37756
  } else {
37568
37757
  const home = homedir3();
37569
37758
  filePaths = [
37570
- join13(home, ".agents", "AGENTS.md"),
37759
+ join12(home, ".agents", "AGENTS.md"),
37571
37760
  // project-level AGENTS.md in cwd
37572
- join13(process.cwd(), "AGENTS.md")
37761
+ join12(process.cwd(), "AGENTS.md")
37573
37762
  ];
37574
37763
  }
37575
37764
  if (args["dry-run"]) {
@@ -37677,7 +37866,7 @@ __export(cant_exports, {
37677
37866
  cantCommand: () => cantCommand
37678
37867
  });
37679
37868
  import { existsSync as existsSync10, mkdirSync as mkdirSync2, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "node:fs";
37680
- import { dirname as dirname4, isAbsolute, join as join14, resolve as resolve3 } from "node:path";
37869
+ import { dirname as dirname4, isAbsolute, join as join13, resolve as resolve3 } from "node:path";
37681
37870
  function resolveFilePath(file) {
37682
37871
  return isAbsolute(file) ? file : resolve3(process.cwd(), file);
37683
37872
  }
@@ -37842,7 +38031,7 @@ var init_cant = __esm({
37842
38031
  const projectRoot = process.cwd();
37843
38032
  let written = 0;
37844
38033
  for (const outputFile of result.outputFiles) {
37845
- const outputPath = isAbsolute(outputFile.path) ? outputFile.path : join14(projectRoot, outputFile.path);
38034
+ const outputPath = isAbsolute(outputFile.path) ? outputFile.path : join13(projectRoot, outputFile.path);
37846
38035
  mkdirSync2(dirname4(outputPath), { recursive: true });
37847
38036
  writeFileSync3(outputPath, outputFile.content, "utf-8");
37848
38037
  written++;
@@ -38022,8 +38211,14 @@ __export(changeset_exports, {
38022
38211
  changesetCommand: () => changesetCommand
38023
38212
  });
38024
38213
  import { existsSync as existsSync11 } from "node:fs";
38025
- import { join as join15 } from "node:path";
38026
- import { changesets, dataTable, getProjectRoot as getProjectRoot29 } from "@cleocode/core";
38214
+ import { join as join14 } from "node:path";
38215
+ import {
38216
+ changesets,
38217
+ dataTable,
38218
+ detectStrayCleoDb,
38219
+ getProjectRoot as getProjectRoot30,
38220
+ resolveWorktreeRouting
38221
+ } from "@cleocode/core";
38027
38222
  function isValidKind(raw) {
38028
38223
  return typeof raw === "string" && CHANGESET_KINDS.includes(raw);
38029
38224
  }
@@ -38117,7 +38312,25 @@ var init_changeset = __esm({
38117
38312
  ...typeof args.notes === "string" && args.notes.length > 0 ? { notes: args.notes } : {},
38118
38313
  ...typeof args.breaking === "string" && args.breaking.length > 0 ? { breaking: args.breaking } : {}
38119
38314
  };
38120
- const projectRoot = getProjectRoot29();
38315
+ const routing = resolveWorktreeRouting();
38316
+ const strayDb = detectStrayCleoDb(routing);
38317
+ if (strayDb) {
38318
+ cliError(
38319
+ `stray .cleo/tasks.db detected inside worktree at ${routing.worktreePath}. This is a leaked CLEO state directory.`,
38320
+ 6 /* VALIDATION_ERROR */,
38321
+ {
38322
+ name: "E_STRAY_WORKTREE_DB",
38323
+ fix: `Remove it with: rm -rf ${routing.worktreePath}/.cleo \u2014 then retry. See ADR-068 \xA73 for the worktree DB isolation rationale.`
38324
+ }
38325
+ );
38326
+ process.exit(6 /* VALIDATION_ERROR */);
38327
+ }
38328
+ if (routing.isWorktree && process.env["CLEO_QUIET"] !== "1") {
38329
+ const routingLog = `[T10389] routing SSoT write from worktree cwd ${routing.cwd} \u2192 canonical project root ${routing.canonicalRoot}
38330
+ `;
38331
+ process.stderr.write(routingLog);
38332
+ }
38333
+ const projectRoot = routing.canonicalRoot;
38121
38334
  const outcome = await changesets.writeChangesetEntry(entry, {
38122
38335
  projectRoot,
38123
38336
  ...typeof args["attached-by"] === "string" && args["attached-by"].length > 0 ? { attachedBy: args["attached-by"] } : {}
@@ -38144,8 +38357,8 @@ var init_changeset = __esm({
38144
38357
  },
38145
38358
  args: {},
38146
38359
  async run() {
38147
- const projectRoot = getProjectRoot29();
38148
- const dir = join15(projectRoot, ".changeset");
38360
+ const projectRoot = getProjectRoot30();
38361
+ const dir = join14(projectRoot, ".changeset");
38149
38362
  if (!existsSync11(dir)) {
38150
38363
  const empty = { entries: [], count: 0, dir, note: "no .changeset/ dir" };
38151
38364
  if (isHumanOutput()) {
@@ -38610,7 +38823,7 @@ var init_check2 = __esm({
38610
38823
  async run({ args }) {
38611
38824
  const { spawnSync } = await import("node:child_process");
38612
38825
  const { existsSync: existsSync17 } = await import("node:fs");
38613
- const { join: join35, resolve: resolve7 } = await import("node:path");
38826
+ const { join: join34, resolve: resolve7 } = await import("node:path");
38614
38827
  const strict = Boolean(args.strict);
38615
38828
  const jsonOnly = Boolean(args.json);
38616
38829
  const repoRoot = resolve7(process.cwd());
@@ -38650,7 +38863,7 @@ var init_check2 = __esm({
38650
38863
  const results = [];
38651
38864
  let anyFailed = false;
38652
38865
  for (const gate of gates) {
38653
- const scriptPath = join35(repoRoot, gate.script);
38866
+ const scriptPath = join34(repoRoot, gate.script);
38654
38867
  if (!existsSync17(scriptPath)) {
38655
38868
  results.push({
38656
38869
  id: gate.id,
@@ -38966,9 +39179,9 @@ var init_code = __esm({
38966
39179
  async run({ args }) {
38967
39180
  await requireTreeSitter();
38968
39181
  const { smartOutline } = await import("@cleocode/core/internal");
38969
- const { join: join35 } = await import("node:path");
39182
+ const { join: join34 } = await import("node:path");
38970
39183
  const root = process.cwd();
38971
- const absPath = args.file.startsWith("/") ? args.file : join35(root, args.file);
39184
+ const absPath = args.file.startsWith("/") ? args.file : join34(root, args.file);
38972
39185
  const result = smartOutline(absPath, root);
38973
39186
  if (result.errors.length > 0 && result.symbols.length === 0) {
38974
39187
  cliError(result.errors.join(", "), 1, { name: "E_OUTLINE_FAILED" });
@@ -39059,9 +39272,9 @@ var init_code = __esm({
39059
39272
  async run({ args }) {
39060
39273
  await requireTreeSitter();
39061
39274
  const { smartUnfold } = await import("@cleocode/core/internal");
39062
- const { join: join35 } = await import("node:path");
39275
+ const { join: join34 } = await import("node:path");
39063
39276
  const root = process.cwd();
39064
- const absPath = args.file.startsWith("/") ? args.file : join35(root, args.file);
39277
+ const absPath = args.file.startsWith("/") ? args.file : join34(root, args.file);
39065
39278
  const result = smartUnfold(absPath, args.symbol, root);
39066
39279
  if (!result.found) {
39067
39280
  const errs = result.errors.length > 0 ? `: ${result.errors.join(", ")}` : "";
@@ -40184,7 +40397,7 @@ var curator_exports = {};
40184
40397
  __export(curator_exports, {
40185
40398
  curatorCommand: () => curatorCommand
40186
40399
  });
40187
- import { join as join16 } from "node:path";
40400
+ import { join as join15 } from "node:path";
40188
40401
  import { getCleoHome } from "@cleocode/paths";
40189
40402
  async function loadCurator() {
40190
40403
  return import("@cleocode/core/sentient/curator.js");
@@ -40214,7 +40427,7 @@ var init_curator = __esm({
40214
40427
  try {
40215
40428
  const { runCuratorTick } = await loadCurator();
40216
40429
  const { readCuratorConfig } = await loadDaemon();
40217
- const configPath = join16(getCleoHome(), "config.json");
40430
+ const configPath = join15(getCleoHome(), "config.json");
40218
40431
  const cfg = await readCuratorConfig(configPath);
40219
40432
  const result = await runCuratorTick({
40220
40433
  dryRun: args["dry-run"] === true,
@@ -40255,7 +40468,7 @@ var init_curator = __esm({
40255
40468
  async run() {
40256
40469
  try {
40257
40470
  const { readCuratorConfig, curatorCronExpression } = await loadDaemon();
40258
- const configPath = join16(getCleoHome(), "config.json");
40471
+ const configPath = join15(getCleoHome(), "config.json");
40259
40472
  const cfg = await readCuratorConfig(configPath);
40260
40473
  cliOutput(
40261
40474
  {
@@ -40330,7 +40543,7 @@ __export(daemon_exports, {
40330
40543
  daemonCommand: () => daemonCommand
40331
40544
  });
40332
40545
  import { existsSync as existsSync12 } from "node:fs";
40333
- import { join as join17 } from "node:path";
40546
+ import { join as join16 } from "node:path";
40334
40547
  import { fileURLToPath as fileURLToPath3 } from "node:url";
40335
40548
  import { getGCDaemonStatus, spawnGCDaemon, stopGCDaemon } from "@cleocode/core/gc/daemon.js";
40336
40549
  import {
@@ -40396,9 +40609,9 @@ async function showDaemonStatus(cleoDir, projectRoot) {
40396
40609
  }
40397
40610
  function resolveDaemonInstallerScript() {
40398
40611
  const filePath = fileURLToPath3(import.meta.url);
40399
- const candidate1 = join17(filePath, "..", "..", "..", "scripts", "install-daemon-service.mjs");
40612
+ const candidate1 = join16(filePath, "..", "..", "..", "scripts", "install-daemon-service.mjs");
40400
40613
  if (existsSync12(candidate1)) return candidate1;
40401
- const candidate2 = join17(
40614
+ const candidate2 = join16(
40402
40615
  filePath,
40403
40616
  "..",
40404
40617
  "..",
@@ -40470,13 +40683,13 @@ var init_daemon = __esm({
40470
40683
  {
40471
40684
  pid,
40472
40685
  cleoDir,
40473
- logs: join17(cleoDir, "logs", "gc.log"),
40686
+ logs: join16(cleoDir, "logs", "gc.log"),
40474
40687
  message: `GC daemon started (PID ${pid})`
40475
40688
  },
40476
40689
  {
40477
40690
  command: "daemon",
40478
40691
  operation: "daemon.start",
40479
- message: `GC daemon started (PID ${pid}) \u2014 Logs: ${join17(cleoDir, "logs", "gc.log")}`
40692
+ message: `GC daemon started (PID ${pid}) \u2014 Logs: ${join16(cleoDir, "logs", "gc.log")}`
40480
40693
  }
40481
40694
  );
40482
40695
  } catch (err) {
@@ -41247,11 +41460,11 @@ __export(detect_drift_exports, {
41247
41460
  detectDriftCommand: () => detectDriftCommand
41248
41461
  });
41249
41462
  import { existsSync as existsSync13, readdirSync, readFileSync as readFileSync13 } from "node:fs";
41250
- import { dirname as dirname5, join as join18 } from "node:path";
41463
+ import { dirname as dirname5, join as join17 } from "node:path";
41251
41464
  function findProjectRoot() {
41252
41465
  let currentDir = process.cwd();
41253
41466
  while (currentDir !== "/") {
41254
- if (existsSync13(join18(currentDir, "package.json"))) {
41467
+ if (existsSync13(join17(currentDir, "package.json"))) {
41255
41468
  return currentDir;
41256
41469
  }
41257
41470
  const parent = dirname5(currentDir);
@@ -41275,8 +41488,8 @@ var init_detect_drift = __esm({
41275
41488
  },
41276
41489
  async run() {
41277
41490
  const projectRoot = findProjectRoot();
41278
- const isCleoRepo = existsSync13(join18(projectRoot, "packages", "cleo", "src"));
41279
- const cleoSrcRoot = isCleoRepo ? join18(projectRoot, "packages", "cleo", "src") : join18(projectRoot, "src");
41491
+ const isCleoRepo = existsSync13(join17(projectRoot, "packages", "cleo", "src"));
41492
+ const cleoSrcRoot = isCleoRepo ? join17(projectRoot, "packages", "cleo", "src") : join17(projectRoot, "src");
41280
41493
  const safeRead = (filePath) => {
41281
41494
  try {
41282
41495
  return readFileSync13(filePath, "utf-8");
@@ -41290,7 +41503,7 @@ var init_detect_drift = __esm({
41290
41503
  checks: [],
41291
41504
  recommendations: []
41292
41505
  };
41293
- const injPath = join18(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
41506
+ const injPath = join17(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
41294
41507
  if (existsSync13(injPath)) {
41295
41508
  const content = safeRead(injPath);
41296
41509
  userResult.checks.push({
@@ -41342,9 +41555,9 @@ var init_detect_drift = __esm({
41342
41555
  }
41343
41556
  };
41344
41557
  try {
41345
- const specPath = join18(projectRoot, "docs", "specs", "CLEO-OPERATION-CONSTITUTION.md");
41346
- const registryPath = join18(cleoSrcRoot, "dispatch", "registry.ts");
41347
- const dispatchDomainsDir = join18(cleoSrcRoot, "dispatch", "domains");
41558
+ const specPath = join17(projectRoot, "docs", "specs", "CLEO-OPERATION-CONSTITUTION.md");
41559
+ const registryPath = join17(cleoSrcRoot, "dispatch", "registry.ts");
41560
+ const dispatchDomainsDir = join17(cleoSrcRoot, "dispatch", "domains");
41348
41561
  if (!existsSync13(specPath)) {
41349
41562
  addCheck("Gateway-to-spec sync", "fail", "CLEO-OPERATION-CONSTITUTION.md missing", [
41350
41563
  {
@@ -41413,8 +41626,8 @@ var init_detect_drift = __esm({
41413
41626
  ]);
41414
41627
  }
41415
41628
  try {
41416
- const cliDir = join18(cleoSrcRoot, "cli", "commands");
41417
- const coreDir = isCleoRepo ? join18(projectRoot, "packages", "core", "src") : join18(projectRoot, "src", "core");
41629
+ const cliDir = join17(cleoSrcRoot, "cli", "commands");
41630
+ const coreDir = isCleoRepo ? join17(projectRoot, "packages", "core", "src") : join17(projectRoot, "src", "core");
41418
41631
  if (!existsSync13(cliDir)) {
41419
41632
  addCheck("CLI-to-core sync", "fail", "CLI commands directory missing", [
41420
41633
  {
@@ -41441,7 +41654,7 @@ var init_detect_drift = __esm({
41441
41654
  addCheck("CLI-to-core sync", "fail", `Error: ${getErrorMessage(e)}`);
41442
41655
  }
41443
41656
  try {
41444
- const domainsDir = join18(cleoSrcRoot, "dispatch", "domains");
41657
+ const domainsDir = join17(cleoSrcRoot, "dispatch", "domains");
41445
41658
  if (!existsSync13(domainsDir)) {
41446
41659
  addCheck("Domain handler coverage", "fail", "Dispatch domains directory missing", [
41447
41660
  {
@@ -41459,7 +41672,7 @@ var init_detect_drift = __esm({
41459
41672
  addCheck("Domain handler coverage", "fail", `Error: ${getErrorMessage(e)}`);
41460
41673
  }
41461
41674
  try {
41462
- const matrixPath = join18(cleoSrcRoot, "dispatch", "lib", "capability-matrix.ts");
41675
+ const matrixPath = join17(cleoSrcRoot, "dispatch", "lib", "capability-matrix.ts");
41463
41676
  if (!existsSync13(matrixPath)) {
41464
41677
  addCheck("Capability matrix", "fail", "Capability matrix missing", [
41465
41678
  {
@@ -41476,7 +41689,7 @@ var init_detect_drift = __esm({
41476
41689
  addCheck("Capability matrix", "fail", `Error: ${getErrorMessage(e)}`);
41477
41690
  }
41478
41691
  try {
41479
- const schemaPath = join18(projectRoot, "src", "store", "schema.ts");
41692
+ const schemaPath = join17(projectRoot, "src", "store", "schema.ts");
41480
41693
  if (!existsSync13(schemaPath)) {
41481
41694
  addCheck("Schema validation", "fail", "Schema definition missing", [
41482
41695
  {
@@ -41511,8 +41724,8 @@ var init_detect_drift = __esm({
41511
41724
  addCheck("Schema validation", "fail", `Error: ${getErrorMessage(e)}`);
41512
41725
  }
41513
41726
  try {
41514
- const visionPath = join18(projectRoot, "docs", "concepts", "CLEO-VISION.md");
41515
- const specPath = join18(projectRoot, "docs", "specs", "CLEO-PORTABLE-PROJECT-BRAIN-SPEC.md");
41727
+ const visionPath = join17(projectRoot, "docs", "concepts", "CLEO-VISION.md");
41728
+ const specPath = join17(projectRoot, "docs", "specs", "CLEO-PORTABLE-PROJECT-BRAIN-SPEC.md");
41516
41729
  const issues = [];
41517
41730
  if (!existsSync13(visionPath)) {
41518
41731
  issues.push({
@@ -41567,7 +41780,7 @@ var init_detect_drift = __esm({
41567
41780
  addCheck("Canonical identity", "fail", `Error: ${getErrorMessage(e)}`);
41568
41781
  }
41569
41782
  try {
41570
- const injectionPath = join18(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
41783
+ const injectionPath = join17(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
41571
41784
  if (!existsSync13(injectionPath)) {
41572
41785
  addCheck("Agent injection", "fail", "Agent injection template missing", [
41573
41786
  {
@@ -41597,7 +41810,7 @@ var init_detect_drift = __esm({
41597
41810
  addCheck("Agent injection", "fail", `Error: ${getErrorMessage(e)}`);
41598
41811
  }
41599
41812
  try {
41600
- const exitCodesPath = join18(cleoSrcRoot, "dispatch", "lib", "exit-codes.ts");
41813
+ const exitCodesPath = join17(cleoSrcRoot, "dispatch", "lib", "exit-codes.ts");
41601
41814
  if (!existsSync13(exitCodesPath)) {
41602
41815
  addCheck("Exit codes", "fail", "Exit codes definition missing", [
41603
41816
  {
@@ -41946,10 +42159,10 @@ var init_strict_args = __esm({
41946
42159
 
41947
42160
  // packages/cleo/src/viewer/pidfile.ts
41948
42161
  import { mkdir, readFile as readFile2, unlink, writeFile } from "node:fs/promises";
41949
- import { dirname as dirname6, join as join19 } from "node:path";
42162
+ import { dirname as dirname6, join as join18 } from "node:path";
41950
42163
  import { getCleoHome as getCleoHome2 } from "@cleocode/core/internal";
41951
42164
  function viewerPidFilePath() {
41952
- return join19(getCleoHome2(), "viewer.pid");
42165
+ return join18(getCleoHome2(), "viewer.pid");
41953
42166
  }
41954
42167
  async function writeViewerPidFile(record) {
41955
42168
  const path6 = viewerPidFilePath();
@@ -42049,11 +42262,11 @@ var init_port_allocator = __esm({
42049
42262
  // packages/cleo/src/viewer/server.ts
42050
42263
  import { createReadStream } from "node:fs";
42051
42264
  import { stat } from "node:fs/promises";
42052
- import { dirname as dirname7, join as join20, normalize, resolve as resolve4 } from "node:path";
42265
+ import { dirname as dirname7, join as join19, normalize, resolve as resolve4 } from "node:path";
42053
42266
  import { fileURLToPath as fileURLToPath4 } from "node:url";
42054
42267
  import {
42055
42268
  createAttachmentStore as createAttachmentStore5,
42056
- getProjectRoot as getProjectRoot30,
42269
+ getProjectRoot as getProjectRoot31,
42057
42270
  searchAllProjectDocs
42058
42271
  } from "@cleocode/core/internal";
42059
42272
  function getViewerAssetsDir() {
@@ -42088,7 +42301,7 @@ function inferTitle(markdown, fallback) {
42088
42301
  }
42089
42302
  async function serveStatic(res, assetsDir, relPath) {
42090
42303
  const safeRel = normalize(relPath).replace(/^[\\/]+/, "");
42091
- const absPath = join20(assetsDir, safeRel);
42304
+ const absPath = join19(assetsDir, safeRel);
42092
42305
  const resolvedAssets = resolve4(assetsDir) + "/";
42093
42306
  const resolvedAbs = resolve4(absPath);
42094
42307
  if (`${resolvedAbs}/`.indexOf(resolvedAssets) !== 0 && resolvedAbs !== resolve4(assetsDir)) {
@@ -42113,7 +42326,7 @@ async function serveStatic(res, assetsDir, relPath) {
42113
42326
  }
42114
42327
  }
42115
42328
  function buildViewerHandler(opts = {}) {
42116
- const projectRoot = opts.projectRoot ?? getProjectRoot30();
42329
+ const projectRoot = opts.projectRoot ?? getProjectRoot31();
42117
42330
  const assetsDir = getViewerAssetsDir();
42118
42331
  const store = createAttachmentStore5();
42119
42332
  return async (req, res) => {
@@ -42289,12 +42502,12 @@ var init_server = __esm({
42289
42502
  // packages/cleo/src/cli/commands/docs-viewer.ts
42290
42503
  import { spawn } from "node:child_process";
42291
42504
  import { open as fsOpen } from "node:fs/promises";
42292
- import { join as join21 } from "node:path";
42505
+ import { join as join20 } from "node:path";
42293
42506
  import { fileURLToPath as fileURLToPath5 } from "node:url";
42294
- import { getCleoHome as getCleoHome3, getProjectRoot as getProjectRoot31 } from "@cleocode/core";
42507
+ import { getCleoHome as getCleoHome3, getProjectRoot as getProjectRoot32 } from "@cleocode/core";
42295
42508
  function getCleoBinPath() {
42296
42509
  const thisFile = fileURLToPath5(import.meta.url);
42297
- return join21(thisFile, "..", "..", "index.js");
42510
+ return join20(thisFile, "..", "..", "index.js");
42298
42511
  }
42299
42512
  async function waitForExit(pid, timeoutMs, intervalMs = 100) {
42300
42513
  const deadline = Date.now() + timeoutMs;
@@ -42323,7 +42536,7 @@ function openInBrowser(url) {
42323
42536
  }
42324
42537
  }
42325
42538
  async function spawnDetachedServer(opts) {
42326
- const logFile = join21(getCleoHome3(), "viewer.log");
42539
+ const logFile = join20(getCleoHome3(), "viewer.log");
42327
42540
  const handle = await fsOpen(logFile, "a").catch(() => null);
42328
42541
  const stdio = handle ? ["ignore", handle.fd, handle.fd] : ["ignore", "ignore", "ignore"];
42329
42542
  const args = [
@@ -42342,7 +42555,7 @@ async function spawnDetachedServer(opts) {
42342
42555
  detached: true,
42343
42556
  stdio,
42344
42557
  env: { ...process.env, [DETACHED_CHILD_ENV]: "1" },
42345
- cwd: getProjectRoot31()
42558
+ cwd: getProjectRoot32()
42346
42559
  });
42347
42560
  child.unref();
42348
42561
  if (handle) await handle.close();
@@ -42494,7 +42707,7 @@ var init_docs_viewer = __esm({
42494
42707
  pid: process.pid,
42495
42708
  port: handle.port,
42496
42709
  host: handle.host,
42497
- projectRoot: getProjectRoot31(),
42710
+ projectRoot: getProjectRoot32(),
42498
42711
  startedAt: Date.now()
42499
42712
  };
42500
42713
  await writeViewerPidFile(record);
@@ -42770,15 +42983,19 @@ __export(docs_exports, {
42770
42983
  docsCommand: () => docsCommand
42771
42984
  });
42772
42985
  import { appendFile, mkdir as mkdir2, readdir, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
42773
- import { dirname as dirname8, isAbsolute as isAbsolute2, join as join22, resolve as resolve5 } from "node:path";
42986
+ import { dirname as dirname8, isAbsolute as isAbsolute2, join as join21, resolve as resolve5 } from "node:path";
42774
42987
  import {
42775
42988
  buildDocsGraph,
42776
42989
  CleoError as CleoError3,
42777
42990
  CounterMismatchError,
42991
+ checkSlugSimilarity,
42778
42992
  createAttachmentStoreDocsAccessor,
42993
+ DEFAULT_SIMILARITY_MODE,
42994
+ DEFAULT_SIMILARITY_THRESHOLD,
42995
+ detectStrayCleoDb as detectStrayCleoDb2,
42779
42996
  exportDocument,
42780
42997
  getAgentOutputsAbsolute,
42781
- getProjectRoot as getProjectRoot32,
42998
+ getProjectRoot as getProjectRoot33,
42782
42999
  listDocVersions,
42783
43000
  makeClassifierForScanRoot,
42784
43001
  mergeDocs,
@@ -42787,6 +43004,8 @@ import {
42787
43004
  rankDocs,
42788
43005
  readJson,
42789
43006
  recordPublication,
43007
+ resolveWorktreeFilePath,
43008
+ resolveWorktreeRouting as resolveWorktreeRouting2,
42790
43009
  runDocsImport,
42791
43010
  searchAllProjectDocs as searchAllProjectDocs2,
42792
43011
  searchDocs as searchDocs2,
@@ -42794,7 +43013,7 @@ import {
42794
43013
  syncFromGit
42795
43014
  } from "@cleocode/core/internal";
42796
43015
  async function getScriptNames(projectRoot) {
42797
- const scriptsDir = join22(projectRoot, "scripts");
43016
+ const scriptsDir = join21(projectRoot, "scripts");
42798
43017
  try {
42799
43018
  const files = await readdir(scriptsDir);
42800
43019
  return files.filter((f) => f.endsWith(".sh")).map((f) => f.replace(".sh", "")).sort();
@@ -42803,7 +43022,7 @@ async function getScriptNames(projectRoot) {
42803
43022
  }
42804
43023
  }
42805
43024
  async function getIndexedCommands(projectRoot) {
42806
- const indexPath = join22(projectRoot, "docs", "commands", "COMMANDS-INDEX.json");
43025
+ const indexPath = join21(projectRoot, "docs", "commands", "COMMANDS-INDEX.json");
42807
43026
  const index = await readJson(indexPath);
42808
43027
  if (!index) return [];
42809
43028
  return index.commands.map((c) => c.name).sort();
@@ -42836,7 +43055,7 @@ async function runGapCheck(_projectRoot, filterId) {
42836
43055
  const reviewFiles = files.filter((f) => f.endsWith(".md"));
42837
43056
  for (const file of reviewFiles) {
42838
43057
  if (filterId && !file.includes(filterId)) continue;
42839
- const filePath = join22(reviewDir, file);
43058
+ const filePath = join21(reviewDir, file);
42840
43059
  const content = await readFile3(filePath, "utf-8");
42841
43060
  const taskMatch = file.match(/^(T\d+)/);
42842
43061
  const taskId = taskMatch ? taskMatch[1] : "UNKNOWN";
@@ -42887,6 +43106,7 @@ var init_docs3 = __esm({
42887
43106
  init_src2();
42888
43107
  init_dist();
42889
43108
  init_cli();
43109
+ init_canon_docs();
42890
43110
  init_strict_args();
42891
43111
  init_renderers();
42892
43112
  init_docs_viewer();
@@ -42924,11 +43144,15 @@ var init_docs3 = __esm({
42924
43144
  },
42925
43145
  slug: {
42926
43146
  type: "string",
42927
- description: "Human-friendly kebab-case alias for the attachment, unique per project (T9636). Collision returns E_SLUG_TAKEN with 3 alternative suggestions."
43147
+ description: "Human-friendly kebab-case alias for the attachment, unique per project (T9636). Collision returns E_SLUG_RESERVED with 3 alternative suggestions (legacy E_SLUG_TAKEN aliased under details.aliases for one release \u2014 T10386)."
42928
43148
  },
42929
43149
  type: {
42930
43150
  type: "string",
42931
43151
  description: "Taxonomy classification \u2014 run `cleo docs list-types` to enumerate registered kinds (T9637 / T9788)"
43152
+ },
43153
+ "allow-similar": {
43154
+ type: "boolean",
43155
+ description: "Bypass the T10361 slug-similarity check. Use when you really do mean to add a new doc with a near-duplicate slug (e.g. intentional fork). Every bypass is logged to .cleo/audit/similar-bypass.jsonl."
42932
43156
  }
42933
43157
  },
42934
43158
  async run({ args, rawArgs }) {
@@ -42949,6 +43173,7 @@ var init_docs3 = __esm({
42949
43173
  const ownerId = args["owner-id"];
42950
43174
  const fileArg = args.file ?? void 0;
42951
43175
  const url = args.url ?? void 0;
43176
+ const allowSimilar = args["allow-similar"] === true;
42952
43177
  if (!fileArg && !url) {
42953
43178
  cliError("provide a file path (positional argument) or --url <url>", 6, {
42954
43179
  name: "E_VALIDATION",
@@ -42956,13 +43181,113 @@ var init_docs3 = __esm({
42956
43181
  });
42957
43182
  process.exit(6);
42958
43183
  }
43184
+ let resolvedFile;
43185
+ if (fileArg) {
43186
+ const routing = resolveWorktreeRouting2();
43187
+ const strayDb = detectStrayCleoDb2(routing);
43188
+ if (strayDb) {
43189
+ cliError(
43190
+ `stray .cleo/tasks.db detected inside worktree at ${routing.worktreePath}. This is a leaked CLEO state directory.`,
43191
+ 6,
43192
+ {
43193
+ name: "E_STRAY_WORKTREE_DB",
43194
+ fix: `Remove it with: rm -rf ${routing.worktreePath}/.cleo \u2014 then retry. See ADR-068 \xA73 for the worktree DB isolation rationale.`
43195
+ }
43196
+ );
43197
+ process.exit(6);
43198
+ }
43199
+ if (routing.isWorktree && process.env["CLEO_QUIET"] !== "1") {
43200
+ const routingLog = `[T10389] routing SSoT write from worktree cwd ${routing.cwd} \u2192 canonical project root ${routing.canonicalRoot}
43201
+ `;
43202
+ process.stderr.write(routingLog);
43203
+ }
43204
+ resolvedFile = resolveWorktreeFilePath(String(fileArg), routing);
43205
+ }
43206
+ if (args.slug && args.type) {
43207
+ const projectRoot = await getProjectRoot33();
43208
+ let warnThreshold = DEFAULT_SIMILARITY_THRESHOLD;
43209
+ let mode = DEFAULT_SIMILARITY_MODE;
43210
+ try {
43211
+ const canon = loadCanonRegistry(projectRoot);
43212
+ if (canon?.similarity) {
43213
+ warnThreshold = canon.similarity.warnThreshold;
43214
+ mode = canon.similarity.mode;
43215
+ }
43216
+ } catch {
43217
+ }
43218
+ try {
43219
+ const sim = await checkSlugSimilarity({
43220
+ slug: args.slug,
43221
+ type: args.type,
43222
+ projectRoot,
43223
+ threshold: warnThreshold
43224
+ });
43225
+ if (sim.mostSimilarSlug !== null) {
43226
+ const scoreFixed = sim.score.toFixed(2);
43227
+ const hint = `Similar to '${sim.mostSimilarSlug}' (score ${scoreFixed}) \u2014 did you mean: cleo docs update ${sim.mostSimilarSlug}? Pass --allow-similar to bypass.`;
43228
+ if (mode === "block" && !allowSimilar) {
43229
+ cliError(hint, 6 /* VALIDATION_ERROR */, {
43230
+ name: "E_SLUG_SIMILARITY",
43231
+ fix: `Use \`cleo docs update ${sim.mostSimilarSlug}\` if updating, or pass --allow-similar to add as a new doc.`,
43232
+ alternatives: [
43233
+ {
43234
+ action: `update '${sim.mostSimilarSlug}' instead`,
43235
+ command: `cleo docs update ${sim.mostSimilarSlug}`
43236
+ },
43237
+ {
43238
+ action: "bypass the similarity check",
43239
+ command: `cleo docs add ${ownerId} ${fileArg ?? `--url ${url}`} --slug ${args.slug} --type ${args.type} --allow-similar`
43240
+ }
43241
+ ],
43242
+ details: {
43243
+ proposedSlug: args.slug,
43244
+ mostSimilarSlug: sim.mostSimilarSlug,
43245
+ score: sim.score,
43246
+ threshold: warnThreshold,
43247
+ kind: args.type
43248
+ }
43249
+ });
43250
+ process.exit(6 /* VALIDATION_ERROR */);
43251
+ }
43252
+ humanInfo(hint);
43253
+ if (allowSimilar) {
43254
+ const auditLine = `${JSON.stringify({
43255
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
43256
+ reason: "allow-similar-bypass",
43257
+ proposedSlug: args.slug,
43258
+ mostSimilarSlug: sim.mostSimilarSlug,
43259
+ score: sim.score,
43260
+ threshold: warnThreshold,
43261
+ kind: args.type,
43262
+ ownerId
43263
+ })}
43264
+ `;
43265
+ try {
43266
+ await mkdir2(join21(projectRoot, ".cleo", "audit"), { recursive: true });
43267
+ await appendFile(
43268
+ join21(projectRoot, ".cleo", "audit", "similar-bypass.jsonl"),
43269
+ auditLine,
43270
+ "utf-8"
43271
+ );
43272
+ } catch {
43273
+ }
43274
+ }
43275
+ }
43276
+ } catch (err) {
43277
+ if (process.env["CLEO_DEBUG"]) {
43278
+ humanInfo(
43279
+ `similarity check skipped: ${err instanceof Error ? err.message : String(err)}`
43280
+ );
43281
+ }
43282
+ }
43283
+ }
42959
43284
  await dispatchFromCli(
42960
43285
  "mutate",
42961
43286
  "docs",
42962
43287
  "add",
42963
43288
  {
42964
43289
  ownerId,
42965
- ...fileArg ? { file: fileArg } : {},
43290
+ ...resolvedFile ? { file: resolvedFile } : {},
42966
43291
  ...url ? { url } : {},
42967
43292
  ...args.desc ? { desc: args.desc } : {},
42968
43293
  ...args.labels ? { labels: args.labels } : {},
@@ -43179,7 +43504,7 @@ var init_docs3 = __esm({
43179
43504
  const taskId = String(args.task);
43180
43505
  const includeAttachments = args["include-attachments"] !== false;
43181
43506
  const includeMemoryRefs = args["include-memory-refs"] === true;
43182
- const projectRoot = getProjectRoot32();
43507
+ const projectRoot = getProjectRoot33();
43183
43508
  try {
43184
43509
  const result = await exportDocument({
43185
43510
  taskId,
@@ -43245,7 +43570,7 @@ var init_docs3 = __esm({
43245
43570
  }
43246
43571
  },
43247
43572
  async run({ args }) {
43248
- const projectRoot = getProjectRoot32();
43573
+ const projectRoot = getProjectRoot33();
43249
43574
  const limit = args.limit ? Number.parseInt(String(args.limit), 10) : 10;
43250
43575
  try {
43251
43576
  const result = args.owner ? await searchDocs2(String(args.query), {
@@ -43301,7 +43626,7 @@ var init_docs3 = __esm({
43301
43626
  }
43302
43627
  },
43303
43628
  async run({ args }) {
43304
- const projectRoot = getProjectRoot32();
43629
+ const projectRoot = getProjectRoot33();
43305
43630
  const rawStrategy = args.strategy ?? "three-way";
43306
43631
  const strategy = rawStrategy === "cherry-pick" || rawStrategy === "multi-diff" ? rawStrategy : "three-way";
43307
43632
  try {
@@ -43350,7 +43675,7 @@ var init_docs3 = __esm({
43350
43675
  }
43351
43676
  },
43352
43677
  async run({ args }) {
43353
- const projectRoot = getProjectRoot32();
43678
+ const projectRoot = getProjectRoot33();
43354
43679
  const fmt = args.format ?? "mermaid";
43355
43680
  try {
43356
43681
  const result = await buildDocsGraph({ ownerId: String(args.for), projectRoot });
@@ -43419,7 +43744,7 @@ var init_docs3 = __esm({
43419
43744
  }
43420
43745
  },
43421
43746
  async run({ args }) {
43422
- const projectRoot = getProjectRoot32();
43747
+ const projectRoot = getProjectRoot33();
43423
43748
  try {
43424
43749
  const result = await rankDocs({
43425
43750
  ownerId: String(args.for),
@@ -43457,7 +43782,7 @@ var init_docs3 = __esm({
43457
43782
  }
43458
43783
  },
43459
43784
  async run({ args }) {
43460
- const projectRoot = getProjectRoot32();
43785
+ const projectRoot = getProjectRoot33();
43461
43786
  try {
43462
43787
  const result = await listDocVersions({
43463
43788
  ownerId: String(args.for),
@@ -43500,7 +43825,7 @@ var init_docs3 = __esm({
43500
43825
  }
43501
43826
  },
43502
43827
  async run({ args }) {
43503
- const projectRoot = getProjectRoot32();
43828
+ const projectRoot = getProjectRoot33();
43504
43829
  try {
43505
43830
  const result = await publishDocs({
43506
43831
  ownerId: String(args.for),
@@ -43624,7 +43949,7 @@ var init_docs3 = __esm({
43624
43949
  },
43625
43950
  async run({ args }) {
43626
43951
  if (args.from) {
43627
- const projectRoot = getProjectRoot32();
43952
+ const projectRoot = getProjectRoot33();
43628
43953
  const ownerId = args.for ?? void 0;
43629
43954
  if (!ownerId) {
43630
43955
  cliError(
@@ -43691,7 +44016,7 @@ var init_docs3 = __esm({
43691
44016
  }
43692
44017
  },
43693
44018
  async run() {
43694
- const projectRoot = getProjectRoot32();
44019
+ const projectRoot = getProjectRoot33();
43695
44020
  try {
43696
44021
  const result = await statusDocs({ projectRoot });
43697
44022
  cliOutput(result, { command: "docs status", operation: "docs.status" });
@@ -43776,7 +44101,7 @@ var init_docs3 = __esm({
43776
44101
  }
43777
44102
  },
43778
44103
  async run({ args }) {
43779
- const projectRoot = getProjectRoot32();
44104
+ const projectRoot = getProjectRoot33();
43780
44105
  const dirArg = String(args.dir);
43781
44106
  const scanRoot = isAbsolute2(dirArg) ? dirArg : resolve5(projectRoot, dirArg);
43782
44107
  const dryRun = args["dry-run"] === true;
@@ -43790,9 +44115,9 @@ var init_docs3 = __esm({
43790
44115
  })}
43791
44116
  `;
43792
44117
  try {
43793
- await mkdir2(join22(projectRoot, ".cleo", "audit"), { recursive: true });
44118
+ await mkdir2(join21(projectRoot, ".cleo", "audit"), { recursive: true });
43794
44119
  await appendFile(
43795
- join22(projectRoot, ".cleo", "audit", "import-force-bypass.jsonl"),
44120
+ join21(projectRoot, ".cleo", "audit", "import-force-bypass.jsonl"),
43796
44121
  auditLine,
43797
44122
  "utf-8"
43798
44123
  );
@@ -43850,7 +44175,7 @@ var init_docs3 = __esm({
43850
44175
  }
43851
44176
  },
43852
44177
  async run({ args }) {
43853
- const projectRoot = getProjectRoot32();
44178
+ const projectRoot = getProjectRoot33();
43854
44179
  const { registry, configError } = loadCliRegistry(projectRoot);
43855
44180
  const kinds = registry.list().map(toWireKind);
43856
44181
  const extensionsCount = kinds.filter((k) => k.isExtension).length;
@@ -43894,7 +44219,7 @@ var init_docs3 = __esm({
43894
44219
  }
43895
44220
  },
43896
44221
  async run({ args }) {
43897
- const projectRoot = getProjectRoot32();
44222
+ const projectRoot = getProjectRoot33();
43898
44223
  const { registry, configError } = loadCliRegistry(projectRoot);
43899
44224
  const kinds = registry.list().map(toWireKind);
43900
44225
  let counts2;
@@ -43972,6 +44297,235 @@ var init_docs3 = __esm({
43972
44297
  }
43973
44298
  });
43974
44299
 
44300
+ // packages/cleo/src/cli/commands/doctor-db-substrate.ts
44301
+ var doctor_db_substrate_exports = {};
44302
+ __export(doctor_db_substrate_exports, {
44303
+ doctorDbSubstrateCommand: () => doctorDbSubstrateCommand
44304
+ });
44305
+ import { getProjectRoot as getProjectRoot34, pushWarning as pushWarning2 } from "@cleocode/core";
44306
+ import { surveyDbSubstrate, surveyFleetDbSubstrate } from "@cleocode/core/doctor/db-substrate.js";
44307
+ function pushSubstrateWarnings(result) {
44308
+ for (const warning of result.warnings) {
44309
+ const context = {
44310
+ kind: warning.kind,
44311
+ path: warning.path,
44312
+ lastWriteMs: warning.lastWriteMs
44313
+ };
44314
+ if (warning.kind === "orphan-project-root") {
44315
+ context["parentWorkspace"] = warning.parentWorkspace ?? null;
44316
+ }
44317
+ pushWarning2({
44318
+ code: warning.kind === "orphan-project-root" ? "W_DB_SUBSTRATE_ORPHAN_PROJECT_ROOT" : "W_DB_SUBSTRATE_NESTED_NEXUS_DUPLICATE",
44319
+ message: warning.kind === "orphan-project-root" ? `Orphan project-root .cleo/ at ${warning.path} (T9550 regression class \u2014 review then remove)` + (warning.parentWorkspace ? ` \u2014 attributed to workspace: ${warning.parentWorkspace}` : "") : `Nested-nexus duplicate at ${warning.path} (structural duplicate of the canonical flat layout)`,
44320
+ severity: "warn",
44321
+ context
44322
+ });
44323
+ }
44324
+ for (const projectSurvey of result.projects) {
44325
+ for (const [role, entry] of Object.entries(projectSurvey.dbs)) {
44326
+ if (entry.pragmaDrift === null || entry.pragmaDrift.length === 0) continue;
44327
+ for (const drift of entry.pragmaDrift) {
44328
+ pushWarning2({
44329
+ code: "W_DB_SUBSTRATE_PRAGMA_DRIFT",
44330
+ message: `Pragma drift on ${role} (${entry.filePath}): expected ${drift.pragma}=${drift.expected}, actual=${drift.actual ?? "<unmeasurable>"}`,
44331
+ severity: "warn",
44332
+ context: {
44333
+ role,
44334
+ filePath: entry.filePath,
44335
+ pragma: drift.pragma,
44336
+ expected: drift.expected,
44337
+ actual: drift.actual
44338
+ }
44339
+ });
44340
+ }
44341
+ }
44342
+ }
44343
+ for (const report of result.crossDbOrphans) {
44344
+ if (report.skipped || report.orphanCount === 0) continue;
44345
+ pushWarning2({
44346
+ code: `W_DB_SUBSTRATE_CROSS_DB_${report.invariant}`,
44347
+ message: `${report.invariant}: ${report.orphanCount} orphan row${report.orphanCount === 1 ? "" : "s"} \u2014 ${report.description}. ${report.suggestedFix}`,
44348
+ severity: "warn",
44349
+ context: {
44350
+ invariant: report.invariant,
44351
+ orphanCount: report.orphanCount,
44352
+ sample: report.sample.join(","),
44353
+ suggestedFix: report.suggestedFix
44354
+ }
44355
+ });
44356
+ }
44357
+ }
44358
+ function pushPerDbWarnings(result) {
44359
+ for (const projectSurvey of result.projects) {
44360
+ for (const [role, dbEntry] of Object.entries(projectSurvey.dbs)) {
44361
+ if (dbEntry.quarantinedTo !== null) {
44362
+ pushWarning2({
44363
+ code: "W_DB_SUBSTRATE_AUTO_QUARANTINED",
44364
+ message: `Auto-quarantined corrupt ${role} DB at ${dbEntry.filePath} \u2192 ${dbEntry.quarantinedTo}. Recover via: cleo backup recover ${role}`,
44365
+ severity: "warn",
44366
+ context: {
44367
+ role,
44368
+ filePath: dbEntry.filePath,
44369
+ quarantinedTo: dbEntry.quarantinedTo,
44370
+ integrityCheckMs: dbEntry.integrityCheckMs
44371
+ }
44372
+ });
44373
+ }
44374
+ if (dbEntry.timedOut) {
44375
+ pushWarning2({
44376
+ code: "W_DB_SUBSTRATE_INTEGRITY_TIMEOUT",
44377
+ message: `integrity_check on ${role} DB at ${dbEntry.filePath} took ${dbEntry.integrityCheckMs}ms \u2014 slow substrate flagged for operator attention`,
44378
+ severity: "warn",
44379
+ context: {
44380
+ role,
44381
+ filePath: dbEntry.filePath,
44382
+ integrityCheckMs: dbEntry.integrityCheckMs
44383
+ }
44384
+ });
44385
+ }
44386
+ }
44387
+ }
44388
+ }
44389
+ var DEFAULT_FLEET_ROOT, doctorDbSubstrateCommand;
44390
+ var init_doctor_db_substrate = __esm({
44391
+ "packages/cleo/src/cli/commands/doctor-db-substrate.ts"() {
44392
+ "use strict";
44393
+ init_define_cli_command();
44394
+ init_renderers();
44395
+ DEFAULT_FLEET_ROOT = "/mnt/projects";
44396
+ doctorDbSubstrateCommand = defineCommand({
44397
+ meta: {
44398
+ name: "db-substrate",
44399
+ description: "Walk every DB in the inventory + report integrity, row counts, orphan dirs. Use --fleet for a multi-project survey under --fleet-root (default /mnt/projects)."
44400
+ },
44401
+ args: {
44402
+ fleet: {
44403
+ type: "boolean",
44404
+ description: "Multi-project survey \u2014 walk every .cleo/-bearing subdir under --fleet-root"
44405
+ },
44406
+ "fleet-root": {
44407
+ type: "string",
44408
+ description: "Fleet root path (default: /mnt/projects). Only used with --fleet."
44409
+ },
44410
+ "integrity-timeout-ms": {
44411
+ type: "string",
44412
+ description: "Wall-clock budget for each PRAGMA integrity_check call (ms; default 60000; 0 disables)."
44413
+ },
44414
+ "no-quarantine": {
44415
+ type: "boolean",
44416
+ description: "Disable auto-quarantine of corrupt DBs (leaves them in place; report-only mode)."
44417
+ },
44418
+ json: { type: "boolean", description: "Output as JSON" },
44419
+ human: { type: "boolean", description: "Force human-readable output" },
44420
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
44421
+ },
44422
+ async run({ args }) {
44423
+ const isFleet = args.fleet === true;
44424
+ let parsedTimeoutMs;
44425
+ if (typeof args["integrity-timeout-ms"] === "string" && args["integrity-timeout-ms"].length > 0) {
44426
+ const n = Number.parseInt(args["integrity-timeout-ms"], 10);
44427
+ if (Number.isFinite(n) && n >= 0) {
44428
+ parsedTimeoutMs = n;
44429
+ }
44430
+ }
44431
+ const options = {
44432
+ ...parsedTimeoutMs !== void 0 ? { integrityCheckTimeoutMs: parsedTimeoutMs } : {},
44433
+ autoQuarantine: args["no-quarantine"] !== true
44434
+ };
44435
+ const result = isFleet ? surveyFleetDbSubstrate(
44436
+ typeof args["fleet-root"] === "string" && args["fleet-root"].length > 0 ? args["fleet-root"] : DEFAULT_FLEET_ROOT,
44437
+ options
44438
+ ) : surveyDbSubstrate(getProjectRoot34(), options);
44439
+ pushSubstrateWarnings(result);
44440
+ pushPerDbWarnings(result);
44441
+ cliOutput(result, {
44442
+ command: "doctor",
44443
+ operation: "doctor.db-substrate.run"
44444
+ });
44445
+ if (result.summary.corrupt > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
44446
+ process.exitCode = 2;
44447
+ }
44448
+ }
44449
+ });
44450
+ }
44451
+ });
44452
+
44453
+ // packages/cleo/src/cli/commands/doctor-legacy-backups.ts
44454
+ var doctor_legacy_backups_exports = {};
44455
+ __export(doctor_legacy_backups_exports, {
44456
+ doctorLegacyBackupsCommand: () => doctorLegacyBackupsCommand
44457
+ });
44458
+ import { getProjectRoot as getProjectRoot35 } from "@cleocode/core";
44459
+ import { pruneLegacyBackups, scanLegacyBackups } from "@cleocode/core/doctor/legacy-backups.js";
44460
+ function parsePositiveInt(raw, fallback) {
44461
+ if (raw === void 0 || raw === null) return fallback;
44462
+ const parsed = Number.parseInt(String(raw), 10);
44463
+ if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
44464
+ return parsed;
44465
+ }
44466
+ var doctorLegacyBackupsCommand;
44467
+ var init_doctor_legacy_backups = __esm({
44468
+ "packages/cleo/src/cli/commands/doctor-legacy-backups.ts"() {
44469
+ "use strict";
44470
+ init_define_cli_command();
44471
+ init_renderers();
44472
+ doctorLegacyBackupsCommand = defineCommand({
44473
+ meta: {
44474
+ name: "legacy-backups",
44475
+ description: "Enumerate legacy *-pre-cleo.db.bak / brain.db.PRE-DUP-FIX-* / pre-untrack / rotation-overflow artefacts and report origin + retention recommendation. Use --prune to delete 'delete'-recommended files (always dry-run unless --no-dry-run is passed)."
44476
+ },
44477
+ args: {
44478
+ prune: {
44479
+ type: "boolean",
44480
+ description: "Remove every artefact whose recommendation is 'delete'. Defaults to --dry-run; pass --no-dry-run to physically remove."
44481
+ },
44482
+ "dry-run": {
44483
+ type: "boolean",
44484
+ description: "Combine with --prune to preview deletions without touching the filesystem.",
44485
+ default: true
44486
+ },
44487
+ "soft-retention-days": {
44488
+ type: "string",
44489
+ description: "Days under which artefacts are always kept (default 30)."
44490
+ },
44491
+ "hard-retention-days": {
44492
+ type: "string",
44493
+ description: "Days over which artefacts are eligible for prune (default 90)."
44494
+ },
44495
+ json: { type: "boolean", description: "Output as JSON" },
44496
+ human: { type: "boolean", description: "Force human-readable output" },
44497
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
44498
+ },
44499
+ async run({ args }) {
44500
+ const softRetentionDays = parsePositiveInt(args["soft-retention-days"], 30);
44501
+ const hardRetentionDays = parsePositiveInt(args["hard-retention-days"], 90);
44502
+ const projectRoot = getProjectRoot35();
44503
+ let result;
44504
+ if (args.prune === true) {
44505
+ const dryRun = args["dry-run"] !== false;
44506
+ result = pruneLegacyBackups(projectRoot, {
44507
+ softRetentionDays,
44508
+ hardRetentionDays,
44509
+ dryRun
44510
+ });
44511
+ } else {
44512
+ result = scanLegacyBackups(projectRoot, {
44513
+ softRetentionDays,
44514
+ hardRetentionDays
44515
+ });
44516
+ }
44517
+ cliOutput(result, {
44518
+ command: "doctor",
44519
+ operation: "doctor.legacy-backups.run"
44520
+ });
44521
+ if (result.errors.length > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
44522
+ process.exitCode = 1;
44523
+ }
44524
+ }
44525
+ });
44526
+ }
44527
+ });
44528
+
43975
44529
  // packages/cleo/src/cli/commands/doctor-projects.ts
43976
44530
  var doctor_projects_exports = {};
43977
44531
  __export(doctor_projects_exports, {
@@ -44236,66 +44790,6 @@ ${this.prefix}: \u2717 ${message}
44236
44790
  }
44237
44791
  });
44238
44792
 
44239
- // packages/cleo/src/cli/commands/doctor-db-substrate.ts
44240
- import { getProjectRoot as getProjectRoot33, pushWarning as pushWarning2 } from "@cleocode/core";
44241
- import { surveyDbSubstrate, surveyFleetDbSubstrate } from "@cleocode/core/doctor/db-substrate.js";
44242
- function pushSubstrateWarnings(result) {
44243
- for (const warning of result.warnings) {
44244
- pushWarning2({
44245
- code: warning.kind === "orphan-project-root" ? "W_DB_SUBSTRATE_ORPHAN_PROJECT_ROOT" : "W_DB_SUBSTRATE_NESTED_NEXUS_DUPLICATE",
44246
- message: warning.kind === "orphan-project-root" ? `Orphan project-root .cleo/ at ${warning.path} (T9550 regression class \u2014 review then remove)` : `Nested-nexus duplicate at ${warning.path} (structural duplicate of the canonical flat layout)`,
44247
- severity: "warn",
44248
- context: {
44249
- kind: warning.kind,
44250
- path: warning.path,
44251
- lastWriteMs: warning.lastWriteMs
44252
- }
44253
- });
44254
- }
44255
- }
44256
- var DEFAULT_FLEET_ROOT, doctorDbSubstrateCommand;
44257
- var init_doctor_db_substrate = __esm({
44258
- "packages/cleo/src/cli/commands/doctor-db-substrate.ts"() {
44259
- "use strict";
44260
- init_define_cli_command();
44261
- init_renderers();
44262
- DEFAULT_FLEET_ROOT = "/mnt/projects";
44263
- doctorDbSubstrateCommand = defineCommand({
44264
- meta: {
44265
- name: "db-substrate",
44266
- description: "Walk every DB in the inventory + report integrity, row counts, orphan dirs. Use --fleet for a multi-project survey under --fleet-root (default /mnt/projects)."
44267
- },
44268
- args: {
44269
- fleet: {
44270
- type: "boolean",
44271
- description: "Multi-project survey \u2014 walk every .cleo/-bearing subdir under --fleet-root"
44272
- },
44273
- "fleet-root": {
44274
- type: "string",
44275
- description: "Fleet root path (default: /mnt/projects). Only used with --fleet."
44276
- },
44277
- json: { type: "boolean", description: "Output as JSON" },
44278
- human: { type: "boolean", description: "Force human-readable output" },
44279
- quiet: { type: "boolean", description: "Suppress non-essential output" }
44280
- },
44281
- async run({ args }) {
44282
- const isFleet = args.fleet === true;
44283
- const result = isFleet ? surveyFleetDbSubstrate(
44284
- typeof args["fleet-root"] === "string" && args["fleet-root"].length > 0 ? args["fleet-root"] : DEFAULT_FLEET_ROOT
44285
- ) : surveyDbSubstrate(getProjectRoot33());
44286
- pushSubstrateWarnings(result);
44287
- cliOutput(result, {
44288
- command: "doctor",
44289
- operation: "doctor.db-substrate.run"
44290
- });
44291
- if (result.summary.corrupt > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
44292
- process.exitCode = 2;
44293
- }
44294
- }
44295
- });
44296
- }
44297
- });
44298
-
44299
44793
  // packages/cleo/src/cli/commands/migrate-agents-v2.ts
44300
44794
  var migrate_agents_v2_exports = {};
44301
44795
  __export(migrate_agents_v2_exports, {
@@ -44307,8 +44801,8 @@ __export(migrate_agents_v2_exports, {
44307
44801
  });
44308
44802
  import { createHash as createHash2 } from "node:crypto";
44309
44803
  import { appendFileSync as appendFileSync2, existsSync as existsSync14, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync14 } from "node:fs";
44310
- import { join as join23 } from "node:path";
44311
- import { getProjectRoot as getProjectRoot34, installAgentFromCant } from "@cleocode/core/internal";
44804
+ import { join as join22 } from "node:path";
44805
+ import { getProjectRoot as getProjectRoot36, installAgentFromCant } from "@cleocode/core/internal";
44312
44806
  import { openCleoDb as openCleoDb2 } from "@cleocode/core/store/open-cleo-db";
44313
44807
  function sha256Hex(bytes) {
44314
44808
  return createHash2("sha256").update(bytes).digest("hex");
@@ -44327,8 +44821,8 @@ function extractAgentName(source) {
44327
44821
  return headerMatch[1] ?? null;
44328
44822
  }
44329
44823
  function appendAuditLog(projectRoot, entry) {
44330
- const auditPath = join23(projectRoot, AUDIT_LOG_RELATIVE);
44331
- const auditDir = join23(auditPath, "..");
44824
+ const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
44825
+ const auditDir = join22(auditPath, "..");
44332
44826
  if (!existsSync14(auditDir)) {
44333
44827
  mkdirSync3(auditDir, { recursive: true });
44334
44828
  }
@@ -44346,7 +44840,7 @@ function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
44346
44840
  return;
44347
44841
  }
44348
44842
  for (const filename of files) {
44349
- const cantPath = join23(scanDir, filename);
44843
+ const cantPath = join22(scanDir, filename);
44350
44844
  const relPath = cantPath.replace(`${projectRoot}/`, "");
44351
44845
  let sourceBytes;
44352
44846
  let sourceText;
@@ -44443,9 +44937,9 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
44443
44937
  const { db: _sdDb } = await openCleoDb2("signaldock");
44444
44938
  const db = _sdDb;
44445
44939
  try {
44446
- const canonicalDir = join23(projectRoot, ".cleo", "cant", "agents");
44940
+ const canonicalDir = join22(projectRoot, ".cleo", "cant", "agents");
44447
44941
  walkAgentsDir(db, canonicalDir, projectRoot, summary, verbose);
44448
- const legacyDir = join23(projectRoot, ".cleo", "agents");
44942
+ const legacyDir = join22(projectRoot, ".cleo", "agents");
44449
44943
  walkAgentsDir(db, legacyDir, projectRoot, summary, verbose);
44450
44944
  } finally {
44451
44945
  db.close();
@@ -44453,7 +44947,7 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
44453
44947
  return summary;
44454
44948
  }
44455
44949
  function readMigrationConflicts(projectRoot) {
44456
- const auditPath = join23(projectRoot, AUDIT_LOG_RELATIVE);
44950
+ const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
44457
44951
  if (!existsSync14(auditPath)) return [];
44458
44952
  let raw;
44459
44953
  try {
@@ -44495,7 +44989,7 @@ var init_migrate_agents_v2 = __esm({
44495
44989
  }
44496
44990
  },
44497
44991
  async run({ args }) {
44498
- const projectRoot = getProjectRoot34();
44992
+ const projectRoot = getProjectRoot36();
44499
44993
  const verbose = args.quiet !== true;
44500
44994
  if (verbose) {
44501
44995
  humanInfo("Scanning .cleo/cant/agents/ and .cleo/agents/ for unregistered agents...");
@@ -44538,8 +45032,8 @@ __export(doctor_exports, {
44538
45032
  doctorCommand: () => doctorCommand2
44539
45033
  });
44540
45034
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
44541
- import { join as join24 } from "node:path";
44542
- import { getProjectRoot as getProjectRoot35, pushWarning as pushWarning3 } from "@cleocode/core";
45035
+ import { join as join23 } from "node:path";
45036
+ import { getProjectRoot as getProjectRoot37, pushWarning as pushWarning3 } from "@cleocode/core";
44543
45037
  import {
44544
45038
  quarantineRogueCleoDir,
44545
45039
  scanRogueCleoDirs
@@ -44577,8 +45071,8 @@ async function scanTestFixturesInProd(projectRoot) {
44577
45071
  }
44578
45072
  async function quarantineTestFixtures(projectRoot, matches) {
44579
45073
  if (matches.length === 0) return 0;
44580
- const cleoDir = join24(projectRoot, ".cleo");
44581
- const quarantineDir = join24(
45074
+ const cleoDir = join23(projectRoot, ".cleo");
45075
+ const quarantineDir = join23(
44582
45076
  cleoDir,
44583
45077
  "quarantine",
44584
45078
  `fixture-scan-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`
@@ -44586,7 +45080,7 @@ async function quarantineTestFixtures(projectRoot, matches) {
44586
45080
  mkdirSync4(quarantineDir, { recursive: true });
44587
45081
  const manifest = matches.map((m) => ({ ...m, quarantinedAt: (/* @__PURE__ */ new Date()).toISOString() }));
44588
45082
  writeFileSync4(
44589
- join24(quarantineDir, "manifest.jsonl"),
45083
+ join23(quarantineDir, "manifest.jsonl"),
44590
45084
  manifest.map((m) => JSON.stringify(m)).join("\n") + "\n"
44591
45085
  );
44592
45086
  const { getNativeDb } = await import("@cleocode/core/store/sqlite.js");
@@ -44650,6 +45144,7 @@ var init_doctor = __esm({
44650
45144
  init_progress();
44651
45145
  init_renderers();
44652
45146
  init_doctor_db_substrate();
45147
+ init_doctor_legacy_backups();
44653
45148
  init_doctor_projects();
44654
45149
  init_migrate_agents_v2();
44655
45150
  FIXTURE_ID_PATTERNS = [/^E\d+$/, /^T\d+EP$/];
@@ -44663,7 +45158,9 @@ var init_doctor = __esm({
44663
45158
  meta: { name: "doctor", description: "Run system diagnostics and health checks" },
44664
45159
  subCommands: {
44665
45160
  // T10307 / Saga T10281 / Epic T10282 — DB-substrate walker
44666
- "db-substrate": doctorDbSubstrateCommand
45161
+ "db-substrate": doctorDbSubstrateCommand,
45162
+ // T10309 / Saga T10281 / Epic T10282 — Legacy-backup walker
45163
+ "legacy-backups": doctorLegacyBackupsCommand
44667
45164
  },
44668
45165
  args: {
44669
45166
  detailed: {
@@ -44831,7 +45328,7 @@ var init_doctor = __esm({
44831
45328
  try {
44832
45329
  if (args.brain) {
44833
45330
  const { computeBrainHealthDashboard } = await import("@cleocode/core/memory/brain-health-dashboard.js");
44834
- const projectRoot = getProjectRoot35();
45331
+ const projectRoot = getProjectRoot37();
44835
45332
  const dashboard = await computeBrainHealthDashboard(projectRoot);
44836
45333
  cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
44837
45334
  if (dashboard.hasP0Failure) {
@@ -44840,7 +45337,7 @@ var init_doctor = __esm({
44840
45337
  return;
44841
45338
  }
44842
45339
  if (args["scan-test-fixtures-in-prod"]) {
44843
- const projectRoot = getProjectRoot35();
45340
+ const projectRoot = getProjectRoot37();
44844
45341
  const matches = await scanTestFixturesInProd(projectRoot);
44845
45342
  const dryRun = args["dry-run"] !== false && args.quarantine !== true;
44846
45343
  const quarantined = !dryRun && matches.length > 0 ? await quarantineTestFixtures(projectRoot, matches) : void 0;
@@ -44928,7 +45425,7 @@ var init_doctor = __esm({
44928
45425
  progress.complete("Comprehensive diagnostics complete");
44929
45426
  } else if (args["scan-rogue-cleo-dirs"]) {
44930
45427
  progress.step(0, "Scanning for rogue .cleo/ directories");
44931
- const projectRoot = getProjectRoot35();
45428
+ const projectRoot = getProjectRoot37();
44932
45429
  const reports = scanRogueCleoDirs(projectRoot);
44933
45430
  progress.complete(
44934
45431
  `Found ${reports.length} rogue .cleo/ director${reports.length === 1 ? "y" : "ies"}`
@@ -44937,7 +45434,7 @@ var init_doctor = __esm({
44937
45434
  } else if (args["quarantine-rogue-cleo-dirs"]) {
44938
45435
  const isDryRun = args["dry-run"] === true;
44939
45436
  progress.step(0, `${isDryRun ? "[DRY RUN] " : ""}Scanning for rogue .cleo/ directories`);
44940
- const projectRoot = getProjectRoot35();
45437
+ const projectRoot = getProjectRoot37();
44941
45438
  const reports = scanRogueCleoDirs(projectRoot);
44942
45439
  if (reports.length === 0) {
44943
45440
  progress.complete("No rogue .cleo/ directories found \u2014 nothing to quarantine");
@@ -44991,7 +45488,7 @@ var init_doctor = __esm({
44991
45488
  const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/store/cleanup-legacy.js");
44992
45489
  const { getCleoHome: getCleoHome6 } = await import("@cleocode/core");
44993
45490
  const cleoHome = getCleoHome6();
44994
- const projectRoot = getProjectRoot35();
45491
+ const projectRoot = getProjectRoot37();
44995
45492
  const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
44996
45493
  const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
44997
45494
  const isDryRun = args["dry-run"] === true;
@@ -45024,7 +45521,7 @@ var init_doctor = __esm({
45024
45521
  } else if (args["audit-worktree-orphans"]) {
45025
45522
  progress.step(0, "Comprehensive worktree anomaly audit (T9808 / council D009)");
45026
45523
  const { auditWorktreeOrphansComprehensive, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
45027
- const projectRoot = getProjectRoot35();
45524
+ const projectRoot = getProjectRoot37();
45028
45525
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
45029
45526
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
45030
45527
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -45081,7 +45578,7 @@ var init_doctor = __esm({
45081
45578
  `${isDryRun ? "[DRY RUN] " : ""}Scanning + pruning worktree-orphan .cleo/ directories`
45082
45579
  );
45083
45580
  const { pruneWorktreeOrphans, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
45084
- const projectRoot = getProjectRoot35();
45581
+ const projectRoot = getProjectRoot37();
45085
45582
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
45086
45583
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
45087
45584
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -45129,8 +45626,8 @@ var init_doctor = __esm({
45129
45626
  );
45130
45627
  return;
45131
45628
  }
45132
- const archiveDir = join24(projectRoot, ".cleo", "backups");
45133
- const auditLogPath = join24(projectRoot, ".cleo", "audit", "worktree-prune.jsonl");
45629
+ const archiveDir = join23(projectRoot, ".cleo", "backups");
45630
+ const auditLogPath = join23(projectRoot, ".cleo", "audit", "worktree-prune.jsonl");
45134
45631
  const result = await pruneWorktreeOrphans(orphans, {
45135
45632
  archiveDir,
45136
45633
  auditLogPath,
@@ -45160,7 +45657,7 @@ var init_doctor = __esm({
45160
45657
  `${isDryRun ? "[DRY RUN] " : ""}Migrating .cleo/worktree-include \u2192 .worktreeinclude`
45161
45658
  );
45162
45659
  const { migrateWorktreeIncludeFile } = await import("@cleocode/core");
45163
- const projectRoot = getProjectRoot35();
45660
+ const projectRoot = getProjectRoot37();
45164
45661
  const result = await migrateWorktreeIncludeFile(projectRoot, { dryRun: isDryRun });
45165
45662
  progress.complete(`Migration ${result.action}`);
45166
45663
  cliOutput(result, { command: "doctor", operation: "doctor.migrate-worktree-include" });
@@ -45176,7 +45673,7 @@ var init_doctor = __esm({
45176
45673
  } else if (args["audit-sagas"]) {
45177
45674
  progress.step(0, "Auditing Saga hierarchy for ADR-073 invariants");
45178
45675
  const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
45179
- const projectRoot = getProjectRoot35();
45676
+ const projectRoot = getProjectRoot37();
45180
45677
  const result = await auditSagaHierarchy(projectRoot);
45181
45678
  const summary = `Saga audit complete \u2014 ${result.sagas.length} saga(s) inspected, ${result.count} invariant violation(s), ${result.driftCount} drift warning(s)`;
45182
45679
  progress.complete(summary);
@@ -45194,7 +45691,7 @@ var init_doctor = __esm({
45194
45691
  { command: "doctor", operation: "admin.health" }
45195
45692
  );
45196
45693
  try {
45197
- const projectRoot = getProjectRoot35();
45694
+ const projectRoot = getProjectRoot37();
45198
45695
  const conflicts = readMigrationConflicts(projectRoot);
45199
45696
  if (conflicts.length > 0) {
45200
45697
  progress.complete(
@@ -45225,7 +45722,7 @@ var init_doctor = __esm({
45225
45722
  progress.complete("Health check complete");
45226
45723
  }
45227
45724
  try {
45228
- const projectRoot = getProjectRoot35();
45725
+ const projectRoot = getProjectRoot37();
45229
45726
  const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
45230
45727
  const sagaAudit = await auditSagaHierarchy(projectRoot);
45231
45728
  if (sagaAudit.sagas.length === 0) {
@@ -45287,7 +45784,7 @@ __export(event_exports, {
45287
45784
  orchestratorCommand: () => orchestratorCommand
45288
45785
  });
45289
45786
  import { readdir as readdir2 } from "node:fs/promises";
45290
- import { join as join25 } from "node:path";
45787
+ import { join as join24 } from "node:path";
45291
45788
  import { cwd as processCwd } from "node:process";
45292
45789
  import { appendEvent } from "@cleocode/core/events/event-bus.js";
45293
45790
  function resolveProjectRoot3(arg) {
@@ -45410,7 +45907,7 @@ var init_event = __esm({
45410
45907
  const agentIdFilter = args.agent;
45411
45908
  const showAll = args.all === true;
45412
45909
  const lines = parseInt(args.lines ?? "20", 10);
45413
- const eventsDir = join25(projectRoot, ".cleo", "agent-events");
45910
+ const eventsDir = join24(projectRoot, ".cleo", "agent-events");
45414
45911
  try {
45415
45912
  let files = [];
45416
45913
  try {
@@ -45448,7 +45945,7 @@ var init_event = __esm({
45448
45945
  for (const file of filesToTail) {
45449
45946
  const agentId = file.replace(".jsonl", "");
45450
45947
  const { readFileSync: readFileSync18 } = await import("node:fs");
45451
- const content = readFileSync18(join25(eventsDir, file), "utf-8");
45948
+ const content = readFileSync18(join24(eventsDir, file), "utf-8");
45452
45949
  const eventLines = content.trim().split("\n").filter(Boolean);
45453
45950
  const tail = eventLines.slice(-lines);
45454
45951
  if (jsonMode) {
@@ -45518,7 +46015,7 @@ var init_event = __esm({
45518
46015
  const epicFilter = args.epic;
45519
46016
  const follow = args.follow === true;
45520
46017
  const lines = parseInt(args.lines ?? "50", 10);
45521
- const eventsDir = join25(projectRoot, ".cleo", "agent-events");
46018
+ const eventsDir = join24(projectRoot, ".cleo", "agent-events");
45522
46019
  let files = [];
45523
46020
  try {
45524
46021
  const entries = await readdir2(eventsDir);
@@ -45544,7 +46041,7 @@ var init_event = __esm({
45544
46041
  const agentId = file.replace(".jsonl", "");
45545
46042
  try {
45546
46043
  const { readFileSync: readFileSync18 } = await import("node:fs");
45547
- const content = readFileSync18(join25(eventsDir, file), "utf-8");
46044
+ const content = readFileSync18(join24(eventsDir, file), "utf-8");
45548
46045
  const eventLines = content.trim().split("\n").filter(Boolean);
45549
46046
  const tail = eventLines.slice(-lines);
45550
46047
  if (jsonMode) {
@@ -46083,7 +46580,7 @@ __export(gc_exports, {
46083
46580
  gcCommand: () => gcCommand
46084
46581
  });
46085
46582
  import { homedir as homedir4, tmpdir } from "node:os";
46086
- import { join as join26 } from "node:path";
46583
+ import { join as join25 } from "node:path";
46087
46584
  import { pruneOrphanTempDirs, pruneOrphanWorktrees } from "@cleocode/core/gc/cleanup.js";
46088
46585
  import { runGC } from "@cleocode/core/gc/runner.js";
46089
46586
  import { readGCState } from "@cleocode/core/gc/state.js";
@@ -46166,7 +46663,7 @@ var init_gc = __esm({
46166
46663
  },
46167
46664
  async run({ args }) {
46168
46665
  const cleoDir = resolveLegacyCleoDir3(args["cleo-dir"]);
46169
- const statePath = join26(cleoDir, "gc-state.json");
46666
+ const statePath = join25(cleoDir, "gc-state.json");
46170
46667
  try {
46171
46668
  const state = await readGCState(statePath);
46172
46669
  const diskStr = state.lastDiskUsedPct !== null ? `${state.lastDiskUsedPct.toFixed(1)}%` : "unknown";
@@ -46219,8 +46716,8 @@ var init_gc = __esm({
46219
46716
  }
46220
46717
  },
46221
46718
  async run({ args }) {
46222
- const xdgData = process.env["XDG_DATA_HOME"] ?? join26(homedir4(), ".local", "share");
46223
- const worktreesRoot = args["worktrees-root"] ?? join26(xdgData, "cleo", "worktrees");
46719
+ const xdgData = process.env["XDG_DATA_HOME"] ?? join25(homedir4(), ".local", "share");
46720
+ const worktreesRoot = args["worktrees-root"] ?? join25(xdgData, "cleo", "worktrees");
46224
46721
  const projectHash = args["project-hash"];
46225
46722
  const dryRun = args["dry-run"];
46226
46723
  const preserveRaw = args["preserve-tasks"];
@@ -47433,7 +47930,7 @@ __export(init_exports, {
47433
47930
  initCommand: () => initCommand2
47434
47931
  });
47435
47932
  import { existsSync as existsSync15, readFileSync as readFileSync15 } from "node:fs";
47436
- import { join as join27 } from "node:path";
47933
+ import { join as join26 } from "node:path";
47437
47934
  import { fileURLToPath as fileURLToPath6 } from "node:url";
47438
47935
  import {
47439
47936
  CleoError as CleoError4,
@@ -47445,9 +47942,9 @@ import {
47445
47942
  function getGitignoreTemplate() {
47446
47943
  try {
47447
47944
  const thisFile = fileURLToPath6(import.meta.url);
47448
- const packageRoot = join27(thisFile, "..", "..", "..", "..");
47449
- const localTemplatePath = join27(packageRoot, "templates", "cleo-gitignore");
47450
- const monorepoTemplatePath = join27(packageRoot, "..", "..", "templates", "cleo-gitignore");
47945
+ const packageRoot = join26(thisFile, "..", "..", "..", "..");
47946
+ const localTemplatePath = join26(packageRoot, "templates", "cleo-gitignore");
47947
+ const monorepoTemplatePath = join26(packageRoot, "..", "..", "templates", "cleo-gitignore");
47451
47948
  const templatePath = existsSync15(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
47452
47949
  if (existsSync15(templatePath)) {
47453
47950
  return readFileSync15(templatePath, "utf-8");
@@ -48372,7 +48869,7 @@ var llm_cost_exports = {};
48372
48869
  __export(llm_cost_exports, {
48373
48870
  costCommand: () => costCommand
48374
48871
  });
48375
- import { getProjectRoot as getProjectRoot36 } from "@cleocode/core/internal";
48872
+ import { getProjectRoot as getProjectRoot38 } from "@cleocode/core/internal";
48376
48873
  import { computeCost } from "@cleocode/core/llm/usage-pricing";
48377
48874
  function resolveSessionId(raw) {
48378
48875
  if (raw === "current") {
@@ -48445,7 +48942,7 @@ var init_llm_cost = __esm({
48445
48942
  process.exit(6);
48446
48943
  }
48447
48944
  const sessionId = resolveSessionId(rawSessionId);
48448
- const projectRoot = getProjectRoot36(process.cwd());
48945
+ const projectRoot = getProjectRoot38(process.cwd());
48449
48946
  let breakdown;
48450
48947
  try {
48451
48948
  breakdown = await loadSessionCostBreakdown(projectRoot, sessionId);
@@ -49992,7 +50489,7 @@ var memory_exports = {};
49992
50489
  __export(memory_exports, {
49993
50490
  memoryCommand: () => memoryCommand
49994
50491
  });
49995
- import { getProjectRoot as getProjectRoot37 } from "@cleocode/core";
50492
+ import { getProjectRoot as getProjectRoot39 } from "@cleocode/core";
49996
50493
  import {
49997
50494
  getBrainDb as getBrainDb2,
49998
50495
  getDreamStatus,
@@ -50916,7 +51413,7 @@ var init_memory3 = __esm({
50916
51413
  },
50917
51414
  args: {},
50918
51415
  async run() {
50919
- const root = getProjectRoot37();
51416
+ const root = getProjectRoot39();
50920
51417
  try {
50921
51418
  const result = await runConsolidation(root);
50922
51419
  cliOutput(result, { command: "memory-consolidate", operation: "memory.consolidate" });
@@ -50940,7 +51437,7 @@ var init_memory3 = __esm({
50940
51437
  }
50941
51438
  },
50942
51439
  async run({ args }) {
50943
- const root = getProjectRoot37();
51440
+ const root = getProjectRoot39();
50944
51441
  if (args.status) {
50945
51442
  try {
50946
51443
  const status = await getDreamStatus(root);
@@ -50977,7 +51474,7 @@ var init_memory3 = __esm({
50977
51474
  }
50978
51475
  },
50979
51476
  async run({ args }) {
50980
- const root = getProjectRoot37();
51477
+ const root = getProjectRoot39();
50981
51478
  try {
50982
51479
  const { runObserver, runReflector } = await import("@cleocode/core/memory");
50983
51480
  const observerResult = await runObserver(root, args.session, {
@@ -51017,7 +51514,7 @@ var init_memory3 = __esm({
51017
51514
  }
51018
51515
  },
51019
51516
  async run({ args }) {
51020
- const root = getProjectRoot37();
51517
+ const root = getProjectRoot39();
51021
51518
  try {
51022
51519
  await getBrainDb2(root);
51023
51520
  const { totalDuplicateRows, groups } = await scanDuplicateEntries();
@@ -51063,7 +51560,7 @@ var init_memory3 = __esm({
51063
51560
  async run({ args }) {
51064
51561
  const sourceDir = args.from;
51065
51562
  const isDryRun = !!args["dry-run"];
51066
- const projectRoot = getProjectRoot37();
51563
+ const projectRoot = getProjectRoot39();
51067
51564
  try {
51068
51565
  const result = await importMemoryFiles({
51069
51566
  sourceDir,
@@ -51214,7 +51711,7 @@ var init_memory3 = __esm({
51214
51711
  },
51215
51712
  args: {},
51216
51713
  async run() {
51217
- const root = getProjectRoot37();
51714
+ const root = getProjectRoot39();
51218
51715
  try {
51219
51716
  await getBrainDb2(root);
51220
51717
  const result = await getTierStats(root);
@@ -51257,7 +51754,7 @@ var init_memory3 = __esm({
51257
51754
  }
51258
51755
  },
51259
51756
  async run({ args }) {
51260
- const root = getProjectRoot37();
51757
+ const root = getProjectRoot39();
51261
51758
  const targetTier = args.to;
51262
51759
  const reason = args.reason;
51263
51760
  const validTiers = ["medium", "long"];
@@ -51323,7 +51820,7 @@ var init_memory3 = __esm({
51323
51820
  }
51324
51821
  },
51325
51822
  async run({ args }) {
51326
- const root = getProjectRoot37();
51823
+ const root = getProjectRoot39();
51327
51824
  const targetTier = args.to;
51328
51825
  const reason = args.reason;
51329
51826
  const validTiers = ["short", "medium"];
@@ -51783,7 +52280,7 @@ var migrate_claude_mem_exports = {};
51783
52280
  __export(migrate_claude_mem_exports, {
51784
52281
  migrateClaudeMemCommand: () => migrateClaudeMemCommand
51785
52282
  });
51786
- import { getProjectRoot as getProjectRoot38, migrateClaudeMem } from "@cleocode/core/internal";
52283
+ import { getProjectRoot as getProjectRoot40, migrateClaudeMem } from "@cleocode/core/internal";
51787
52284
  import { ingestLooseAgentOutputs, ingestRcasdDirectories } from "@cleocode/core/memory";
51788
52285
  import { getDb as getDb2 } from "@cleocode/core/store/sqlite";
51789
52286
  var storageCommand, claudeMemCommand, manifestIngestCommand, migrateClaudeMemCommand;
@@ -51846,7 +52343,7 @@ var init_migrate_claude_mem = __esm({
51846
52343
  }
51847
52344
  },
51848
52345
  async run({ args }) {
51849
- const root = getProjectRoot38();
52346
+ const root = getProjectRoot40();
51850
52347
  try {
51851
52348
  const result = await migrateClaudeMem(root, {
51852
52349
  sourcePath: args.source,
@@ -51895,7 +52392,7 @@ var init_migrate_claude_mem = __esm({
51895
52392
  }
51896
52393
  },
51897
52394
  async run({ args }) {
51898
- const projectRoot = getProjectRoot38();
52395
+ const projectRoot = getProjectRoot40();
51899
52396
  try {
51900
52397
  const db = await getDb2(projectRoot);
51901
52398
  const rcasdFlag = Boolean(args.rcasd);
@@ -51999,7 +52496,7 @@ __export(nexus_exports, {
51999
52496
  import { appendFile as appendFile2, mkdir as mkdir3 } from "node:fs/promises";
52000
52497
  import { homedir as homedir5 } from "node:os";
52001
52498
  import path4 from "node:path";
52002
- import { getProjectRoot as getProjectRoot39 } from "@cleocode/core";
52499
+ import { getProjectRoot as getProjectRoot41 } from "@cleocode/core";
52003
52500
  import { getSymbolImpact } from "@cleocode/core/nexus";
52004
52501
  import { runNexusAnalysis } from "@cleocode/core/nexus/analyze-orchestrator.js";
52005
52502
  import { exportNexusGraph } from "@cleocode/core/nexus/export.js";
@@ -52114,7 +52611,7 @@ var init_nexus3 = __esm({
52114
52611
  async run({ args }) {
52115
52612
  applyJsonFlag2(args.json);
52116
52613
  const projectIdOverride = args["project-id"];
52117
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
52614
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52118
52615
  const startTime = Date.now();
52119
52616
  try {
52120
52617
  const [{ getNexusDb, nexusSchema }, { getIndexStats }] = await Promise.all([
@@ -52629,7 +53126,7 @@ var init_nexus3 = __esm({
52629
53126
  applyJsonFlag2(args.json);
52630
53127
  const startTime = Date.now();
52631
53128
  const projectIdOverride = args["project-id"];
52632
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53129
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52633
53130
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
52634
53131
  const response = await dispatchRaw("query", "nexus", "clusters", { projectId, repoPath });
52635
53132
  const durationMs = Date.now() - startTime;
@@ -52673,7 +53170,7 @@ var init_nexus3 = __esm({
52673
53170
  applyJsonFlag2(args.json);
52674
53171
  const startTime = Date.now();
52675
53172
  const projectIdOverride = args["project-id"];
52676
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53173
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52677
53174
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
52678
53175
  const response = await dispatchRaw("query", "nexus", "flows", { projectId, repoPath });
52679
53176
  const durationMs = Date.now() - startTime;
@@ -52716,7 +53213,7 @@ var init_nexus3 = __esm({
52716
53213
  void appendDeprecationTelemetry("nexus.context", "cleo graph context");
52717
53214
  const startTime = Date.now();
52718
53215
  const projectIdOverride = args["project-id"];
52719
- const repoPath = getProjectRoot39();
53216
+ const repoPath = getProjectRoot41();
52720
53217
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
52721
53218
  const limit = parseInt(args.limit, 10);
52722
53219
  const symbolName = args.symbol;
@@ -52779,7 +53276,7 @@ var init_nexus3 = __esm({
52779
53276
  const startTime = Date.now();
52780
53277
  const whyFlag = !!args.why;
52781
53278
  const projectIdOverride = args["project-id"];
52782
- const repoPath = getProjectRoot39();
53279
+ const repoPath = getProjectRoot41();
52783
53280
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
52784
53281
  const maxDepth = Math.min(parseInt(args.depth, 10), 5);
52785
53282
  const symbolName = args.symbol;
@@ -52851,7 +53348,7 @@ var init_nexus3 = __esm({
52851
53348
  const projectIdOverride = args["project-id"];
52852
53349
  const isIncremental = !!args.incremental;
52853
53350
  const ctx = getFormatContext();
52854
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53351
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52855
53352
  humanInfo(`[nexus] Analyzing: ${repoPath}${isIncremental ? " (incremental)" : ""}`);
52856
53353
  if (!isIncremental) humanInfo("[nexus] Clearing existing index for project...");
52857
53354
  try {
@@ -52954,7 +53451,7 @@ var init_nexus3 = __esm({
52954
53451
  async run({ args }) {
52955
53452
  applyJsonFlag2(args.json);
52956
53453
  const startTime = Date.now();
52957
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53454
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52958
53455
  const name = args.name;
52959
53456
  const response = await dispatchRaw("mutate", "nexus", "projects.register", {
52960
53457
  path: repoPath,
@@ -53312,7 +53809,7 @@ var init_nexus3 = __esm({
53312
53809
  applyJsonFlag2(args.json);
53313
53810
  const startTime = Date.now();
53314
53811
  const projectIdOverride = args["project-id"];
53315
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53812
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53316
53813
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53317
53814
  const response = await dispatchRaw("mutate", "nexus", "refresh-bridge", {
53318
53815
  repoPath,
@@ -53418,7 +53915,7 @@ var init_nexus3 = __esm({
53418
53915
  async run({ args }) {
53419
53916
  applyJsonFlag2(args.json);
53420
53917
  const startTime = Date.now();
53421
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53918
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53422
53919
  const projectIdOverride = args["project-id"];
53423
53920
  const beforeRef = args.before ?? "HEAD~1";
53424
53921
  const afterRef = args.after ?? "HEAD";
@@ -53536,7 +54033,7 @@ var init_nexus3 = __esm({
53536
54033
  applyJsonFlag2(args.json);
53537
54034
  const startTime = Date.now();
53538
54035
  const projectIdOverride = args["project-id"];
53539
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
54036
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53540
54037
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53541
54038
  const response = await dispatchRaw("query", "nexus", "route-map", { projectId });
53542
54039
  const durationMs = Date.now() - startTime;
@@ -53592,7 +54089,7 @@ var init_nexus3 = __esm({
53592
54089
  const startTime = Date.now();
53593
54090
  const routeSymbol = args.routeSymbol;
53594
54091
  const projectIdOverride = args["project-id"];
53595
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
54092
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53596
54093
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53597
54094
  const response = await dispatchRaw("query", "nexus", "shape-check", { routeSymbol, projectId });
53598
54095
  const durationMs = Date.now() - startTime;
@@ -53982,7 +54479,7 @@ var init_nexus3 = __esm({
53982
54479
  async run({ args }) {
53983
54480
  applyJsonFlag2(args.json);
53984
54481
  const startTime = Date.now();
53985
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
54482
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53986
54483
  const projectIdOverride = args["project-id"];
53987
54484
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53988
54485
  const response = await dispatchRaw("mutate", "nexus", "contracts-sync", {
@@ -54086,7 +54583,7 @@ var init_nexus3 = __esm({
54086
54583
  async run({ args }) {
54087
54584
  applyJsonFlag2(args.json);
54088
54585
  const startTime = Date.now();
54089
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
54586
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
54090
54587
  const projectId = Buffer.from(repoPath).toString("base64url").slice(0, 32);
54091
54588
  const response = await dispatchRaw("mutate", "nexus", "contracts-link-tasks", {
54092
54589
  projectId,
@@ -54167,7 +54664,7 @@ var init_nexus3 = __esm({
54167
54664
  const isIncremental = !!args.incremental;
54168
54665
  try {
54169
54666
  const result = await runNexusWiki({
54170
- projectRoot: getProjectRoot39(),
54667
+ projectRoot: getProjectRoot41(),
54171
54668
  outputDir,
54172
54669
  communityFilter,
54173
54670
  incremental: isIncremental
@@ -56594,7 +57091,7 @@ var refresh_memory_exports = {};
56594
57091
  __export(refresh_memory_exports, {
56595
57092
  refreshMemoryCommand: () => refreshMemoryCommand
56596
57093
  });
56597
- import { getProjectRoot as getProjectRoot40 } from "@cleocode/core";
57094
+ import { getProjectRoot as getProjectRoot42 } from "@cleocode/core";
56598
57095
  var refreshMemoryCommand;
56599
57096
  var init_refresh_memory = __esm({
56600
57097
  "packages/cleo/src/cli/commands/refresh-memory.ts"() {
@@ -56607,7 +57104,7 @@ var init_refresh_memory = __esm({
56607
57104
  description: "Regenerate .cleo/memory-bridge.md from brain.db"
56608
57105
  },
56609
57106
  async run() {
56610
- const projectDir = getProjectRoot40();
57107
+ const projectDir = getProjectRoot42();
56611
57108
  const { writeMemoryBridge } = await import("@cleocode/core/internal");
56612
57109
  const result = await writeMemoryBridge(projectDir);
56613
57110
  if (result.written) {
@@ -58008,7 +58505,7 @@ import fs3 from "node:fs";
58008
58505
  import path5 from "node:path";
58009
58506
  import {
58010
58507
  CleoError as CleoError7,
58011
- getProjectRoot as getProjectRoot41,
58508
+ getProjectRoot as getProjectRoot43,
58012
58509
  getTaskAccessor as getTaskAccessor3,
58013
58510
  parseConflictReport,
58014
58511
  setAtPath
@@ -58029,7 +58526,7 @@ var init_restore = __esm({
58029
58526
  description: "Apply manually-resolved conflicts from .cleo/restore-conflicts.md"
58030
58527
  },
58031
58528
  async run() {
58032
- const projectRoot = getProjectRoot41();
58529
+ const projectRoot = getProjectRoot43();
58033
58530
  const reportPath = path5.join(projectRoot, CLEO_DIR_NAME, RESTORE_CONFLICTS_MD);
58034
58531
  if (!fs3.existsSync(reportPath)) {
58035
58532
  humanLine("No pending restore conflicts. Nothing to finalize.");
@@ -58395,7 +58892,7 @@ __export(revert_exports, {
58395
58892
  revertCommand: () => revertCommand
58396
58893
  });
58397
58894
  import { readFile as readFile4 } from "node:fs/promises";
58398
- import { join as join28 } from "node:path";
58895
+ import { join as join27 } from "node:path";
58399
58896
  import { cwd as processCwd2 } from "node:process";
58400
58897
  import { E_RECEIPT_NOT_FOUND } from "@cleocode/core/sentient/chain-walker.js";
58401
58898
  import { SENTIENT_STATE_FILE } from "@cleocode/core/sentient/daemon.js";
@@ -58448,7 +58945,7 @@ async function loadOwnerAttestation(attestationFilePath) {
58448
58945
  return obj;
58449
58946
  }
58450
58947
  async function loadOwnerPubkeys(projectRoot) {
58451
- const path6 = join28(projectRoot, OWNER_PUBKEYS_FILE);
58948
+ const path6 = join27(projectRoot, OWNER_PUBKEYS_FILE);
58452
58949
  try {
58453
58950
  const raw = await readFile4(path6, "utf-8");
58454
58951
  const parsed = JSON.parse(raw);
@@ -58532,7 +59029,7 @@ var init_revert = __esm({
58532
59029
  if (attestation && allowedPubkeys.size > 0 && !allowedPubkeys.has(attestation.ownerPubkey)) {
58533
59030
  emitFailure2(
58534
59031
  E_OWNER_ATTESTATION_REQUIRED,
58535
- `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join28(projectRoot, OWNER_PUBKEYS_FILE)}`,
59032
+ `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join27(projectRoot, OWNER_PUBKEYS_FILE)}`,
58536
59033
  jsonMode
58537
59034
  );
58538
59035
  }
@@ -58585,7 +59082,7 @@ ${lines}`
58585
59082
  identity,
58586
59083
  includeHuman
58587
59084
  });
58588
- const statePath = join28(projectRoot, SENTIENT_STATE_FILE);
59085
+ const statePath = join27(projectRoot, SENTIENT_STATE_FILE);
58589
59086
  const state = await readSentientState(statePath);
58590
59087
  emitSuccess(
58591
59088
  {
@@ -59055,7 +59552,7 @@ __export(self_update_exports, {
59055
59552
  });
59056
59553
  import { execFile } from "node:child_process";
59057
59554
  import { readFile as readFile5 } from "node:fs/promises";
59058
- import { join as join29 } from "node:path";
59555
+ import { join as join28 } from "node:path";
59059
59556
  import * as readline2 from "node:readline";
59060
59557
  import { promisify } from "node:util";
59061
59558
  import {
@@ -59070,7 +59567,7 @@ import {
59070
59567
  async function getCurrentVersion() {
59071
59568
  const cleoHome = getCleoHome4();
59072
59569
  try {
59073
- const content = await readFile5(join29(cleoHome, "VERSION"), "utf-8");
59570
+ const content = await readFile5(join28(cleoHome, "VERSION"), "utf-8");
59074
59571
  return (content.split("\n")[0] ?? "unknown").trim();
59075
59572
  } catch {
59076
59573
  return "unknown";
@@ -59124,7 +59621,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
59124
59621
  ];
59125
59622
  await import("node:fs/promises").then(
59126
59623
  ({ writeFile: writeFile4, mkdir: mkdir5 }) => mkdir5(cleoHome, { recursive: true }).then(
59127
- () => writeFile4(join29(cleoHome, "VERSION"), `${lines.join("\n")}
59624
+ () => writeFile4(join28(cleoHome, "VERSION"), `${lines.join("\n")}
59128
59625
  `, "utf-8")
59129
59626
  )
59130
59627
  );
@@ -59535,7 +60032,7 @@ var sentient_exports = {};
59535
60032
  __export(sentient_exports, {
59536
60033
  sentientCommand: () => sentientCommand
59537
60034
  });
59538
- import { join as join30 } from "node:path";
60035
+ import { join as join29 } from "node:path";
59539
60036
  import { cwd as processCwd3 } from "node:process";
59540
60037
  import {
59541
60038
  getSentientDaemonStatus as getSentientDaemonStatus2,
@@ -59610,7 +60107,7 @@ var init_sentient3 = __esm({
59610
60107
  return;
59611
60108
  }
59612
60109
  if (dryRun) {
59613
- const statePath2 = join30(projectRoot, SENTIENT_STATE_FILE2);
60110
+ const statePath2 = join29(projectRoot, SENTIENT_STATE_FILE2);
59614
60111
  const outcome = await safeRunTick({ projectRoot, statePath: statePath2, dryRun: true });
59615
60112
  emitSuccess2(
59616
60113
  { dryRun: true, outcome },
@@ -59726,7 +60223,7 @@ Logs: ${logPath}`
59726
60223
  const jsonMode = args.json === true;
59727
60224
  const dryRun = args["dry-run"] === true;
59728
60225
  try {
59729
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60226
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59730
60227
  const outcome = await safeRunTick({ projectRoot, statePath, dryRun });
59731
60228
  emitSuccess2(
59732
60229
  { outcome, dryRun },
@@ -59795,7 +60292,7 @@ Logs: ${logPath}`
59795
60292
  return;
59796
60293
  }
59797
60294
  await db.update(tasks).set({ status: "pending", updatedAt: now }).where(eq2(tasks.id, id)).run();
59798
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60295
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59799
60296
  const state = await readSentientState2(statePath);
59800
60297
  await patchSentientState(statePath, {
59801
60298
  tier2Stats: {
@@ -59847,7 +60344,7 @@ Logs: ${logPath}`
59847
60344
  return;
59848
60345
  }
59849
60346
  await db.update(tasks).set({ status: "cancelled", cancellationReason: reason, cancelledAt: now, updatedAt: now }).where(eq2(tasks.id, id)).run();
59850
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60347
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59851
60348
  const state = await readSentientState2(statePath);
59852
60349
  await patchSentientState(statePath, {
59853
60350
  tier2Stats: {
@@ -59892,7 +60389,7 @@ Logs: ${logPath}`
59892
60389
  const projectRoot = resolveProjectRoot6(args.project);
59893
60390
  const jsonMode = args.json === true;
59894
60391
  try {
59895
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60392
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59896
60393
  const outcome = await safeRunProposeTick({ projectRoot, statePath });
59897
60394
  emitSuccess2(
59898
60395
  { outcome },
@@ -59912,7 +60409,7 @@ Logs: ${logPath}`
59912
60409
  const projectRoot = resolveProjectRoot6(args.project);
59913
60410
  const jsonMode = args.json === true;
59914
60411
  try {
59915
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60412
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59916
60413
  const updated = await patchSentientState(statePath, { tier2Enabled: true });
59917
60414
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals enabled");
59918
60415
  } catch (err) {
@@ -59931,7 +60428,7 @@ Logs: ${logPath}`
59931
60428
  const projectRoot = resolveProjectRoot6(args.project);
59932
60429
  const jsonMode = args.json === true;
59933
60430
  try {
59934
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60431
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59935
60432
  const updated = await patchSentientState(statePath, { tier2Enabled: false });
59936
60433
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals disabled");
59937
60434
  } catch (err) {
@@ -59962,7 +60459,7 @@ Logs: ${logPath}`
59962
60459
  const projectRoot = resolveProjectRoot6(args.project);
59963
60460
  const jsonMode = args.json === true;
59964
60461
  try {
59965
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60462
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59966
60463
  const state = await readSentientState2(statePath);
59967
60464
  emitSuccess2(
59968
60465
  {
@@ -60520,7 +61017,7 @@ var sequence_exports = {};
60520
61017
  __export(sequence_exports, {
60521
61018
  sequenceCommand: () => sequenceCommand
60522
61019
  });
60523
- import { getProjectRoot as getProjectRoot42 } from "@cleocode/core/internal";
61020
+ import { getProjectRoot as getProjectRoot44 } from "@cleocode/core/internal";
60524
61021
  var showCommand12, checkCommand6, repairCommand2, sequenceCommand;
60525
61022
  var init_sequence = __esm({
60526
61023
  "packages/cleo/src/cli/commands/sequence.ts"() {
@@ -60556,7 +61053,7 @@ var init_sequence = __esm({
60556
61053
  meta: { name: "repair", description: "Reset counter to max + 1 if behind" },
60557
61054
  async run() {
60558
61055
  const { repairSequence } = await import("@cleocode/core/internal");
60559
- const projectRoot = getProjectRoot42();
61056
+ const projectRoot = getProjectRoot44();
60560
61057
  const repair = await repairSequence(projectRoot);
60561
61058
  const result = {
60562
61059
  repaired: repair.repaired,
@@ -61011,8 +61508,8 @@ var init_session4 = __esm({
61011
61508
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
61012
61509
  },
61013
61510
  async run({ args }) {
61014
- const { detectSessionDrift, getProjectRoot: getProjectRoot46 } = await import("@cleocode/core");
61015
- const projectRoot = await getProjectRoot46();
61511
+ const { detectSessionDrift, getProjectRoot: getProjectRoot48 } = await import("@cleocode/core");
61512
+ const projectRoot = await getProjectRoot48();
61016
61513
  const scope = args["audit-scope"] === "local" ? "local" : "global";
61017
61514
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
61018
61515
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -63778,7 +64275,7 @@ __export(token_exports, {
63778
64275
  tokenCommand: () => tokenCommand
63779
64276
  });
63780
64277
  import { readFileSync as readFileSync16 } from "node:fs";
63781
- import { getProjectRoot as getProjectRoot43, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
64278
+ import { getProjectRoot as getProjectRoot45, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
63782
64279
  function readPayload(args, textKey, fileKey) {
63783
64280
  const text = args[textKey];
63784
64281
  const file = args[fileKey];
@@ -63942,7 +64439,7 @@ var init_token = __esm({
63942
64439
  domain: args.domain,
63943
64440
  operation: args.operation
63944
64441
  };
63945
- const result = args.record ? await recordTokenExchange2(getProjectRoot43(), input2) : await measureTokenExchange(input2);
64442
+ const result = args.record ? await recordTokenExchange2(getProjectRoot45(), input2) : await measureTokenExchange(input2);
63946
64443
  cliOutput(result, {
63947
64444
  command: "token",
63948
64445
  operation: args.record ? "admin.token.record" : "token.estimate"
@@ -63977,8 +64474,8 @@ __export(transcript_exports, {
63977
64474
  transcriptCommand: () => transcriptCommand
63978
64475
  });
63979
64476
  import { homedir as homedir6 } from "node:os";
63980
- import { join as join31 } from "node:path";
63981
- import { getProjectRoot as getProjectRoot44 } from "@cleocode/core";
64477
+ import { join as join30 } from "node:path";
64478
+ import { getProjectRoot as getProjectRoot46 } from "@cleocode/core";
63982
64479
  import {
63983
64480
  parseDurationMs,
63984
64481
  pruneTranscripts,
@@ -64008,7 +64505,7 @@ var init_transcript = __esm({
64008
64505
  async run({ args }) {
64009
64506
  if (args.pending) {
64010
64507
  try {
64011
- const projectRoot = getProjectRoot44();
64508
+ const projectRoot = getProjectRoot46();
64012
64509
  const { scanPendingTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
64013
64510
  const pending = await scanPendingTranscripts(projectRoot);
64014
64511
  cliOutput(
@@ -64031,7 +64528,7 @@ var init_transcript = __esm({
64031
64528
  }
64032
64529
  return;
64033
64530
  }
64034
- const projectsDir = args["projects-dir"] ?? join31(homedir6(), ".claude", "projects");
64531
+ const projectsDir = args["projects-dir"] ?? join30(homedir6(), ".claude", "projects");
64035
64532
  try {
64036
64533
  const result = await scanTranscripts(projectsDir);
64037
64534
  cliOutput(
@@ -64105,7 +64602,7 @@ var init_transcript = __esm({
64105
64602
  async run({ args }) {
64106
64603
  const tier = args.tier ?? "warm";
64107
64604
  const dryRun = args["dry-run"] ?? false;
64108
- const projectRoot = getProjectRoot44();
64605
+ const projectRoot = getProjectRoot46();
64109
64606
  try {
64110
64607
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
64111
64608
  const { findSessionTranscriptPath, listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -64217,7 +64714,7 @@ var init_transcript = __esm({
64217
64714
  const dryRun = args["dry-run"] ?? false;
64218
64715
  const olderThanHours = args["older-than-hours"] ? Number.parseInt(args["older-than-hours"], 10) : 24;
64219
64716
  const limit = args.limit ? Number.parseInt(args.limit, 10) : void 0;
64220
- const projectRoot = getProjectRoot44();
64717
+ const projectRoot = getProjectRoot46();
64221
64718
  try {
64222
64719
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
64223
64720
  const { listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -64337,7 +64834,7 @@ var init_transcript = __esm({
64337
64834
  process.exit(2);
64338
64835
  return;
64339
64836
  }
64340
- const projectsDir = args["projects-dir"] ?? join31(homedir6(), ".claude", "projects");
64837
+ const projectsDir = args["projects-dir"] ?? join30(homedir6(), ".claude", "projects");
64341
64838
  try {
64342
64839
  const pruneResult = await pruneTranscripts({
64343
64840
  olderThanMs,
@@ -65014,15 +65511,15 @@ __export(web_exports, {
65014
65511
  });
65015
65512
  import { execFileSync as execFileSync3, spawn as spawn3 } from "node:child_process";
65016
65513
  import { mkdir as mkdir4, open, readFile as readFile6, rm, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
65017
- import { join as join32 } from "node:path";
65514
+ import { join as join31 } from "node:path";
65018
65515
  import { CleoError as CleoError11, formatError as formatError7, getCleoHome as getCleoHome5 } from "@cleocode/core";
65019
65516
  function getWebPaths() {
65020
65517
  const cleoHome = getCleoHome5();
65021
65518
  return {
65022
- pidFile: join32(cleoHome, "web-server.pid"),
65023
- configFile: join32(cleoHome, "web-server.json"),
65024
- logDir: join32(cleoHome, "logs"),
65025
- logFile: join32(cleoHome, "logs", "web-server.log")
65519
+ pidFile: join31(cleoHome, "web-server.pid"),
65520
+ configFile: join31(cleoHome, "web-server.json"),
65521
+ logDir: join31(cleoHome, "logs"),
65522
+ logFile: join31(cleoHome, "logs", "web-server.log")
65026
65523
  };
65027
65524
  }
65028
65525
  function isProcessRunning(pid) {
@@ -65061,7 +65558,7 @@ async function startWebServer(port, host) {
65061
65558
  throw new CleoError11(1 /* GENERAL_ERROR */, `Server already running (PID: ${status.pid})`);
65062
65559
  }
65063
65560
  const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
65064
- const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join32(projectRoot, "packages", "studio", "build");
65561
+ const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join31(projectRoot, "packages", "studio", "build");
65065
65562
  await mkdir4(logDir, { recursive: true });
65066
65563
  await writeFile3(
65067
65564
  configFile,
@@ -65071,7 +65568,7 @@ async function startWebServer(port, host) {
65071
65568
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
65072
65569
  })
65073
65570
  );
65074
- const webIndexPath = join32(studioDir, "index.js");
65571
+ const webIndexPath = join31(studioDir, "index.js");
65075
65572
  try {
65076
65573
  await stat2(webIndexPath);
65077
65574
  } catch {
@@ -65344,7 +65841,7 @@ __export(worktree_exports, {
65344
65841
  worktreeCommand: () => worktreeCommand
65345
65842
  });
65346
65843
  import readline4 from "node:readline";
65347
- import { getProjectRoot as getProjectRoot45, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
65844
+ import { getProjectRoot as getProjectRoot47, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
65348
65845
  async function promptYesNo2(question) {
65349
65846
  return new Promise((resolve7) => {
65350
65847
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
@@ -65449,7 +65946,7 @@ var init_worktree3 = __esm({
65449
65946
  const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
65450
65947
  const idleDaysRaw = typeof args["idle-days"] === "string" ? args["idle-days"] : void 0;
65451
65948
  const idleDays = idleDaysRaw !== void 0 ? Number.parseInt(idleDaysRaw, 10) : void 0;
65452
- const projectRoot = getProjectRoot45();
65949
+ const projectRoot = getProjectRoot47();
65453
65950
  const listResult = await listWorktrees2({
65454
65951
  projectRoot,
65455
65952
  ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
@@ -65685,7 +66182,7 @@ init_dist();
65685
66182
  init_field_context();
65686
66183
  init_format_context();
65687
66184
  import { readFileSync as readFileSync17 } from "node:fs";
65688
- import { dirname as dirname9, join as join34 } from "node:path";
66185
+ import { dirname as dirname9, join as join33 } from "node:path";
65689
66186
  import { fileURLToPath as fileURLToPath7 } from "node:url";
65690
66187
 
65691
66188
  // packages/cleo/src/cli/generated/command-manifest.ts
@@ -65777,7 +66274,7 @@ var COMMAND_MANIFEST = [
65777
66274
  {
65778
66275
  exportName: "backupRecoverSubCommand",
65779
66276
  name: "recover",
65780
- description: "Recover a malformed CLEO database from snapshot",
66277
+ description: "Recover a malformed CLEO database from snapshot \u2014 accepts any role from DB_INVENTORY (T10318)",
65781
66278
  load: async () => (await Promise.resolve().then(() => (init_backup_recover(), backup_recover_exports))).backupRecoverSubCommand
65782
66279
  },
65783
66280
  {
@@ -65984,6 +66481,18 @@ var COMMAND_MANIFEST = [
65984
66481
  description: "Documentation attachment management (add/list/fetch/remove), ",
65985
66482
  load: async () => (await Promise.resolve().then(() => (init_docs3(), docs_exports))).docsCommand
65986
66483
  },
66484
+ {
66485
+ exportName: "doctorDbSubstrateCommand",
66486
+ name: "db-substrate",
66487
+ description: "Walk every DB in the inventory + report integrity, row counts, orphan dirs. ",
66488
+ load: async () => (await Promise.resolve().then(() => (init_doctor_db_substrate(), doctor_db_substrate_exports))).doctorDbSubstrateCommand
66489
+ },
66490
+ {
66491
+ exportName: "doctorLegacyBackupsCommand",
66492
+ name: "legacy-backups",
66493
+ description: "Enumerate legacy *-pre-cleo.db.bak / brain.db.PRE-DUP-FIX-* / pre-untrack / rotation-overflow ",
66494
+ load: async () => (await Promise.resolve().then(() => (init_doctor_legacy_backups(), doctor_legacy_backups_exports))).doctorLegacyBackupsCommand
66495
+ },
65987
66496
  {
65988
66497
  exportName: "doctorProjectsCommand",
65989
66498
  name: "doctor-projects",
@@ -66682,12 +67191,12 @@ init_did_you_mean();
66682
67191
 
66683
67192
  // packages/cleo/src/cli/lib/first-run-detection.ts
66684
67193
  import { existsSync as existsSync16 } from "node:fs";
66685
- import { join as join33 } from "node:path";
67194
+ import { join as join32 } from "node:path";
66686
67195
  async function detectFirstRun() {
66687
67196
  const envKey = process.env["ANTHROPIC_API_KEY"];
66688
67197
  if (typeof envKey === "string" && envKey.length > 0) return false;
66689
67198
  const { getCleoPlatformPaths } = await import("@cleocode/paths");
66690
- const configPath = join33(getCleoPlatformPaths().config, "config.json");
67199
+ const configPath = join32(getCleoPlatformPaths().config, "config.json");
66691
67200
  if (existsSync16(configPath)) return false;
66692
67201
  try {
66693
67202
  const { getCredentialPool } = await import("@cleocode/core/llm/credential-pool.js");
@@ -66802,7 +67311,7 @@ Or via NodeSource: https://github.com/nodesource/distributions
66802
67311
  }
66803
67312
  }
66804
67313
  function getPackageVersion() {
66805
- const pkgPath = join34(dirname9(fileURLToPath7(import.meta.url)), "../../package.json");
67314
+ const pkgPath = join33(dirname9(fileURLToPath7(import.meta.url)), "../../package.json");
66806
67315
  const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
66807
67316
  return pkg.version;
66808
67317
  }
@@ -66955,7 +67464,7 @@ async function runStartupMaintenance() {
66955
67464
  detectAndRemoveStrayProjectNexus,
66956
67465
  getGlobalSalt,
66957
67466
  getLogger: getLogger21,
66958
- getProjectRoot: getProjectRoot46,
67467
+ getProjectRoot: getProjectRoot48,
66959
67468
  isCleanupMarkerSet,
66960
67469
  migrateSignaldockToConduit,
66961
67470
  needsSignaldockToConduitMigration,
@@ -66964,7 +67473,7 @@ async function runStartupMaintenance() {
66964
67473
  } = await import("@cleocode/core/internal");
66965
67474
  let projectRootForCleanup = "";
66966
67475
  try {
66967
- projectRootForCleanup = getProjectRoot46();
67476
+ projectRootForCleanup = getProjectRoot48();
66968
67477
  } catch {
66969
67478
  }
66970
67479
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -66984,7 +67493,7 @@ async function runStartupMaintenance() {
66984
67493
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
66985
67494
  if (!isInitInvocation) {
66986
67495
  try {
66987
- const _projectRootForMigration = getProjectRoot46();
67496
+ const _projectRootForMigration = getProjectRoot48();
66988
67497
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
66989
67498
  const migrationResult = migrateSignaldockToConduit(_projectRootForMigration);
66990
67499
  if (migrationResult.status === "failed") {