@cleocode/cleo 2026.5.109 → 2026.5.111

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,8 +16199,12 @@ import {
16168
16199
  getCleoDirAbsolute,
16169
16200
  getProjectRoot as getProjectRoot5,
16170
16201
  memoryObserve as memoryObserve2,
16202
+ parseChangesetFrontmatter,
16203
+ releaseReservedSlug,
16204
+ reserveSlugForDispatch,
16171
16205
  resolveAttachmentBackend,
16172
- SlugCollisionError
16206
+ SlugCollisionError,
16207
+ writeChangesetEntry
16173
16208
  } from "@cleocode/core/internal";
16174
16209
  function getDocKindRegistry() {
16175
16210
  const root = getProjectRoot5();
@@ -16676,6 +16711,105 @@ var init_docs2 = __esm({
16676
16711
  }
16677
16712
  type2 = rawType;
16678
16713
  }
16714
+ if (type2 === "changeset") {
16715
+ if (!filePath) {
16716
+ return lafsError(
16717
+ "E_INVALID_INPUT",
16718
+ "changeset writes require a --file path (URL attachments are not supported for changesets)",
16719
+ "add"
16720
+ );
16721
+ }
16722
+ const absPath = resolve2(filePath);
16723
+ let bytes;
16724
+ try {
16725
+ bytes = await readFile(absPath);
16726
+ } catch {
16727
+ return lafsError("E_FILE_ERROR", `Cannot read file: ${absPath}`, "add");
16728
+ }
16729
+ const parsed = parseChangesetFrontmatter(bytes.toString("utf-8"));
16730
+ if (!parsed.ok) {
16731
+ let message;
16732
+ if (parsed.error === "missing-frontmatter") {
16733
+ message = "changeset file is missing the `---`-fenced YAML frontmatter. Required fields: id, tasks, kind, summary.";
16734
+ } else if (parsed.error === "missing-required") {
16735
+ message = `changeset frontmatter is missing required fields: ${parsed.missing.join(", ")}.`;
16736
+ } else if (parsed.error === "yaml-invalid") {
16737
+ const lineHint = parsed.line !== void 0 ? ` (line ${parsed.line})` : "";
16738
+ message = `changeset frontmatter YAML is invalid${lineHint}: ${parsed.parserMessage}`;
16739
+ } else {
16740
+ message = `changeset frontmatter failed schema validation: ${parsed.issues.join("; ")}`;
16741
+ }
16742
+ return {
16743
+ success: false,
16744
+ error: {
16745
+ code: "E_REQUIRES_CHANGESET_VERB",
16746
+ message,
16747
+ details: {
16748
+ fix: "Use `cleo changeset add --slug <id> --tasks <T####> --kind <kind> --summary <text>` for guided authoring.",
16749
+ parserError: parsed.error,
16750
+ ...parsed.error === "missing-required" ? { missing: parsed.missing } : {},
16751
+ ...parsed.error === "schema-invalid" ? { issues: parsed.issues } : {}
16752
+ }
16753
+ }
16754
+ };
16755
+ }
16756
+ if (slug !== void 0 && slug !== parsed.entry.id) {
16757
+ return {
16758
+ success: false,
16759
+ error: {
16760
+ code: "E_SLUG_MISMATCH",
16761
+ message: `--slug '${slug}' does not match changeset frontmatter id '${parsed.entry.id}'. The frontmatter is canonical \u2014 drop --slug or align it.`
16762
+ }
16763
+ };
16764
+ }
16765
+ const outcome = await writeChangesetEntry(parsed.entry, {
16766
+ projectRoot: getProjectRoot5(),
16767
+ attachedBy: typeof rawAttachedBy === "string" && rawAttachedBy.length > 0 ? rawAttachedBy : "cleo-docs-add"
16768
+ });
16769
+ if (!outcome.ok) {
16770
+ const err = outcome.error;
16771
+ if (err.code === "E_SLUG_PATTERN_MISMATCH") {
16772
+ const hint = err.example ? ` (example: ${err.example})` : "";
16773
+ return lafsError("E_SLUG_PATTERN_MISMATCH", `${err.message}${hint}`, "add");
16774
+ }
16775
+ if (err.code === "E_INVALID_ENTRY") {
16776
+ return lafsError("E_INVALID_INPUT", err.message, "add");
16777
+ }
16778
+ if (err.code === "E_FILE_WRITE_FAILED") {
16779
+ return lafsError("E_FILE_ERROR", err.message, "add");
16780
+ }
16781
+ return lafsError("E_SSOT_WRITE_FAILED", err.message, "add");
16782
+ }
16783
+ const changesetPayload = {
16784
+ kind: "doc-attachment",
16785
+ attachmentId: outcome.result.attachmentId,
16786
+ ownerId: outcome.result.ownerId,
16787
+ addedAt: (/* @__PURE__ */ new Date()).toISOString(),
16788
+ slug: outcome.result.slug,
16789
+ type: "changeset"
16790
+ };
16791
+ emitDocAttachmentObservation(changesetPayload, getProjectRoot5());
16792
+ return lafsSuccess(
16793
+ {
16794
+ attachmentId: outcome.result.attachmentId,
16795
+ sha256: outcome.result.sha256,
16796
+ // writeChangesetEntry returns a freshly-minted ref so refCount is 1
16797
+ // (or more if the same content was already addressed by another
16798
+ // owner). The store sets the canonical value; mirroring it here
16799
+ // keeps the envelope shape identical to the file/url branches.
16800
+ refCount: 1,
16801
+ kind: "blob",
16802
+ ownerId: outcome.result.ownerId,
16803
+ ownerType: "task",
16804
+ // Changeset writes land in the legacy attachment store; v2 mirror
16805
+ // is not applicable to the dual-write transaction.
16806
+ attachmentBackend: "legacy",
16807
+ slug: outcome.result.slug,
16808
+ type: "changeset"
16809
+ },
16810
+ "add"
16811
+ );
16812
+ }
16679
16813
  if (type2 !== void 0 && slug !== void 0) {
16680
16814
  const patternCheck = getDocKindRegistry().validateSlug(type2, slug);
16681
16815
  if (!patternCheck.ok) {
@@ -16683,6 +16817,25 @@ var init_docs2 = __esm({
16683
16817
  return lafsError("E_SLUG_PATTERN_MISMATCH", `${patternCheck.error}${exampleHint}`, "add");
16684
16818
  }
16685
16819
  }
16820
+ if (slug !== void 0) {
16821
+ const reservation = await reserveSlugForDispatch(getProjectRoot5(), {
16822
+ kind: type2 ?? "",
16823
+ slug
16824
+ });
16825
+ if (!reservation.ok) {
16826
+ return {
16827
+ success: false,
16828
+ error: {
16829
+ code: "E_SLUG_RESERVED",
16830
+ message: `slug '${slug}' is already in use in this project`,
16831
+ details: {
16832
+ suggestions: reservation.suggestions,
16833
+ aliases: ["E_SLUG_TAKEN"]
16834
+ }
16835
+ }
16836
+ };
16837
+ }
16838
+ }
16686
16839
  const extras = {};
16687
16840
  if (slug !== void 0) extras.slug = slug;
16688
16841
  if (type2 !== void 0) extras.type = type2;
@@ -16719,13 +16872,17 @@ var init_docs2 = __esm({
16719
16872
  extras
16720
16873
  );
16721
16874
  } catch (err) {
16875
+ if (slug !== void 0) releaseReservedSlug(slug);
16722
16876
  if (err instanceof SlugCollisionError) {
16723
16877
  return {
16724
16878
  success: false,
16725
16879
  error: {
16726
- code: "E_SLUG_TAKEN",
16880
+ code: "E_SLUG_RESERVED",
16727
16881
  message: `slug '${err.slug}' is already in use in this project`,
16728
- details: { suggestions: err.suggestions }
16882
+ details: {
16883
+ suggestions: err.suggestions,
16884
+ aliases: ["E_SLUG_TAKEN"]
16885
+ }
16729
16886
  }
16730
16887
  };
16731
16888
  }
@@ -16797,13 +16954,17 @@ var init_docs2 = __esm({
16797
16954
  extras
16798
16955
  );
16799
16956
  } catch (err) {
16957
+ if (slug !== void 0) releaseReservedSlug(slug);
16800
16958
  if (err instanceof SlugCollisionError) {
16801
16959
  return {
16802
16960
  success: false,
16803
16961
  error: {
16804
- code: "E_SLUG_TAKEN",
16962
+ code: "E_SLUG_RESERVED",
16805
16963
  message: `slug '${err.slug}' is already in use in this project`,
16806
- details: { suggestions: err.suggestions }
16964
+ details: {
16965
+ suggestions: err.suggestions,
16966
+ aliases: ["E_SLUG_TAKEN"]
16967
+ }
16807
16968
  }
16808
16969
  };
16809
16970
  }
@@ -16969,6 +17130,7 @@ import {
16969
17130
  createAttachmentStore as createAttachmentStore2,
16970
17131
  memoryFind as memoryFind2,
16971
17132
  orchestrateReady as orchestrateReady2,
17133
+ sagas,
16972
17134
  taskRelates as taskRelates2,
16973
17135
  taskShow as taskShow2
16974
17136
  } from "@cleocode/core/internal";
@@ -17070,8 +17232,7 @@ async function buildFocusEnvelope(id, projectRoot) {
17070
17232
  };
17071
17233
  }
17072
17234
  const task = showResult.data.task;
17073
- const labels = Array.isArray(task.labels) ? task.labels : [];
17074
- const isSaga = labels.includes("saga");
17235
+ const isSaga = sagas.isSagaType(task);
17075
17236
  const isEpic = task.type === "epic" && !isSaga;
17076
17237
  const entityType = isSaga ? "saga" : isEpic ? "epic" : "task";
17077
17238
  const identity = {
@@ -25211,8 +25372,8 @@ async function loadPlaybookByName(name) {
25211
25372
  return null;
25212
25373
  }
25213
25374
  try {
25214
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core/internal");
25215
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot46();
25375
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25376
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot48();
25216
25377
  const resolved = resolvePlaybook(name, {
25217
25378
  projectRoot,
25218
25379
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -25256,8 +25417,8 @@ async function acquireDb() {
25256
25417
  async function buildDefaultDispatcher() {
25257
25418
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
25258
25419
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
25259
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core/internal");
25260
- const projectRoot = getProjectRoot46();
25420
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25421
+ const projectRoot = getProjectRoot48();
25261
25422
  return {
25262
25423
  async dispatch(input2) {
25263
25424
  try {
@@ -25447,8 +25608,8 @@ var init_playbook2 = __esm({
25447
25608
  projectRoot = __playbookRuntimeOverrides.projectRoot;
25448
25609
  } else {
25449
25610
  try {
25450
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core/internal");
25451
- projectRoot = getProjectRoot46();
25611
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25612
+ projectRoot = getProjectRoot48();
25452
25613
  } catch {
25453
25614
  projectRoot = void 0;
25454
25615
  }
@@ -25512,14 +25673,14 @@ var init_playbook2 = __esm({
25512
25673
  const dispatcher = await buildDefaultDispatcher();
25513
25674
  let result;
25514
25675
  try {
25515
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core/internal");
25676
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25516
25677
  const opts = {
25517
25678
  db,
25518
25679
  playbook: parsed.definition,
25519
25680
  playbookHash: parsed.sourceHash,
25520
25681
  initialContext,
25521
25682
  dispatcher,
25522
- projectRoot: getProjectRoot46()
25683
+ projectRoot: getProjectRoot48()
25523
25684
  };
25524
25685
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
25525
25686
  opts.approvalSecret = __playbookRuntimeOverrides.approvalSecret;
@@ -25884,7 +26045,7 @@ async function orchestrateClassify(request, context, projectRoot) {
25884
26045
  try {
25885
26046
  const { getCleoCantWorkflowsDir } = await import("@cleocode/core/internal");
25886
26047
  const { readFileSync: readFileSync18, readdirSync: readdirSync3, existsSync: existsSync17 } = await import("node:fs");
25887
- const { join: join35 } = await import("node:path");
26048
+ const { join: join34 } = await import("node:path");
25888
26049
  const workflowsDir = getCleoCantWorkflowsDir();
25889
26050
  const combined = `${request} ${context ?? ""}`.toLowerCase();
25890
26051
  const matches = [];
@@ -25892,7 +26053,7 @@ async function orchestrateClassify(request, context, projectRoot) {
25892
26053
  const files = readdirSync3(workflowsDir).filter((f) => f.endsWith(".cant"));
25893
26054
  for (const file of files) {
25894
26055
  try {
25895
- const src = readFileSync18(join35(workflowsDir, file), "utf-8");
26056
+ const src = readFileSync18(join34(workflowsDir, file), "utf-8");
25896
26057
  const teamMatch = /^team\s+(\S+):/m.exec(src);
25897
26058
  if (!teamMatch) continue;
25898
26059
  const teamName = teamMatch[1];
@@ -25907,12 +26068,12 @@ async function orchestrateClassify(request, context, projectRoot) {
25907
26068
  }
25908
26069
  }
25909
26070
  }
25910
- const localCantDir = join35(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
26071
+ const localCantDir = join34(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
25911
26072
  if (existsSync17(localCantDir)) {
25912
26073
  const files = readdirSync3(localCantDir).filter((f) => f.endsWith(".cant"));
25913
26074
  for (const file of files) {
25914
26075
  try {
25915
- const src = readFileSync18(join35(localCantDir, file), "utf-8");
26076
+ const src = readFileSync18(join34(localCantDir, file), "utf-8");
25916
26077
  const teamMatch = /^team\s+(\S+):/m.exec(src);
25917
26078
  if (!teamMatch) continue;
25918
26079
  const teamName = teamMatch[1];
@@ -31307,11 +31468,11 @@ var init_security = __esm({
31307
31468
  });
31308
31469
 
31309
31470
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
31310
- function createSanitizer(getProjectRoot46) {
31471
+ function createSanitizer(getProjectRoot48) {
31311
31472
  return async (req, next) => {
31312
31473
  if (req.params) {
31313
31474
  try {
31314
- const root = getProjectRoot46 ? getProjectRoot46() : void 0;
31475
+ const root = getProjectRoot48 ? getProjectRoot48() : void 0;
31315
31476
  req.params = sanitizeParams(req.params, root, {
31316
31477
  domain: req.domain,
31317
31478
  operation: req.operation
@@ -32903,9 +33064,9 @@ var init_agent = __esm({
32903
33064
  isActive: true
32904
33065
  });
32905
33066
  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`);
33067
+ const { join: join34 } = await import("node:path");
33068
+ const cantDir = join34(CLEO_DIR_NAME, AGENTS_SUBDIR);
33069
+ const cantPath = join34(cantDir, `${agentId}.cant`);
32909
33070
  let cantScaffolded = false;
32910
33071
  if (!existsSync17(cantPath)) {
32911
33072
  mkdirSync5(cantDir, { recursive: true });
@@ -33087,7 +33248,7 @@ agent ${agentId}:
33087
33248
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
33088
33249
  const { createRuntime } = await import("@cleocode/runtime");
33089
33250
  const { existsSync: existsSync17, readFileSync: readFileSync18 } = await import("node:fs");
33090
- const { join: join35 } = await import("node:path");
33251
+ const { join: join34 } = await import("node:path");
33091
33252
  await openCleoDb("tasks");
33092
33253
  const registry = new AgentRegistryAccessor(getProjectRoot24());
33093
33254
  const credential = await registry.get(args.agentId);
@@ -33107,7 +33268,7 @@ agent ${agentId}:
33107
33268
  }
33108
33269
  let profile = null;
33109
33270
  let cantValidation = null;
33110
- const cantPath = args.cant ?? join35(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33271
+ const cantPath = args.cant ?? join34(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33111
33272
  if (existsSync17(cantPath)) {
33112
33273
  profile = readFileSync18(cantPath, "utf-8");
33113
33274
  try {
@@ -33633,7 +33794,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33633
33794
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
33634
33795
  const { createRuntime } = await import("@cleocode/runtime");
33635
33796
  const { existsSync: existsSync17 } = await import("node:fs");
33636
- const { join: join35 } = await import("node:path");
33797
+ const { join: join34 } = await import("node:path");
33637
33798
  await openCleoDb("tasks");
33638
33799
  const registry = new AgentRegistryAccessor(getProjectRoot24());
33639
33800
  const credential = await registry.get(args.agentId);
@@ -33650,7 +33811,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33650
33811
  }
33651
33812
  await registry.update(args.agentId, { isActive: true });
33652
33813
  await registry.markUsed(args.agentId);
33653
- const cantPath = join35(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33814
+ const cantPath = join34(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33654
33815
  const hasProfile = existsSync17(cantPath);
33655
33816
  const runtime = await createRuntime(registry, {
33656
33817
  agentId: args.agentId,
@@ -34593,8 +34754,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34593
34754
  process.exitCode = 4;
34594
34755
  return;
34595
34756
  }
34596
- const { join: join35 } = await import("node:path");
34597
- const personaPath = join35(resolvedDir, "persona.cant");
34757
+ const { join: join34 } = await import("node:path");
34758
+ const personaPath = join34(resolvedDir, "persona.cant");
34598
34759
  if (!existsSync17(personaPath)) {
34599
34760
  cliOutput(
34600
34761
  {
@@ -34642,7 +34803,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34642
34803
  if (entry.isFile()) {
34643
34804
  fileCount++;
34644
34805
  } else if (entry.isDirectory()) {
34645
- countFiles(join35(dirPath, entry.name));
34806
+ countFiles(join34(dirPath, entry.name));
34646
34807
  }
34647
34808
  }
34648
34809
  };
@@ -34891,7 +35052,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34891
35052
  async run({ args }) {
34892
35053
  try {
34893
35054
  const { existsSync: existsSync17, readFileSync: readFileSync18, mkdirSync: mkdirSync5 } = await import("node:fs");
34894
- const { resolve: resolve7, join: join35 } = await import("node:path");
35055
+ const { resolve: resolve7, join: join34 } = await import("node:path");
34895
35056
  const specPath = resolve7(args.spec);
34896
35057
  if (!existsSync17(specPath)) {
34897
35058
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
@@ -34900,7 +35061,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34900
35061
  }
34901
35062
  const specContent = readFileSync18(specPath, "utf-8");
34902
35063
  const projectRoot = getProjectRoot24();
34903
- const outputDir = args["output-dir"] ? resolve7(args["output-dir"]) : join35(projectRoot, ".cleo", "cant", "agents");
35064
+ const outputDir = args["output-dir"] ? resolve7(args["output-dir"]) : join34(projectRoot, ".cleo", "cant", "agents");
34904
35065
  mkdirSync5(outputDir, { recursive: true });
34905
35066
  if (args["dry-run"]) {
34906
35067
  cliOutput(
@@ -36311,12 +36472,8 @@ __export(backup_recover_exports, {
36311
36472
  backupRecoverBrainLeaf: () => backupRecoverBrainLeaf,
36312
36473
  backupRecoverSubCommand: () => backupRecoverSubCommand
36313
36474
  });
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";
36475
+ import { getLogger as getLogger20, getProjectRoot as getProjectRoot27 } from "@cleocode/core";
36476
+ import { BackupRecoverError, runBackupRecover } from "@cleocode/core/store/backup-recover.js";
36320
36477
  function readBoolFlag(args, key) {
36321
36478
  return args[key] === true;
36322
36479
  }
@@ -36324,6 +36481,68 @@ function readStringFlag(args, key) {
36324
36481
  const v = args[key];
36325
36482
  return typeof v === "string" ? v : "";
36326
36483
  }
36484
+ function executeRecover(role, args) {
36485
+ const projectRoot = getProjectRoot27();
36486
+ const dryRun = readBoolFlag(args, "dry-run");
36487
+ const fromSnapshot = readStringFlag(args, "from-snapshot");
36488
+ const noDelta = readBoolFlag(args, "no-delta");
36489
+ const operation = `backup.recover.${role}`;
36490
+ try {
36491
+ const result = runBackupRecover({
36492
+ role,
36493
+ projectRoot,
36494
+ logger: getLogger20(`backup-recover-${role}`),
36495
+ dryRun,
36496
+ fromSnapshot: fromSnapshot.length > 0 ? fromSnapshot : void 0,
36497
+ noDelta
36498
+ });
36499
+ cliOutput(result, {
36500
+ command: "backup",
36501
+ operation
36502
+ });
36503
+ if (result.dryRun) {
36504
+ humanInfo(
36505
+ `[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}).`
36506
+ );
36507
+ } else {
36508
+ humanInfo(
36509
+ `Recovered "${role}" DB from ${result.restoredFrom}. Corrupt DB quarantined at ${result.quarantinedTo}.`
36510
+ );
36511
+ }
36512
+ } catch (err) {
36513
+ if (err instanceof BackupRecoverError) {
36514
+ cliError(
36515
+ err.message,
36516
+ err.code,
36517
+ {
36518
+ name: err.codeName,
36519
+ ...err.fix ? { fix: err.fix } : {}
36520
+ },
36521
+ { operation }
36522
+ );
36523
+ process.exitCode = err.code;
36524
+ return;
36525
+ }
36526
+ const message = err instanceof Error ? err.message : String(err);
36527
+ cliError(message, 1 /* GENERAL_ERROR */, { name: "E_RECOVERY_FAILED" }, { operation });
36528
+ process.exitCode = 1 /* GENERAL_ERROR */;
36529
+ }
36530
+ }
36531
+ function parseRoleArg(value) {
36532
+ const trimmed = value.trim();
36533
+ for (const entry of DB_INVENTORY) {
36534
+ if (entry.role === trimmed) {
36535
+ return entry.role;
36536
+ }
36537
+ }
36538
+ const validRoles = DB_INVENTORY.map((e) => e.role).join(", ");
36539
+ throw new BackupRecoverError(
36540
+ `Unknown DB role "${trimmed}". Valid roles: ${validRoles}.`,
36541
+ 6 /* VALIDATION_ERROR */,
36542
+ "E_UNKNOWN_ROLE",
36543
+ "Run `cleo backup recover --help` for the list of valid roles."
36544
+ );
36545
+ }
36327
36546
  var backupRecoverBrainLeaf, backupRecoverSubCommand;
36328
36547
  var init_backup_recover = __esm({
36329
36548
  "packages/cleo/src/cli/commands/backup-recover.ts"() {
@@ -36359,43 +36578,67 @@ var init_backup_recover = __esm({
36359
36578
  }
36360
36579
  },
36361
36580
  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
36581
  const argsBag = args;
36369
- const dryRun = readBoolFlag(argsBag, "dry-run");
36370
- const fromSnapshot = readStringFlag(argsBag, "from-snapshot");
36371
- const noDelta = readBoolFlag(argsBag, "no-delta");
36582
+ executeRecover("brain", argsBag);
36583
+ }
36584
+ });
36585
+ backupRecoverSubCommand = defineCommand({
36586
+ meta: {
36587
+ name: "recover",
36588
+ description: "Recover a malformed CLEO database from snapshot \u2014 accepts any role from DB_INVENTORY (T10318)"
36589
+ },
36590
+ args: {
36591
+ role: {
36592
+ type: "positional",
36593
+ description: `Canonical DB role (one of: ${DB_INVENTORY.map((e) => e.role).join(", ")})`,
36594
+ required: false
36595
+ },
36596
+ "dry-run": {
36597
+ type: "boolean",
36598
+ description: "Print what would be done without quarantining or copying any files",
36599
+ default: false
36600
+ },
36601
+ "from-snapshot": {
36602
+ type: "string",
36603
+ description: "Pin recovery to a specific snapshot \u2014 absolute path or ISO timestamp prefix (e.g. 2026-05-23)",
36604
+ default: ""
36605
+ },
36606
+ "no-delta": {
36607
+ type: "boolean",
36608
+ description: "Skip the sqlite3 .recover delta-merge step (reserved \u2014 current pipeline does not delta-merge; flag plumbed for forward-compat)",
36609
+ default: false
36610
+ },
36611
+ force: {
36612
+ type: "boolean",
36613
+ description: "Bypass any safety prompts (currently a no-op; reserved)",
36614
+ default: false
36615
+ }
36616
+ },
36617
+ subCommands: {
36618
+ brain: backupRecoverBrainLeaf
36619
+ },
36620
+ async run({ args }) {
36621
+ const argsBag = args;
36622
+ const roleArg = readStringFlag(argsBag, "role");
36623
+ if (roleArg.length === 0) {
36624
+ const validRoles = DB_INVENTORY.map((e) => e.role).join(", ");
36625
+ cliError(
36626
+ `Missing role. Try \`cleo backup recover <role>\` (one of: ${validRoles}).`,
36627
+ 6 /* VALIDATION_ERROR */,
36628
+ {
36629
+ name: "E_VALIDATION",
36630
+ fix: "Run `cleo backup recover --help` to see available roles and flags."
36631
+ },
36632
+ { operation: "backup.recover" }
36633
+ );
36634
+ process.exitCode = 6 /* VALIDATION_ERROR */;
36635
+ return;
36636
+ }
36637
+ let role;
36372
36638
  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
- }
36639
+ role = parseRoleArg(roleArg);
36397
36640
  } catch (err) {
36398
- if (err instanceof BackupRecoverBrainError) {
36641
+ if (err instanceof BackupRecoverError) {
36399
36642
  cliError(
36400
36643
  err.message,
36401
36644
  err.code,
@@ -36403,44 +36646,89 @@ var init_backup_recover = __esm({
36403
36646
  name: err.codeName,
36404
36647
  ...err.fix ? { fix: err.fix } : {}
36405
36648
  },
36406
- { operation: "backup.recover.brain" }
36649
+ { operation: "backup.recover" }
36407
36650
  );
36408
36651
  process.exitCode = err.code;
36409
36652
  return;
36410
36653
  }
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 */;
36654
+ throw err;
36419
36655
  }
36656
+ executeRecover(role, argsBag);
36420
36657
  }
36421
36658
  });
36422
- backupRecoverSubCommand = defineCommand({
36659
+ }
36660
+ });
36661
+
36662
+ // packages/cleo/src/cli/commands/backup-verify.ts
36663
+ import { getProjectRoot as getProjectRoot28 } from "@cleocode/core";
36664
+ import { runBackupVerify } from "@cleocode/core/store/backup-verify.js";
36665
+ var backupVerifySubCommand;
36666
+ var init_backup_verify = __esm({
36667
+ "packages/cleo/src/cli/commands/backup-verify.ts"() {
36668
+ "use strict";
36669
+ init_src2();
36670
+ init_define_cli_command();
36671
+ init_renderers();
36672
+ backupVerifySubCommand = defineCommand({
36423
36673
  meta: {
36424
- name: "recover",
36425
- description: "Recover a malformed CLEO database from snapshot"
36674
+ name: "verify",
36675
+ 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
36676
  },
36427
- subCommands: {
36428
- brain: backupRecoverBrainLeaf
36677
+ args: {
36678
+ "per-db-timeout-ms": {
36679
+ type: "string",
36680
+ description: "Per-DB integrity-check timeout in milliseconds (default: 30000).",
36681
+ default: "30000"
36682
+ },
36683
+ json: { type: "boolean", description: "Output as JSON" },
36684
+ human: { type: "boolean", description: "Force human-readable output" },
36685
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
36429
36686
  },
36430
36687
  async run({ args }) {
36431
36688
  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 */;
36689
+ const rawTimeout = argsBag["per-db-timeout-ms"];
36690
+ let perDbTimeoutMs = 3e4;
36691
+ if (typeof rawTimeout === "string" && rawTimeout.length > 0) {
36692
+ const parsed = Number.parseInt(rawTimeout, 10);
36693
+ if (!Number.isFinite(parsed) || parsed <= 0) {
36694
+ cliError(
36695
+ `Invalid --per-db-timeout-ms value: ${rawTimeout}`,
36696
+ 6 /* VALIDATION_ERROR */,
36697
+ {
36698
+ name: "E_VALIDATION",
36699
+ fix: "Provide a positive integer number of milliseconds (e.g. --per-db-timeout-ms 30000)."
36700
+ },
36701
+ { operation: "backup.verify" }
36702
+ );
36703
+ process.exitCode = 6 /* VALIDATION_ERROR */;
36704
+ return;
36705
+ }
36706
+ perDbTimeoutMs = parsed;
36707
+ }
36708
+ let result;
36709
+ try {
36710
+ result = runBackupVerify({
36711
+ projectRoot: getProjectRoot28(),
36712
+ perDbTimeoutMs
36713
+ });
36714
+ } catch (err) {
36715
+ const message = err instanceof Error ? err.message : String(err);
36716
+ cliError(
36717
+ message,
36718
+ 1 /* GENERAL_ERROR */,
36719
+ { name: "E_BACKUP_VERIFY_FAILED" },
36720
+ { operation: "backup.verify" }
36721
+ );
36722
+ process.exitCode = 1 /* GENERAL_ERROR */;
36723
+ return;
36724
+ }
36725
+ cliOutput(result, {
36726
+ command: "backup",
36727
+ operation: "backup.verify"
36728
+ });
36729
+ if ((result.summary.corrupt > 0 || result.summary.stale > 0) && (process.exitCode === void 0 || process.exitCode === 0)) {
36730
+ process.exitCode = 1 /* GENERAL_ERROR */;
36731
+ }
36444
36732
  }
36445
36733
  });
36446
36734
  }
@@ -36518,6 +36806,7 @@ var init_backup = __esm({
36518
36806
  init_renderers();
36519
36807
  init_backup_inspect();
36520
36808
  init_backup_recover();
36809
+ init_backup_verify();
36521
36810
  addCommand2 = defineCommand({
36522
36811
  meta: {
36523
36812
  name: "add",
@@ -36601,9 +36890,9 @@ var init_backup = __esm({
36601
36890
  async run({ args }) {
36602
36891
  const scope = args.scope;
36603
36892
  const { packBundle } = await import("@cleocode/core/store/backup-pack.js");
36604
- const { getProjectRoot: getProjectRoot46 } = await import("@cleocode/core");
36893
+ const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core");
36605
36894
  const includesProject = scope === "project" || scope === "all";
36606
- const projectRoot = includesProject ? getProjectRoot46() : void 0;
36895
+ const projectRoot = includesProject ? getProjectRoot48() : void 0;
36607
36896
  let passphrase;
36608
36897
  if (args.encrypt === true) {
36609
36898
  passphrase = process.env["CLEO_BACKUP_PASSPHRASE"];
@@ -36679,12 +36968,12 @@ var init_backup = __esm({
36679
36968
  },
36680
36969
  async run({ args }) {
36681
36970
  const bundlePath = args.bundle;
36682
- const { getProjectRoot: getProjectRoot46, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
36971
+ const { getProjectRoot: getProjectRoot48, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
36683
36972
  const { BundleError, cleanupStaging, unpackBundle } = await import("@cleocode/core/store/backup-unpack.js");
36684
36973
  const { regenerateConfigJson, regenerateProjectContextJson, regenerateProjectInfoJson } = await import("@cleocode/core/store/regenerators.js");
36685
36974
  const { regenerateAndCompare } = await import("@cleocode/core/store/restore-json-merge.js");
36686
36975
  const { buildConflictReport, writeConflictReport } = await import("@cleocode/core/store/restore-conflict-report.js");
36687
- const projectRoot = getProjectRoot46();
36976
+ const projectRoot = getProjectRoot48();
36688
36977
  if (args.force !== true) {
36689
36978
  const existing = checkForExistingData(projectRoot, getCleoHome6());
36690
36979
  if (existing.length > 0) {
@@ -36853,7 +37142,8 @@ var init_backup = __esm({
36853
37142
  export: exportCommand,
36854
37143
  import: importCommand,
36855
37144
  inspect: backupInspectSubCommand,
36856
- recover: backupRecoverSubCommand
37145
+ recover: backupRecoverSubCommand,
37146
+ verify: backupVerifySubCommand
36857
37147
  },
36858
37148
  async run({ cmd, rawArgs }) {
36859
37149
  if (isSubCommandDispatch(rawArgs, cmd.subCommands)) return;
@@ -36903,7 +37193,7 @@ var brain_exports = {};
36903
37193
  __export(brain_exports, {
36904
37194
  brainCommand: () => brainCommand
36905
37195
  });
36906
- import { getProjectRoot as getProjectRoot28 } from "@cleocode/core";
37196
+ import { getProjectRoot as getProjectRoot29 } from "@cleocode/core";
36907
37197
  import {
36908
37198
  backfillBrainGraph,
36909
37199
  exportBrainAsGexf,
@@ -36948,7 +37238,7 @@ var init_brain2 = __esm({
36948
37238
  json: { type: "boolean", description: "Output results as JSON" }
36949
37239
  },
36950
37240
  async run({ args }) {
36951
- const root = getProjectRoot28();
37241
+ const root = getProjectRoot29();
36952
37242
  try {
36953
37243
  const result = await runBrainMaintenance(root, {
36954
37244
  skipDecay: !!args["skip-decay"],
@@ -37019,7 +37309,7 @@ var init_brain2 = __esm({
37019
37309
  json: { type: "boolean", description: "Output results as JSON" }
37020
37310
  },
37021
37311
  async run({ args: _args }) {
37022
- const root = getProjectRoot28();
37312
+ const root = getProjectRoot29();
37023
37313
  try {
37024
37314
  const result = await backfillBrainGraph(root);
37025
37315
  cliOutput(
@@ -37060,7 +37350,7 @@ var init_brain2 = __esm({
37060
37350
  json: { type: "boolean", description: "Output results as JSON" }
37061
37351
  },
37062
37352
  async run({ args: _args }) {
37063
- const root = getProjectRoot28();
37353
+ const root = getProjectRoot29();
37064
37354
  try {
37065
37355
  const result = await purgeBrainNoise(root);
37066
37356
  cliOutput(
@@ -37106,7 +37396,7 @@ var init_brain2 = __esm({
37106
37396
  json: { type: "boolean", description: "Output results as JSON" }
37107
37397
  },
37108
37398
  async run({ args }) {
37109
- const root = getProjectRoot28();
37399
+ const root = getProjectRoot29();
37110
37400
  const limit = Number.parseInt(args.limit, 10) || 20;
37111
37401
  try {
37112
37402
  const stats = await getPlasticityStats(root, limit);
@@ -37156,7 +37446,7 @@ var init_brain2 = __esm({
37156
37446
  json: { type: "boolean", description: "Output results as JSON" }
37157
37447
  },
37158
37448
  async run({ args: _args }) {
37159
- const root = getProjectRoot28();
37449
+ const root = getProjectRoot29();
37160
37450
  try {
37161
37451
  const report = await getMemoryQualityReport(root);
37162
37452
  cliOutput(
@@ -37205,7 +37495,7 @@ var init_brain2 = __esm({
37205
37495
  }
37206
37496
  },
37207
37497
  async run({ args }) {
37208
- const root = getProjectRoot28();
37498
+ const root = getProjectRoot29();
37209
37499
  const format = args.format ?? "gexf";
37210
37500
  if (format !== "gexf" && format !== "json") {
37211
37501
  cliError(`Invalid format: ${format}. Use 'gexf' or 'json'.`, "E_VALIDATION", {
@@ -37286,12 +37576,12 @@ __export(briefing_exports, {
37286
37576
  briefingCommand: () => briefingCommand
37287
37577
  });
37288
37578
  import { existsSync as existsSync9, readFileSync as readFileSync10 } from "node:fs";
37289
- import { join as join12 } from "node:path";
37579
+ import { join as join11 } from "node:path";
37290
37580
  import { pushWarning } from "@cleocode/core";
37291
37581
  import { resolveLegacyCleoDir } from "@cleocode/paths";
37292
37582
  function resolveInjectionTemplatePath() {
37293
37583
  const xdgConfig = resolveLegacyCleoDir(process.env["XDG_CONFIG_HOME"]);
37294
- return join12(xdgConfig, "templates", "CLEO-INJECTION.md");
37584
+ return join11(xdgConfig, "templates", "CLEO-INJECTION.md");
37295
37585
  }
37296
37586
  function extractSection(content, sectionName) {
37297
37587
  const openTag = `<!-- CLEO-INJECTION:section=${sectionName} -->`;
@@ -37530,7 +37820,7 @@ __export(caamp_exports, {
37530
37820
  caampCommand: () => caampCommand
37531
37821
  });
37532
37822
  import { homedir as homedir3 } from "node:os";
37533
- import { join as join13 } from "node:path";
37823
+ import { join as join12 } from "node:path";
37534
37824
  var dedupeCommand, caampCommand;
37535
37825
  var init_caamp = __esm({
37536
37826
  "packages/cleo/src/cli/commands/caamp.ts"() {
@@ -37567,9 +37857,9 @@ var init_caamp = __esm({
37567
37857
  } else {
37568
37858
  const home = homedir3();
37569
37859
  filePaths = [
37570
- join13(home, ".agents", "AGENTS.md"),
37860
+ join12(home, ".agents", "AGENTS.md"),
37571
37861
  // project-level AGENTS.md in cwd
37572
- join13(process.cwd(), "AGENTS.md")
37862
+ join12(process.cwd(), "AGENTS.md")
37573
37863
  ];
37574
37864
  }
37575
37865
  if (args["dry-run"]) {
@@ -37677,7 +37967,7 @@ __export(cant_exports, {
37677
37967
  cantCommand: () => cantCommand
37678
37968
  });
37679
37969
  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";
37970
+ import { dirname as dirname4, isAbsolute, join as join13, resolve as resolve3 } from "node:path";
37681
37971
  function resolveFilePath(file) {
37682
37972
  return isAbsolute(file) ? file : resolve3(process.cwd(), file);
37683
37973
  }
@@ -37842,7 +38132,7 @@ var init_cant = __esm({
37842
38132
  const projectRoot = process.cwd();
37843
38133
  let written = 0;
37844
38134
  for (const outputFile of result.outputFiles) {
37845
- const outputPath = isAbsolute(outputFile.path) ? outputFile.path : join14(projectRoot, outputFile.path);
38135
+ const outputPath = isAbsolute(outputFile.path) ? outputFile.path : join13(projectRoot, outputFile.path);
37846
38136
  mkdirSync2(dirname4(outputPath), { recursive: true });
37847
38137
  writeFileSync3(outputPath, outputFile.content, "utf-8");
37848
38138
  written++;
@@ -38022,8 +38312,14 @@ __export(changeset_exports, {
38022
38312
  changesetCommand: () => changesetCommand
38023
38313
  });
38024
38314
  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";
38315
+ import { join as join14 } from "node:path";
38316
+ import {
38317
+ changesets,
38318
+ dataTable,
38319
+ detectStrayCleoDb,
38320
+ getProjectRoot as getProjectRoot30,
38321
+ resolveWorktreeRouting
38322
+ } from "@cleocode/core";
38027
38323
  function isValidKind(raw) {
38028
38324
  return typeof raw === "string" && CHANGESET_KINDS.includes(raw);
38029
38325
  }
@@ -38117,7 +38413,25 @@ var init_changeset = __esm({
38117
38413
  ...typeof args.notes === "string" && args.notes.length > 0 ? { notes: args.notes } : {},
38118
38414
  ...typeof args.breaking === "string" && args.breaking.length > 0 ? { breaking: args.breaking } : {}
38119
38415
  };
38120
- const projectRoot = getProjectRoot29();
38416
+ const routing = resolveWorktreeRouting();
38417
+ const strayDb = detectStrayCleoDb(routing);
38418
+ if (strayDb) {
38419
+ cliError(
38420
+ `stray .cleo/tasks.db detected inside worktree at ${routing.worktreePath}. This is a leaked CLEO state directory.`,
38421
+ 6 /* VALIDATION_ERROR */,
38422
+ {
38423
+ name: "E_STRAY_WORKTREE_DB",
38424
+ fix: `Remove it with: rm -rf ${routing.worktreePath}/.cleo \u2014 then retry. See ADR-068 \xA73 for the worktree DB isolation rationale.`
38425
+ }
38426
+ );
38427
+ process.exit(6 /* VALIDATION_ERROR */);
38428
+ }
38429
+ if (routing.isWorktree && process.env["CLEO_QUIET"] !== "1") {
38430
+ const routingLog = `[T10389] routing SSoT write from worktree cwd ${routing.cwd} \u2192 canonical project root ${routing.canonicalRoot}
38431
+ `;
38432
+ process.stderr.write(routingLog);
38433
+ }
38434
+ const projectRoot = routing.canonicalRoot;
38121
38435
  const outcome = await changesets.writeChangesetEntry(entry, {
38122
38436
  projectRoot,
38123
38437
  ...typeof args["attached-by"] === "string" && args["attached-by"].length > 0 ? { attachedBy: args["attached-by"] } : {}
@@ -38144,8 +38458,8 @@ var init_changeset = __esm({
38144
38458
  },
38145
38459
  args: {},
38146
38460
  async run() {
38147
- const projectRoot = getProjectRoot29();
38148
- const dir = join15(projectRoot, ".changeset");
38461
+ const projectRoot = getProjectRoot30();
38462
+ const dir = join14(projectRoot, ".changeset");
38149
38463
  if (!existsSync11(dir)) {
38150
38464
  const empty = { entries: [], count: 0, dir, note: "no .changeset/ dir" };
38151
38465
  if (isHumanOutput()) {
@@ -38610,7 +38924,7 @@ var init_check2 = __esm({
38610
38924
  async run({ args }) {
38611
38925
  const { spawnSync } = await import("node:child_process");
38612
38926
  const { existsSync: existsSync17 } = await import("node:fs");
38613
- const { join: join35, resolve: resolve7 } = await import("node:path");
38927
+ const { join: join34, resolve: resolve7 } = await import("node:path");
38614
38928
  const strict = Boolean(args.strict);
38615
38929
  const jsonOnly = Boolean(args.json);
38616
38930
  const repoRoot = resolve7(process.cwd());
@@ -38650,7 +38964,7 @@ var init_check2 = __esm({
38650
38964
  const results = [];
38651
38965
  let anyFailed = false;
38652
38966
  for (const gate of gates) {
38653
- const scriptPath = join35(repoRoot, gate.script);
38967
+ const scriptPath = join34(repoRoot, gate.script);
38654
38968
  if (!existsSync17(scriptPath)) {
38655
38969
  results.push({
38656
38970
  id: gate.id,
@@ -38966,9 +39280,9 @@ var init_code = __esm({
38966
39280
  async run({ args }) {
38967
39281
  await requireTreeSitter();
38968
39282
  const { smartOutline } = await import("@cleocode/core/internal");
38969
- const { join: join35 } = await import("node:path");
39283
+ const { join: join34 } = await import("node:path");
38970
39284
  const root = process.cwd();
38971
- const absPath = args.file.startsWith("/") ? args.file : join35(root, args.file);
39285
+ const absPath = args.file.startsWith("/") ? args.file : join34(root, args.file);
38972
39286
  const result = smartOutline(absPath, root);
38973
39287
  if (result.errors.length > 0 && result.symbols.length === 0) {
38974
39288
  cliError(result.errors.join(", "), 1, { name: "E_OUTLINE_FAILED" });
@@ -39059,9 +39373,9 @@ var init_code = __esm({
39059
39373
  async run({ args }) {
39060
39374
  await requireTreeSitter();
39061
39375
  const { smartUnfold } = await import("@cleocode/core/internal");
39062
- const { join: join35 } = await import("node:path");
39376
+ const { join: join34 } = await import("node:path");
39063
39377
  const root = process.cwd();
39064
- const absPath = args.file.startsWith("/") ? args.file : join35(root, args.file);
39378
+ const absPath = args.file.startsWith("/") ? args.file : join34(root, args.file);
39065
39379
  const result = smartUnfold(absPath, args.symbol, root);
39066
39380
  if (!result.found) {
39067
39381
  const errs = result.errors.length > 0 ? `: ${result.errors.join(", ")}` : "";
@@ -40184,7 +40498,7 @@ var curator_exports = {};
40184
40498
  __export(curator_exports, {
40185
40499
  curatorCommand: () => curatorCommand
40186
40500
  });
40187
- import { join as join16 } from "node:path";
40501
+ import { join as join15 } from "node:path";
40188
40502
  import { getCleoHome } from "@cleocode/paths";
40189
40503
  async function loadCurator() {
40190
40504
  return import("@cleocode/core/sentient/curator.js");
@@ -40214,7 +40528,7 @@ var init_curator = __esm({
40214
40528
  try {
40215
40529
  const { runCuratorTick } = await loadCurator();
40216
40530
  const { readCuratorConfig } = await loadDaemon();
40217
- const configPath = join16(getCleoHome(), "config.json");
40531
+ const configPath = join15(getCleoHome(), "config.json");
40218
40532
  const cfg = await readCuratorConfig(configPath);
40219
40533
  const result = await runCuratorTick({
40220
40534
  dryRun: args["dry-run"] === true,
@@ -40255,7 +40569,7 @@ var init_curator = __esm({
40255
40569
  async run() {
40256
40570
  try {
40257
40571
  const { readCuratorConfig, curatorCronExpression } = await loadDaemon();
40258
- const configPath = join16(getCleoHome(), "config.json");
40572
+ const configPath = join15(getCleoHome(), "config.json");
40259
40573
  const cfg = await readCuratorConfig(configPath);
40260
40574
  cliOutput(
40261
40575
  {
@@ -40330,7 +40644,7 @@ __export(daemon_exports, {
40330
40644
  daemonCommand: () => daemonCommand
40331
40645
  });
40332
40646
  import { existsSync as existsSync12 } from "node:fs";
40333
- import { join as join17 } from "node:path";
40647
+ import { join as join16 } from "node:path";
40334
40648
  import { fileURLToPath as fileURLToPath3 } from "node:url";
40335
40649
  import { getGCDaemonStatus, spawnGCDaemon, stopGCDaemon } from "@cleocode/core/gc/daemon.js";
40336
40650
  import {
@@ -40396,9 +40710,9 @@ async function showDaemonStatus(cleoDir, projectRoot) {
40396
40710
  }
40397
40711
  function resolveDaemonInstallerScript() {
40398
40712
  const filePath = fileURLToPath3(import.meta.url);
40399
- const candidate1 = join17(filePath, "..", "..", "..", "scripts", "install-daemon-service.mjs");
40713
+ const candidate1 = join16(filePath, "..", "..", "..", "scripts", "install-daemon-service.mjs");
40400
40714
  if (existsSync12(candidate1)) return candidate1;
40401
- const candidate2 = join17(
40715
+ const candidate2 = join16(
40402
40716
  filePath,
40403
40717
  "..",
40404
40718
  "..",
@@ -40470,13 +40784,13 @@ var init_daemon = __esm({
40470
40784
  {
40471
40785
  pid,
40472
40786
  cleoDir,
40473
- logs: join17(cleoDir, "logs", "gc.log"),
40787
+ logs: join16(cleoDir, "logs", "gc.log"),
40474
40788
  message: `GC daemon started (PID ${pid})`
40475
40789
  },
40476
40790
  {
40477
40791
  command: "daemon",
40478
40792
  operation: "daemon.start",
40479
- message: `GC daemon started (PID ${pid}) \u2014 Logs: ${join17(cleoDir, "logs", "gc.log")}`
40793
+ message: `GC daemon started (PID ${pid}) \u2014 Logs: ${join16(cleoDir, "logs", "gc.log")}`
40480
40794
  }
40481
40795
  );
40482
40796
  } catch (err) {
@@ -41247,11 +41561,11 @@ __export(detect_drift_exports, {
41247
41561
  detectDriftCommand: () => detectDriftCommand
41248
41562
  });
41249
41563
  import { existsSync as existsSync13, readdirSync, readFileSync as readFileSync13 } from "node:fs";
41250
- import { dirname as dirname5, join as join18 } from "node:path";
41564
+ import { dirname as dirname5, join as join17 } from "node:path";
41251
41565
  function findProjectRoot() {
41252
41566
  let currentDir = process.cwd();
41253
41567
  while (currentDir !== "/") {
41254
- if (existsSync13(join18(currentDir, "package.json"))) {
41568
+ if (existsSync13(join17(currentDir, "package.json"))) {
41255
41569
  return currentDir;
41256
41570
  }
41257
41571
  const parent = dirname5(currentDir);
@@ -41275,8 +41589,8 @@ var init_detect_drift = __esm({
41275
41589
  },
41276
41590
  async run() {
41277
41591
  const projectRoot = findProjectRoot();
41278
- const isCleoRepo = existsSync13(join18(projectRoot, "packages", "cleo", "src"));
41279
- const cleoSrcRoot = isCleoRepo ? join18(projectRoot, "packages", "cleo", "src") : join18(projectRoot, "src");
41592
+ const isCleoRepo = existsSync13(join17(projectRoot, "packages", "cleo", "src"));
41593
+ const cleoSrcRoot = isCleoRepo ? join17(projectRoot, "packages", "cleo", "src") : join17(projectRoot, "src");
41280
41594
  const safeRead = (filePath) => {
41281
41595
  try {
41282
41596
  return readFileSync13(filePath, "utf-8");
@@ -41290,7 +41604,7 @@ var init_detect_drift = __esm({
41290
41604
  checks: [],
41291
41605
  recommendations: []
41292
41606
  };
41293
- const injPath = join18(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
41607
+ const injPath = join17(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
41294
41608
  if (existsSync13(injPath)) {
41295
41609
  const content = safeRead(injPath);
41296
41610
  userResult.checks.push({
@@ -41342,9 +41656,9 @@ var init_detect_drift = __esm({
41342
41656
  }
41343
41657
  };
41344
41658
  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");
41659
+ const specPath = join17(projectRoot, "docs", "specs", "CLEO-OPERATION-CONSTITUTION.md");
41660
+ const registryPath = join17(cleoSrcRoot, "dispatch", "registry.ts");
41661
+ const dispatchDomainsDir = join17(cleoSrcRoot, "dispatch", "domains");
41348
41662
  if (!existsSync13(specPath)) {
41349
41663
  addCheck("Gateway-to-spec sync", "fail", "CLEO-OPERATION-CONSTITUTION.md missing", [
41350
41664
  {
@@ -41413,8 +41727,8 @@ var init_detect_drift = __esm({
41413
41727
  ]);
41414
41728
  }
41415
41729
  try {
41416
- const cliDir = join18(cleoSrcRoot, "cli", "commands");
41417
- const coreDir = isCleoRepo ? join18(projectRoot, "packages", "core", "src") : join18(projectRoot, "src", "core");
41730
+ const cliDir = join17(cleoSrcRoot, "cli", "commands");
41731
+ const coreDir = isCleoRepo ? join17(projectRoot, "packages", "core", "src") : join17(projectRoot, "src", "core");
41418
41732
  if (!existsSync13(cliDir)) {
41419
41733
  addCheck("CLI-to-core sync", "fail", "CLI commands directory missing", [
41420
41734
  {
@@ -41441,7 +41755,7 @@ var init_detect_drift = __esm({
41441
41755
  addCheck("CLI-to-core sync", "fail", `Error: ${getErrorMessage(e)}`);
41442
41756
  }
41443
41757
  try {
41444
- const domainsDir = join18(cleoSrcRoot, "dispatch", "domains");
41758
+ const domainsDir = join17(cleoSrcRoot, "dispatch", "domains");
41445
41759
  if (!existsSync13(domainsDir)) {
41446
41760
  addCheck("Domain handler coverage", "fail", "Dispatch domains directory missing", [
41447
41761
  {
@@ -41459,7 +41773,7 @@ var init_detect_drift = __esm({
41459
41773
  addCheck("Domain handler coverage", "fail", `Error: ${getErrorMessage(e)}`);
41460
41774
  }
41461
41775
  try {
41462
- const matrixPath = join18(cleoSrcRoot, "dispatch", "lib", "capability-matrix.ts");
41776
+ const matrixPath = join17(cleoSrcRoot, "dispatch", "lib", "capability-matrix.ts");
41463
41777
  if (!existsSync13(matrixPath)) {
41464
41778
  addCheck("Capability matrix", "fail", "Capability matrix missing", [
41465
41779
  {
@@ -41476,7 +41790,7 @@ var init_detect_drift = __esm({
41476
41790
  addCheck("Capability matrix", "fail", `Error: ${getErrorMessage(e)}`);
41477
41791
  }
41478
41792
  try {
41479
- const schemaPath = join18(projectRoot, "src", "store", "schema.ts");
41793
+ const schemaPath = join17(projectRoot, "src", "store", "schema.ts");
41480
41794
  if (!existsSync13(schemaPath)) {
41481
41795
  addCheck("Schema validation", "fail", "Schema definition missing", [
41482
41796
  {
@@ -41511,8 +41825,8 @@ var init_detect_drift = __esm({
41511
41825
  addCheck("Schema validation", "fail", `Error: ${getErrorMessage(e)}`);
41512
41826
  }
41513
41827
  try {
41514
- const visionPath = join18(projectRoot, "docs", "concepts", "CLEO-VISION.md");
41515
- const specPath = join18(projectRoot, "docs", "specs", "CLEO-PORTABLE-PROJECT-BRAIN-SPEC.md");
41828
+ const visionPath = join17(projectRoot, "docs", "concepts", "CLEO-VISION.md");
41829
+ const specPath = join17(projectRoot, "docs", "specs", "CLEO-PORTABLE-PROJECT-BRAIN-SPEC.md");
41516
41830
  const issues = [];
41517
41831
  if (!existsSync13(visionPath)) {
41518
41832
  issues.push({
@@ -41567,7 +41881,7 @@ var init_detect_drift = __esm({
41567
41881
  addCheck("Canonical identity", "fail", `Error: ${getErrorMessage(e)}`);
41568
41882
  }
41569
41883
  try {
41570
- const injectionPath = join18(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
41884
+ const injectionPath = join17(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
41571
41885
  if (!existsSync13(injectionPath)) {
41572
41886
  addCheck("Agent injection", "fail", "Agent injection template missing", [
41573
41887
  {
@@ -41597,7 +41911,7 @@ var init_detect_drift = __esm({
41597
41911
  addCheck("Agent injection", "fail", `Error: ${getErrorMessage(e)}`);
41598
41912
  }
41599
41913
  try {
41600
- const exitCodesPath = join18(cleoSrcRoot, "dispatch", "lib", "exit-codes.ts");
41914
+ const exitCodesPath = join17(cleoSrcRoot, "dispatch", "lib", "exit-codes.ts");
41601
41915
  if (!existsSync13(exitCodesPath)) {
41602
41916
  addCheck("Exit codes", "fail", "Exit codes definition missing", [
41603
41917
  {
@@ -41946,10 +42260,10 @@ var init_strict_args = __esm({
41946
42260
 
41947
42261
  // packages/cleo/src/viewer/pidfile.ts
41948
42262
  import { mkdir, readFile as readFile2, unlink, writeFile } from "node:fs/promises";
41949
- import { dirname as dirname6, join as join19 } from "node:path";
42263
+ import { dirname as dirname6, join as join18 } from "node:path";
41950
42264
  import { getCleoHome as getCleoHome2 } from "@cleocode/core/internal";
41951
42265
  function viewerPidFilePath() {
41952
- return join19(getCleoHome2(), "viewer.pid");
42266
+ return join18(getCleoHome2(), "viewer.pid");
41953
42267
  }
41954
42268
  async function writeViewerPidFile(record) {
41955
42269
  const path6 = viewerPidFilePath();
@@ -42049,11 +42363,11 @@ var init_port_allocator = __esm({
42049
42363
  // packages/cleo/src/viewer/server.ts
42050
42364
  import { createReadStream } from "node:fs";
42051
42365
  import { stat } from "node:fs/promises";
42052
- import { dirname as dirname7, join as join20, normalize, resolve as resolve4 } from "node:path";
42366
+ import { dirname as dirname7, join as join19, normalize, resolve as resolve4 } from "node:path";
42053
42367
  import { fileURLToPath as fileURLToPath4 } from "node:url";
42054
42368
  import {
42055
42369
  createAttachmentStore as createAttachmentStore5,
42056
- getProjectRoot as getProjectRoot30,
42370
+ getProjectRoot as getProjectRoot31,
42057
42371
  searchAllProjectDocs
42058
42372
  } from "@cleocode/core/internal";
42059
42373
  function getViewerAssetsDir() {
@@ -42088,7 +42402,7 @@ function inferTitle(markdown, fallback) {
42088
42402
  }
42089
42403
  async function serveStatic(res, assetsDir, relPath) {
42090
42404
  const safeRel = normalize(relPath).replace(/^[\\/]+/, "");
42091
- const absPath = join20(assetsDir, safeRel);
42405
+ const absPath = join19(assetsDir, safeRel);
42092
42406
  const resolvedAssets = resolve4(assetsDir) + "/";
42093
42407
  const resolvedAbs = resolve4(absPath);
42094
42408
  if (`${resolvedAbs}/`.indexOf(resolvedAssets) !== 0 && resolvedAbs !== resolve4(assetsDir)) {
@@ -42113,7 +42427,7 @@ async function serveStatic(res, assetsDir, relPath) {
42113
42427
  }
42114
42428
  }
42115
42429
  function buildViewerHandler(opts = {}) {
42116
- const projectRoot = opts.projectRoot ?? getProjectRoot30();
42430
+ const projectRoot = opts.projectRoot ?? getProjectRoot31();
42117
42431
  const assetsDir = getViewerAssetsDir();
42118
42432
  const store = createAttachmentStore5();
42119
42433
  return async (req, res) => {
@@ -42289,12 +42603,12 @@ var init_server = __esm({
42289
42603
  // packages/cleo/src/cli/commands/docs-viewer.ts
42290
42604
  import { spawn } from "node:child_process";
42291
42605
  import { open as fsOpen } from "node:fs/promises";
42292
- import { join as join21 } from "node:path";
42606
+ import { join as join20 } from "node:path";
42293
42607
  import { fileURLToPath as fileURLToPath5 } from "node:url";
42294
- import { getCleoHome as getCleoHome3, getProjectRoot as getProjectRoot31 } from "@cleocode/core";
42608
+ import { getCleoHome as getCleoHome3, getProjectRoot as getProjectRoot32 } from "@cleocode/core";
42295
42609
  function getCleoBinPath() {
42296
42610
  const thisFile = fileURLToPath5(import.meta.url);
42297
- return join21(thisFile, "..", "..", "index.js");
42611
+ return join20(thisFile, "..", "..", "index.js");
42298
42612
  }
42299
42613
  async function waitForExit(pid, timeoutMs, intervalMs = 100) {
42300
42614
  const deadline = Date.now() + timeoutMs;
@@ -42323,7 +42637,7 @@ function openInBrowser(url) {
42323
42637
  }
42324
42638
  }
42325
42639
  async function spawnDetachedServer(opts) {
42326
- const logFile = join21(getCleoHome3(), "viewer.log");
42640
+ const logFile = join20(getCleoHome3(), "viewer.log");
42327
42641
  const handle = await fsOpen(logFile, "a").catch(() => null);
42328
42642
  const stdio = handle ? ["ignore", handle.fd, handle.fd] : ["ignore", "ignore", "ignore"];
42329
42643
  const args = [
@@ -42342,7 +42656,7 @@ async function spawnDetachedServer(opts) {
42342
42656
  detached: true,
42343
42657
  stdio,
42344
42658
  env: { ...process.env, [DETACHED_CHILD_ENV]: "1" },
42345
- cwd: getProjectRoot31()
42659
+ cwd: getProjectRoot32()
42346
42660
  });
42347
42661
  child.unref();
42348
42662
  if (handle) await handle.close();
@@ -42494,7 +42808,7 @@ var init_docs_viewer = __esm({
42494
42808
  pid: process.pid,
42495
42809
  port: handle.port,
42496
42810
  host: handle.host,
42497
- projectRoot: getProjectRoot31(),
42811
+ projectRoot: getProjectRoot32(),
42498
42812
  startedAt: Date.now()
42499
42813
  };
42500
42814
  await writeViewerPidFile(record);
@@ -42770,15 +43084,19 @@ __export(docs_exports, {
42770
43084
  docsCommand: () => docsCommand
42771
43085
  });
42772
43086
  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";
43087
+ import { dirname as dirname8, isAbsolute as isAbsolute2, join as join21, resolve as resolve5 } from "node:path";
42774
43088
  import {
42775
43089
  buildDocsGraph,
42776
43090
  CleoError as CleoError3,
42777
43091
  CounterMismatchError,
43092
+ checkSlugSimilarity,
42778
43093
  createAttachmentStoreDocsAccessor,
43094
+ DEFAULT_SIMILARITY_MODE,
43095
+ DEFAULT_SIMILARITY_THRESHOLD,
43096
+ detectStrayCleoDb as detectStrayCleoDb2,
42779
43097
  exportDocument,
42780
43098
  getAgentOutputsAbsolute,
42781
- getProjectRoot as getProjectRoot32,
43099
+ getProjectRoot as getProjectRoot33,
42782
43100
  listDocVersions,
42783
43101
  makeClassifierForScanRoot,
42784
43102
  mergeDocs,
@@ -42787,6 +43105,8 @@ import {
42787
43105
  rankDocs,
42788
43106
  readJson,
42789
43107
  recordPublication,
43108
+ resolveWorktreeFilePath,
43109
+ resolveWorktreeRouting as resolveWorktreeRouting2,
42790
43110
  runDocsImport,
42791
43111
  searchAllProjectDocs as searchAllProjectDocs2,
42792
43112
  searchDocs as searchDocs2,
@@ -42794,7 +43114,7 @@ import {
42794
43114
  syncFromGit
42795
43115
  } from "@cleocode/core/internal";
42796
43116
  async function getScriptNames(projectRoot) {
42797
- const scriptsDir = join22(projectRoot, "scripts");
43117
+ const scriptsDir = join21(projectRoot, "scripts");
42798
43118
  try {
42799
43119
  const files = await readdir(scriptsDir);
42800
43120
  return files.filter((f) => f.endsWith(".sh")).map((f) => f.replace(".sh", "")).sort();
@@ -42803,7 +43123,7 @@ async function getScriptNames(projectRoot) {
42803
43123
  }
42804
43124
  }
42805
43125
  async function getIndexedCommands(projectRoot) {
42806
- const indexPath = join22(projectRoot, "docs", "commands", "COMMANDS-INDEX.json");
43126
+ const indexPath = join21(projectRoot, "docs", "commands", "COMMANDS-INDEX.json");
42807
43127
  const index = await readJson(indexPath);
42808
43128
  if (!index) return [];
42809
43129
  return index.commands.map((c) => c.name).sort();
@@ -42836,7 +43156,7 @@ async function runGapCheck(_projectRoot, filterId) {
42836
43156
  const reviewFiles = files.filter((f) => f.endsWith(".md"));
42837
43157
  for (const file of reviewFiles) {
42838
43158
  if (filterId && !file.includes(filterId)) continue;
42839
- const filePath = join22(reviewDir, file);
43159
+ const filePath = join21(reviewDir, file);
42840
43160
  const content = await readFile3(filePath, "utf-8");
42841
43161
  const taskMatch = file.match(/^(T\d+)/);
42842
43162
  const taskId = taskMatch ? taskMatch[1] : "UNKNOWN";
@@ -42887,6 +43207,7 @@ var init_docs3 = __esm({
42887
43207
  init_src2();
42888
43208
  init_dist();
42889
43209
  init_cli();
43210
+ init_canon_docs();
42890
43211
  init_strict_args();
42891
43212
  init_renderers();
42892
43213
  init_docs_viewer();
@@ -42924,11 +43245,15 @@ var init_docs3 = __esm({
42924
43245
  },
42925
43246
  slug: {
42926
43247
  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."
43248
+ 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
43249
  },
42929
43250
  type: {
42930
43251
  type: "string",
42931
43252
  description: "Taxonomy classification \u2014 run `cleo docs list-types` to enumerate registered kinds (T9637 / T9788)"
43253
+ },
43254
+ "allow-similar": {
43255
+ type: "boolean",
43256
+ 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
43257
  }
42933
43258
  },
42934
43259
  async run({ args, rawArgs }) {
@@ -42949,6 +43274,7 @@ var init_docs3 = __esm({
42949
43274
  const ownerId = args["owner-id"];
42950
43275
  const fileArg = args.file ?? void 0;
42951
43276
  const url = args.url ?? void 0;
43277
+ const allowSimilar = args["allow-similar"] === true;
42952
43278
  if (!fileArg && !url) {
42953
43279
  cliError("provide a file path (positional argument) or --url <url>", 6, {
42954
43280
  name: "E_VALIDATION",
@@ -42956,13 +43282,113 @@ var init_docs3 = __esm({
42956
43282
  });
42957
43283
  process.exit(6);
42958
43284
  }
43285
+ let resolvedFile;
43286
+ if (fileArg) {
43287
+ const routing = resolveWorktreeRouting2();
43288
+ const strayDb = detectStrayCleoDb2(routing);
43289
+ if (strayDb) {
43290
+ cliError(
43291
+ `stray .cleo/tasks.db detected inside worktree at ${routing.worktreePath}. This is a leaked CLEO state directory.`,
43292
+ 6,
43293
+ {
43294
+ name: "E_STRAY_WORKTREE_DB",
43295
+ fix: `Remove it with: rm -rf ${routing.worktreePath}/.cleo \u2014 then retry. See ADR-068 \xA73 for the worktree DB isolation rationale.`
43296
+ }
43297
+ );
43298
+ process.exit(6);
43299
+ }
43300
+ if (routing.isWorktree && process.env["CLEO_QUIET"] !== "1") {
43301
+ const routingLog = `[T10389] routing SSoT write from worktree cwd ${routing.cwd} \u2192 canonical project root ${routing.canonicalRoot}
43302
+ `;
43303
+ process.stderr.write(routingLog);
43304
+ }
43305
+ resolvedFile = resolveWorktreeFilePath(String(fileArg), routing);
43306
+ }
43307
+ if (args.slug && args.type) {
43308
+ const projectRoot = await getProjectRoot33();
43309
+ let warnThreshold = DEFAULT_SIMILARITY_THRESHOLD;
43310
+ let mode = DEFAULT_SIMILARITY_MODE;
43311
+ try {
43312
+ const canon = loadCanonRegistry(projectRoot);
43313
+ if (canon?.similarity) {
43314
+ warnThreshold = canon.similarity.warnThreshold;
43315
+ mode = canon.similarity.mode;
43316
+ }
43317
+ } catch {
43318
+ }
43319
+ try {
43320
+ const sim = await checkSlugSimilarity({
43321
+ slug: args.slug,
43322
+ type: args.type,
43323
+ projectRoot,
43324
+ threshold: warnThreshold
43325
+ });
43326
+ if (sim.mostSimilarSlug !== null) {
43327
+ const scoreFixed = sim.score.toFixed(2);
43328
+ const hint = `Similar to '${sim.mostSimilarSlug}' (score ${scoreFixed}) \u2014 did you mean: cleo docs update ${sim.mostSimilarSlug}? Pass --allow-similar to bypass.`;
43329
+ if (mode === "block" && !allowSimilar) {
43330
+ cliError(hint, 6 /* VALIDATION_ERROR */, {
43331
+ name: "E_SLUG_SIMILARITY",
43332
+ fix: `Use \`cleo docs update ${sim.mostSimilarSlug}\` if updating, or pass --allow-similar to add as a new doc.`,
43333
+ alternatives: [
43334
+ {
43335
+ action: `update '${sim.mostSimilarSlug}' instead`,
43336
+ command: `cleo docs update ${sim.mostSimilarSlug}`
43337
+ },
43338
+ {
43339
+ action: "bypass the similarity check",
43340
+ command: `cleo docs add ${ownerId} ${fileArg ?? `--url ${url}`} --slug ${args.slug} --type ${args.type} --allow-similar`
43341
+ }
43342
+ ],
43343
+ details: {
43344
+ proposedSlug: args.slug,
43345
+ mostSimilarSlug: sim.mostSimilarSlug,
43346
+ score: sim.score,
43347
+ threshold: warnThreshold,
43348
+ kind: args.type
43349
+ }
43350
+ });
43351
+ process.exit(6 /* VALIDATION_ERROR */);
43352
+ }
43353
+ humanInfo(hint);
43354
+ if (allowSimilar) {
43355
+ const auditLine = `${JSON.stringify({
43356
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
43357
+ reason: "allow-similar-bypass",
43358
+ proposedSlug: args.slug,
43359
+ mostSimilarSlug: sim.mostSimilarSlug,
43360
+ score: sim.score,
43361
+ threshold: warnThreshold,
43362
+ kind: args.type,
43363
+ ownerId
43364
+ })}
43365
+ `;
43366
+ try {
43367
+ await mkdir2(join21(projectRoot, ".cleo", "audit"), { recursive: true });
43368
+ await appendFile(
43369
+ join21(projectRoot, ".cleo", "audit", "similar-bypass.jsonl"),
43370
+ auditLine,
43371
+ "utf-8"
43372
+ );
43373
+ } catch {
43374
+ }
43375
+ }
43376
+ }
43377
+ } catch (err) {
43378
+ if (process.env["CLEO_DEBUG"]) {
43379
+ humanInfo(
43380
+ `similarity check skipped: ${err instanceof Error ? err.message : String(err)}`
43381
+ );
43382
+ }
43383
+ }
43384
+ }
42959
43385
  await dispatchFromCli(
42960
43386
  "mutate",
42961
43387
  "docs",
42962
43388
  "add",
42963
43389
  {
42964
43390
  ownerId,
42965
- ...fileArg ? { file: fileArg } : {},
43391
+ ...resolvedFile ? { file: resolvedFile } : {},
42966
43392
  ...url ? { url } : {},
42967
43393
  ...args.desc ? { desc: args.desc } : {},
42968
43394
  ...args.labels ? { labels: args.labels } : {},
@@ -43179,7 +43605,7 @@ var init_docs3 = __esm({
43179
43605
  const taskId = String(args.task);
43180
43606
  const includeAttachments = args["include-attachments"] !== false;
43181
43607
  const includeMemoryRefs = args["include-memory-refs"] === true;
43182
- const projectRoot = getProjectRoot32();
43608
+ const projectRoot = getProjectRoot33();
43183
43609
  try {
43184
43610
  const result = await exportDocument({
43185
43611
  taskId,
@@ -43245,7 +43671,7 @@ var init_docs3 = __esm({
43245
43671
  }
43246
43672
  },
43247
43673
  async run({ args }) {
43248
- const projectRoot = getProjectRoot32();
43674
+ const projectRoot = getProjectRoot33();
43249
43675
  const limit = args.limit ? Number.parseInt(String(args.limit), 10) : 10;
43250
43676
  try {
43251
43677
  const result = args.owner ? await searchDocs2(String(args.query), {
@@ -43301,7 +43727,7 @@ var init_docs3 = __esm({
43301
43727
  }
43302
43728
  },
43303
43729
  async run({ args }) {
43304
- const projectRoot = getProjectRoot32();
43730
+ const projectRoot = getProjectRoot33();
43305
43731
  const rawStrategy = args.strategy ?? "three-way";
43306
43732
  const strategy = rawStrategy === "cherry-pick" || rawStrategy === "multi-diff" ? rawStrategy : "three-way";
43307
43733
  try {
@@ -43350,7 +43776,7 @@ var init_docs3 = __esm({
43350
43776
  }
43351
43777
  },
43352
43778
  async run({ args }) {
43353
- const projectRoot = getProjectRoot32();
43779
+ const projectRoot = getProjectRoot33();
43354
43780
  const fmt = args.format ?? "mermaid";
43355
43781
  try {
43356
43782
  const result = await buildDocsGraph({ ownerId: String(args.for), projectRoot });
@@ -43419,7 +43845,7 @@ var init_docs3 = __esm({
43419
43845
  }
43420
43846
  },
43421
43847
  async run({ args }) {
43422
- const projectRoot = getProjectRoot32();
43848
+ const projectRoot = getProjectRoot33();
43423
43849
  try {
43424
43850
  const result = await rankDocs({
43425
43851
  ownerId: String(args.for),
@@ -43457,7 +43883,7 @@ var init_docs3 = __esm({
43457
43883
  }
43458
43884
  },
43459
43885
  async run({ args }) {
43460
- const projectRoot = getProjectRoot32();
43886
+ const projectRoot = getProjectRoot33();
43461
43887
  try {
43462
43888
  const result = await listDocVersions({
43463
43889
  ownerId: String(args.for),
@@ -43500,7 +43926,7 @@ var init_docs3 = __esm({
43500
43926
  }
43501
43927
  },
43502
43928
  async run({ args }) {
43503
- const projectRoot = getProjectRoot32();
43929
+ const projectRoot = getProjectRoot33();
43504
43930
  try {
43505
43931
  const result = await publishDocs({
43506
43932
  ownerId: String(args.for),
@@ -43624,7 +44050,7 @@ var init_docs3 = __esm({
43624
44050
  },
43625
44051
  async run({ args }) {
43626
44052
  if (args.from) {
43627
- const projectRoot = getProjectRoot32();
44053
+ const projectRoot = getProjectRoot33();
43628
44054
  const ownerId = args.for ?? void 0;
43629
44055
  if (!ownerId) {
43630
44056
  cliError(
@@ -43691,7 +44117,7 @@ var init_docs3 = __esm({
43691
44117
  }
43692
44118
  },
43693
44119
  async run() {
43694
- const projectRoot = getProjectRoot32();
44120
+ const projectRoot = getProjectRoot33();
43695
44121
  try {
43696
44122
  const result = await statusDocs({ projectRoot });
43697
44123
  cliOutput(result, { command: "docs status", operation: "docs.status" });
@@ -43776,7 +44202,7 @@ var init_docs3 = __esm({
43776
44202
  }
43777
44203
  },
43778
44204
  async run({ args }) {
43779
- const projectRoot = getProjectRoot32();
44205
+ const projectRoot = getProjectRoot33();
43780
44206
  const dirArg = String(args.dir);
43781
44207
  const scanRoot = isAbsolute2(dirArg) ? dirArg : resolve5(projectRoot, dirArg);
43782
44208
  const dryRun = args["dry-run"] === true;
@@ -43790,9 +44216,9 @@ var init_docs3 = __esm({
43790
44216
  })}
43791
44217
  `;
43792
44218
  try {
43793
- await mkdir2(join22(projectRoot, ".cleo", "audit"), { recursive: true });
44219
+ await mkdir2(join21(projectRoot, ".cleo", "audit"), { recursive: true });
43794
44220
  await appendFile(
43795
- join22(projectRoot, ".cleo", "audit", "import-force-bypass.jsonl"),
44221
+ join21(projectRoot, ".cleo", "audit", "import-force-bypass.jsonl"),
43796
44222
  auditLine,
43797
44223
  "utf-8"
43798
44224
  );
@@ -43850,7 +44276,7 @@ var init_docs3 = __esm({
43850
44276
  }
43851
44277
  },
43852
44278
  async run({ args }) {
43853
- const projectRoot = getProjectRoot32();
44279
+ const projectRoot = getProjectRoot33();
43854
44280
  const { registry, configError } = loadCliRegistry(projectRoot);
43855
44281
  const kinds = registry.list().map(toWireKind);
43856
44282
  const extensionsCount = kinds.filter((k) => k.isExtension).length;
@@ -43894,7 +44320,7 @@ var init_docs3 = __esm({
43894
44320
  }
43895
44321
  },
43896
44322
  async run({ args }) {
43897
- const projectRoot = getProjectRoot32();
44323
+ const projectRoot = getProjectRoot33();
43898
44324
  const { registry, configError } = loadCliRegistry(projectRoot);
43899
44325
  const kinds = registry.list().map(toWireKind);
43900
44326
  let counts2;
@@ -43972,6 +44398,235 @@ var init_docs3 = __esm({
43972
44398
  }
43973
44399
  });
43974
44400
 
44401
+ // packages/cleo/src/cli/commands/doctor-db-substrate.ts
44402
+ var doctor_db_substrate_exports = {};
44403
+ __export(doctor_db_substrate_exports, {
44404
+ doctorDbSubstrateCommand: () => doctorDbSubstrateCommand
44405
+ });
44406
+ import { getProjectRoot as getProjectRoot34, pushWarning as pushWarning2 } from "@cleocode/core";
44407
+ import { surveyDbSubstrate, surveyFleetDbSubstrate } from "@cleocode/core/doctor/db-substrate.js";
44408
+ function pushSubstrateWarnings(result) {
44409
+ for (const warning of result.warnings) {
44410
+ const context = {
44411
+ kind: warning.kind,
44412
+ path: warning.path,
44413
+ lastWriteMs: warning.lastWriteMs
44414
+ };
44415
+ if (warning.kind === "orphan-project-root") {
44416
+ context["parentWorkspace"] = warning.parentWorkspace ?? null;
44417
+ }
44418
+ pushWarning2({
44419
+ code: warning.kind === "orphan-project-root" ? "W_DB_SUBSTRATE_ORPHAN_PROJECT_ROOT" : "W_DB_SUBSTRATE_NESTED_NEXUS_DUPLICATE",
44420
+ 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)`,
44421
+ severity: "warn",
44422
+ context
44423
+ });
44424
+ }
44425
+ for (const projectSurvey of result.projects) {
44426
+ for (const [role, entry] of Object.entries(projectSurvey.dbs)) {
44427
+ if (entry.pragmaDrift === null || entry.pragmaDrift.length === 0) continue;
44428
+ for (const drift of entry.pragmaDrift) {
44429
+ pushWarning2({
44430
+ code: "W_DB_SUBSTRATE_PRAGMA_DRIFT",
44431
+ message: `Pragma drift on ${role} (${entry.filePath}): expected ${drift.pragma}=${drift.expected}, actual=${drift.actual ?? "<unmeasurable>"}`,
44432
+ severity: "warn",
44433
+ context: {
44434
+ role,
44435
+ filePath: entry.filePath,
44436
+ pragma: drift.pragma,
44437
+ expected: drift.expected,
44438
+ actual: drift.actual
44439
+ }
44440
+ });
44441
+ }
44442
+ }
44443
+ }
44444
+ for (const report of result.crossDbOrphans) {
44445
+ if (report.skipped || report.orphanCount === 0) continue;
44446
+ pushWarning2({
44447
+ code: `W_DB_SUBSTRATE_CROSS_DB_${report.invariant}`,
44448
+ message: `${report.invariant}: ${report.orphanCount} orphan row${report.orphanCount === 1 ? "" : "s"} \u2014 ${report.description}. ${report.suggestedFix}`,
44449
+ severity: "warn",
44450
+ context: {
44451
+ invariant: report.invariant,
44452
+ orphanCount: report.orphanCount,
44453
+ sample: report.sample.join(","),
44454
+ suggestedFix: report.suggestedFix
44455
+ }
44456
+ });
44457
+ }
44458
+ }
44459
+ function pushPerDbWarnings(result) {
44460
+ for (const projectSurvey of result.projects) {
44461
+ for (const [role, dbEntry] of Object.entries(projectSurvey.dbs)) {
44462
+ if (dbEntry.quarantinedTo !== null) {
44463
+ pushWarning2({
44464
+ code: "W_DB_SUBSTRATE_AUTO_QUARANTINED",
44465
+ message: `Auto-quarantined corrupt ${role} DB at ${dbEntry.filePath} \u2192 ${dbEntry.quarantinedTo}. Recover via: cleo backup recover ${role}`,
44466
+ severity: "warn",
44467
+ context: {
44468
+ role,
44469
+ filePath: dbEntry.filePath,
44470
+ quarantinedTo: dbEntry.quarantinedTo,
44471
+ integrityCheckMs: dbEntry.integrityCheckMs
44472
+ }
44473
+ });
44474
+ }
44475
+ if (dbEntry.timedOut) {
44476
+ pushWarning2({
44477
+ code: "W_DB_SUBSTRATE_INTEGRITY_TIMEOUT",
44478
+ message: `integrity_check on ${role} DB at ${dbEntry.filePath} took ${dbEntry.integrityCheckMs}ms \u2014 slow substrate flagged for operator attention`,
44479
+ severity: "warn",
44480
+ context: {
44481
+ role,
44482
+ filePath: dbEntry.filePath,
44483
+ integrityCheckMs: dbEntry.integrityCheckMs
44484
+ }
44485
+ });
44486
+ }
44487
+ }
44488
+ }
44489
+ }
44490
+ var DEFAULT_FLEET_ROOT, doctorDbSubstrateCommand;
44491
+ var init_doctor_db_substrate = __esm({
44492
+ "packages/cleo/src/cli/commands/doctor-db-substrate.ts"() {
44493
+ "use strict";
44494
+ init_define_cli_command();
44495
+ init_renderers();
44496
+ DEFAULT_FLEET_ROOT = "/mnt/projects";
44497
+ doctorDbSubstrateCommand = defineCommand({
44498
+ meta: {
44499
+ name: "db-substrate",
44500
+ 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)."
44501
+ },
44502
+ args: {
44503
+ fleet: {
44504
+ type: "boolean",
44505
+ description: "Multi-project survey \u2014 walk every .cleo/-bearing subdir under --fleet-root"
44506
+ },
44507
+ "fleet-root": {
44508
+ type: "string",
44509
+ description: "Fleet root path (default: /mnt/projects). Only used with --fleet."
44510
+ },
44511
+ "integrity-timeout-ms": {
44512
+ type: "string",
44513
+ description: "Wall-clock budget for each PRAGMA integrity_check call (ms; default 60000; 0 disables)."
44514
+ },
44515
+ "no-quarantine": {
44516
+ type: "boolean",
44517
+ description: "Disable auto-quarantine of corrupt DBs (leaves them in place; report-only mode)."
44518
+ },
44519
+ json: { type: "boolean", description: "Output as JSON" },
44520
+ human: { type: "boolean", description: "Force human-readable output" },
44521
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
44522
+ },
44523
+ async run({ args }) {
44524
+ const isFleet = args.fleet === true;
44525
+ let parsedTimeoutMs;
44526
+ if (typeof args["integrity-timeout-ms"] === "string" && args["integrity-timeout-ms"].length > 0) {
44527
+ const n = Number.parseInt(args["integrity-timeout-ms"], 10);
44528
+ if (Number.isFinite(n) && n >= 0) {
44529
+ parsedTimeoutMs = n;
44530
+ }
44531
+ }
44532
+ const options = {
44533
+ ...parsedTimeoutMs !== void 0 ? { integrityCheckTimeoutMs: parsedTimeoutMs } : {},
44534
+ autoQuarantine: args["no-quarantine"] !== true
44535
+ };
44536
+ const result = isFleet ? surveyFleetDbSubstrate(
44537
+ typeof args["fleet-root"] === "string" && args["fleet-root"].length > 0 ? args["fleet-root"] : DEFAULT_FLEET_ROOT,
44538
+ options
44539
+ ) : surveyDbSubstrate(getProjectRoot34(), options);
44540
+ pushSubstrateWarnings(result);
44541
+ pushPerDbWarnings(result);
44542
+ cliOutput(result, {
44543
+ command: "doctor",
44544
+ operation: "doctor.db-substrate.run"
44545
+ });
44546
+ if (result.summary.corrupt > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
44547
+ process.exitCode = 2;
44548
+ }
44549
+ }
44550
+ });
44551
+ }
44552
+ });
44553
+
44554
+ // packages/cleo/src/cli/commands/doctor-legacy-backups.ts
44555
+ var doctor_legacy_backups_exports = {};
44556
+ __export(doctor_legacy_backups_exports, {
44557
+ doctorLegacyBackupsCommand: () => doctorLegacyBackupsCommand
44558
+ });
44559
+ import { getProjectRoot as getProjectRoot35 } from "@cleocode/core";
44560
+ import { pruneLegacyBackups, scanLegacyBackups } from "@cleocode/core/doctor/legacy-backups.js";
44561
+ function parsePositiveInt(raw, fallback) {
44562
+ if (raw === void 0 || raw === null) return fallback;
44563
+ const parsed = Number.parseInt(String(raw), 10);
44564
+ if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
44565
+ return parsed;
44566
+ }
44567
+ var doctorLegacyBackupsCommand;
44568
+ var init_doctor_legacy_backups = __esm({
44569
+ "packages/cleo/src/cli/commands/doctor-legacy-backups.ts"() {
44570
+ "use strict";
44571
+ init_define_cli_command();
44572
+ init_renderers();
44573
+ doctorLegacyBackupsCommand = defineCommand({
44574
+ meta: {
44575
+ name: "legacy-backups",
44576
+ 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)."
44577
+ },
44578
+ args: {
44579
+ prune: {
44580
+ type: "boolean",
44581
+ description: "Remove every artefact whose recommendation is 'delete'. Defaults to --dry-run; pass --no-dry-run to physically remove."
44582
+ },
44583
+ "dry-run": {
44584
+ type: "boolean",
44585
+ description: "Combine with --prune to preview deletions without touching the filesystem.",
44586
+ default: true
44587
+ },
44588
+ "soft-retention-days": {
44589
+ type: "string",
44590
+ description: "Days under which artefacts are always kept (default 30)."
44591
+ },
44592
+ "hard-retention-days": {
44593
+ type: "string",
44594
+ description: "Days over which artefacts are eligible for prune (default 90)."
44595
+ },
44596
+ json: { type: "boolean", description: "Output as JSON" },
44597
+ human: { type: "boolean", description: "Force human-readable output" },
44598
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
44599
+ },
44600
+ async run({ args }) {
44601
+ const softRetentionDays = parsePositiveInt(args["soft-retention-days"], 30);
44602
+ const hardRetentionDays = parsePositiveInt(args["hard-retention-days"], 90);
44603
+ const projectRoot = getProjectRoot35();
44604
+ let result;
44605
+ if (args.prune === true) {
44606
+ const dryRun = args["dry-run"] !== false;
44607
+ result = pruneLegacyBackups(projectRoot, {
44608
+ softRetentionDays,
44609
+ hardRetentionDays,
44610
+ dryRun
44611
+ });
44612
+ } else {
44613
+ result = scanLegacyBackups(projectRoot, {
44614
+ softRetentionDays,
44615
+ hardRetentionDays
44616
+ });
44617
+ }
44618
+ cliOutput(result, {
44619
+ command: "doctor",
44620
+ operation: "doctor.legacy-backups.run"
44621
+ });
44622
+ if (result.errors.length > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
44623
+ process.exitCode = 1;
44624
+ }
44625
+ }
44626
+ });
44627
+ }
44628
+ });
44629
+
43975
44630
  // packages/cleo/src/cli/commands/doctor-projects.ts
43976
44631
  var doctor_projects_exports = {};
43977
44632
  __export(doctor_projects_exports, {
@@ -44236,66 +44891,6 @@ ${this.prefix}: \u2717 ${message}
44236
44891
  }
44237
44892
  });
44238
44893
 
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
44894
  // packages/cleo/src/cli/commands/migrate-agents-v2.ts
44300
44895
  var migrate_agents_v2_exports = {};
44301
44896
  __export(migrate_agents_v2_exports, {
@@ -44307,8 +44902,8 @@ __export(migrate_agents_v2_exports, {
44307
44902
  });
44308
44903
  import { createHash as createHash2 } from "node:crypto";
44309
44904
  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";
44905
+ import { join as join22 } from "node:path";
44906
+ import { getProjectRoot as getProjectRoot36, installAgentFromCant } from "@cleocode/core/internal";
44312
44907
  import { openCleoDb as openCleoDb2 } from "@cleocode/core/store/open-cleo-db";
44313
44908
  function sha256Hex(bytes) {
44314
44909
  return createHash2("sha256").update(bytes).digest("hex");
@@ -44327,8 +44922,8 @@ function extractAgentName(source) {
44327
44922
  return headerMatch[1] ?? null;
44328
44923
  }
44329
44924
  function appendAuditLog(projectRoot, entry) {
44330
- const auditPath = join23(projectRoot, AUDIT_LOG_RELATIVE);
44331
- const auditDir = join23(auditPath, "..");
44925
+ const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
44926
+ const auditDir = join22(auditPath, "..");
44332
44927
  if (!existsSync14(auditDir)) {
44333
44928
  mkdirSync3(auditDir, { recursive: true });
44334
44929
  }
@@ -44346,7 +44941,7 @@ function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
44346
44941
  return;
44347
44942
  }
44348
44943
  for (const filename of files) {
44349
- const cantPath = join23(scanDir, filename);
44944
+ const cantPath = join22(scanDir, filename);
44350
44945
  const relPath = cantPath.replace(`${projectRoot}/`, "");
44351
44946
  let sourceBytes;
44352
44947
  let sourceText;
@@ -44443,9 +45038,9 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
44443
45038
  const { db: _sdDb } = await openCleoDb2("signaldock");
44444
45039
  const db = _sdDb;
44445
45040
  try {
44446
- const canonicalDir = join23(projectRoot, ".cleo", "cant", "agents");
45041
+ const canonicalDir = join22(projectRoot, ".cleo", "cant", "agents");
44447
45042
  walkAgentsDir(db, canonicalDir, projectRoot, summary, verbose);
44448
- const legacyDir = join23(projectRoot, ".cleo", "agents");
45043
+ const legacyDir = join22(projectRoot, ".cleo", "agents");
44449
45044
  walkAgentsDir(db, legacyDir, projectRoot, summary, verbose);
44450
45045
  } finally {
44451
45046
  db.close();
@@ -44453,7 +45048,7 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
44453
45048
  return summary;
44454
45049
  }
44455
45050
  function readMigrationConflicts(projectRoot) {
44456
- const auditPath = join23(projectRoot, AUDIT_LOG_RELATIVE);
45051
+ const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
44457
45052
  if (!existsSync14(auditPath)) return [];
44458
45053
  let raw;
44459
45054
  try {
@@ -44495,7 +45090,7 @@ var init_migrate_agents_v2 = __esm({
44495
45090
  }
44496
45091
  },
44497
45092
  async run({ args }) {
44498
- const projectRoot = getProjectRoot34();
45093
+ const projectRoot = getProjectRoot36();
44499
45094
  const verbose = args.quiet !== true;
44500
45095
  if (verbose) {
44501
45096
  humanInfo("Scanning .cleo/cant/agents/ and .cleo/agents/ for unregistered agents...");
@@ -44538,8 +45133,8 @@ __export(doctor_exports, {
44538
45133
  doctorCommand: () => doctorCommand2
44539
45134
  });
44540
45135
  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";
45136
+ import { join as join23 } from "node:path";
45137
+ import { getProjectRoot as getProjectRoot37, pushWarning as pushWarning3 } from "@cleocode/core";
44543
45138
  import {
44544
45139
  quarantineRogueCleoDir,
44545
45140
  scanRogueCleoDirs
@@ -44577,8 +45172,8 @@ async function scanTestFixturesInProd(projectRoot) {
44577
45172
  }
44578
45173
  async function quarantineTestFixtures(projectRoot, matches) {
44579
45174
  if (matches.length === 0) return 0;
44580
- const cleoDir = join24(projectRoot, ".cleo");
44581
- const quarantineDir = join24(
45175
+ const cleoDir = join23(projectRoot, ".cleo");
45176
+ const quarantineDir = join23(
44582
45177
  cleoDir,
44583
45178
  "quarantine",
44584
45179
  `fixture-scan-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`
@@ -44586,7 +45181,7 @@ async function quarantineTestFixtures(projectRoot, matches) {
44586
45181
  mkdirSync4(quarantineDir, { recursive: true });
44587
45182
  const manifest = matches.map((m) => ({ ...m, quarantinedAt: (/* @__PURE__ */ new Date()).toISOString() }));
44588
45183
  writeFileSync4(
44589
- join24(quarantineDir, "manifest.jsonl"),
45184
+ join23(quarantineDir, "manifest.jsonl"),
44590
45185
  manifest.map((m) => JSON.stringify(m)).join("\n") + "\n"
44591
45186
  );
44592
45187
  const { getNativeDb } = await import("@cleocode/core/store/sqlite.js");
@@ -44650,6 +45245,7 @@ var init_doctor = __esm({
44650
45245
  init_progress();
44651
45246
  init_renderers();
44652
45247
  init_doctor_db_substrate();
45248
+ init_doctor_legacy_backups();
44653
45249
  init_doctor_projects();
44654
45250
  init_migrate_agents_v2();
44655
45251
  FIXTURE_ID_PATTERNS = [/^E\d+$/, /^T\d+EP$/];
@@ -44663,7 +45259,9 @@ var init_doctor = __esm({
44663
45259
  meta: { name: "doctor", description: "Run system diagnostics and health checks" },
44664
45260
  subCommands: {
44665
45261
  // T10307 / Saga T10281 / Epic T10282 — DB-substrate walker
44666
- "db-substrate": doctorDbSubstrateCommand
45262
+ "db-substrate": doctorDbSubstrateCommand,
45263
+ // T10309 / Saga T10281 / Epic T10282 — Legacy-backup walker
45264
+ "legacy-backups": doctorLegacyBackupsCommand
44667
45265
  },
44668
45266
  args: {
44669
45267
  detailed: {
@@ -44831,7 +45429,7 @@ var init_doctor = __esm({
44831
45429
  try {
44832
45430
  if (args.brain) {
44833
45431
  const { computeBrainHealthDashboard } = await import("@cleocode/core/memory/brain-health-dashboard.js");
44834
- const projectRoot = getProjectRoot35();
45432
+ const projectRoot = getProjectRoot37();
44835
45433
  const dashboard = await computeBrainHealthDashboard(projectRoot);
44836
45434
  cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
44837
45435
  if (dashboard.hasP0Failure) {
@@ -44840,7 +45438,7 @@ var init_doctor = __esm({
44840
45438
  return;
44841
45439
  }
44842
45440
  if (args["scan-test-fixtures-in-prod"]) {
44843
- const projectRoot = getProjectRoot35();
45441
+ const projectRoot = getProjectRoot37();
44844
45442
  const matches = await scanTestFixturesInProd(projectRoot);
44845
45443
  const dryRun = args["dry-run"] !== false && args.quarantine !== true;
44846
45444
  const quarantined = !dryRun && matches.length > 0 ? await quarantineTestFixtures(projectRoot, matches) : void 0;
@@ -44928,7 +45526,7 @@ var init_doctor = __esm({
44928
45526
  progress.complete("Comprehensive diagnostics complete");
44929
45527
  } else if (args["scan-rogue-cleo-dirs"]) {
44930
45528
  progress.step(0, "Scanning for rogue .cleo/ directories");
44931
- const projectRoot = getProjectRoot35();
45529
+ const projectRoot = getProjectRoot37();
44932
45530
  const reports = scanRogueCleoDirs(projectRoot);
44933
45531
  progress.complete(
44934
45532
  `Found ${reports.length} rogue .cleo/ director${reports.length === 1 ? "y" : "ies"}`
@@ -44937,7 +45535,7 @@ var init_doctor = __esm({
44937
45535
  } else if (args["quarantine-rogue-cleo-dirs"]) {
44938
45536
  const isDryRun = args["dry-run"] === true;
44939
45537
  progress.step(0, `${isDryRun ? "[DRY RUN] " : ""}Scanning for rogue .cleo/ directories`);
44940
- const projectRoot = getProjectRoot35();
45538
+ const projectRoot = getProjectRoot37();
44941
45539
  const reports = scanRogueCleoDirs(projectRoot);
44942
45540
  if (reports.length === 0) {
44943
45541
  progress.complete("No rogue .cleo/ directories found \u2014 nothing to quarantine");
@@ -44991,7 +45589,7 @@ var init_doctor = __esm({
44991
45589
  const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/store/cleanup-legacy.js");
44992
45590
  const { getCleoHome: getCleoHome6 } = await import("@cleocode/core");
44993
45591
  const cleoHome = getCleoHome6();
44994
- const projectRoot = getProjectRoot35();
45592
+ const projectRoot = getProjectRoot37();
44995
45593
  const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
44996
45594
  const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
44997
45595
  const isDryRun = args["dry-run"] === true;
@@ -45024,7 +45622,7 @@ var init_doctor = __esm({
45024
45622
  } else if (args["audit-worktree-orphans"]) {
45025
45623
  progress.step(0, "Comprehensive worktree anomaly audit (T9808 / council D009)");
45026
45624
  const { auditWorktreeOrphansComprehensive, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
45027
- const projectRoot = getProjectRoot35();
45625
+ const projectRoot = getProjectRoot37();
45028
45626
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
45029
45627
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
45030
45628
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -45081,7 +45679,7 @@ var init_doctor = __esm({
45081
45679
  `${isDryRun ? "[DRY RUN] " : ""}Scanning + pruning worktree-orphan .cleo/ directories`
45082
45680
  );
45083
45681
  const { pruneWorktreeOrphans, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
45084
- const projectRoot = getProjectRoot35();
45682
+ const projectRoot = getProjectRoot37();
45085
45683
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
45086
45684
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
45087
45685
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -45129,8 +45727,8 @@ var init_doctor = __esm({
45129
45727
  );
45130
45728
  return;
45131
45729
  }
45132
- const archiveDir = join24(projectRoot, ".cleo", "backups");
45133
- const auditLogPath = join24(projectRoot, ".cleo", "audit", "worktree-prune.jsonl");
45730
+ const archiveDir = join23(projectRoot, ".cleo", "backups");
45731
+ const auditLogPath = join23(projectRoot, ".cleo", "audit", "worktree-prune.jsonl");
45134
45732
  const result = await pruneWorktreeOrphans(orphans, {
45135
45733
  archiveDir,
45136
45734
  auditLogPath,
@@ -45160,7 +45758,7 @@ var init_doctor = __esm({
45160
45758
  `${isDryRun ? "[DRY RUN] " : ""}Migrating .cleo/worktree-include \u2192 .worktreeinclude`
45161
45759
  );
45162
45760
  const { migrateWorktreeIncludeFile } = await import("@cleocode/core");
45163
- const projectRoot = getProjectRoot35();
45761
+ const projectRoot = getProjectRoot37();
45164
45762
  const result = await migrateWorktreeIncludeFile(projectRoot, { dryRun: isDryRun });
45165
45763
  progress.complete(`Migration ${result.action}`);
45166
45764
  cliOutput(result, { command: "doctor", operation: "doctor.migrate-worktree-include" });
@@ -45176,7 +45774,7 @@ var init_doctor = __esm({
45176
45774
  } else if (args["audit-sagas"]) {
45177
45775
  progress.step(0, "Auditing Saga hierarchy for ADR-073 invariants");
45178
45776
  const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
45179
- const projectRoot = getProjectRoot35();
45777
+ const projectRoot = getProjectRoot37();
45180
45778
  const result = await auditSagaHierarchy(projectRoot);
45181
45779
  const summary = `Saga audit complete \u2014 ${result.sagas.length} saga(s) inspected, ${result.count} invariant violation(s), ${result.driftCount} drift warning(s)`;
45182
45780
  progress.complete(summary);
@@ -45194,7 +45792,7 @@ var init_doctor = __esm({
45194
45792
  { command: "doctor", operation: "admin.health" }
45195
45793
  );
45196
45794
  try {
45197
- const projectRoot = getProjectRoot35();
45795
+ const projectRoot = getProjectRoot37();
45198
45796
  const conflicts = readMigrationConflicts(projectRoot);
45199
45797
  if (conflicts.length > 0) {
45200
45798
  progress.complete(
@@ -45225,7 +45823,7 @@ var init_doctor = __esm({
45225
45823
  progress.complete("Health check complete");
45226
45824
  }
45227
45825
  try {
45228
- const projectRoot = getProjectRoot35();
45826
+ const projectRoot = getProjectRoot37();
45229
45827
  const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
45230
45828
  const sagaAudit = await auditSagaHierarchy(projectRoot);
45231
45829
  if (sagaAudit.sagas.length === 0) {
@@ -45287,7 +45885,7 @@ __export(event_exports, {
45287
45885
  orchestratorCommand: () => orchestratorCommand
45288
45886
  });
45289
45887
  import { readdir as readdir2 } from "node:fs/promises";
45290
- import { join as join25 } from "node:path";
45888
+ import { join as join24 } from "node:path";
45291
45889
  import { cwd as processCwd } from "node:process";
45292
45890
  import { appendEvent } from "@cleocode/core/events/event-bus.js";
45293
45891
  function resolveProjectRoot3(arg) {
@@ -45410,7 +46008,7 @@ var init_event = __esm({
45410
46008
  const agentIdFilter = args.agent;
45411
46009
  const showAll = args.all === true;
45412
46010
  const lines = parseInt(args.lines ?? "20", 10);
45413
- const eventsDir = join25(projectRoot, ".cleo", "agent-events");
46011
+ const eventsDir = join24(projectRoot, ".cleo", "agent-events");
45414
46012
  try {
45415
46013
  let files = [];
45416
46014
  try {
@@ -45448,7 +46046,7 @@ var init_event = __esm({
45448
46046
  for (const file of filesToTail) {
45449
46047
  const agentId = file.replace(".jsonl", "");
45450
46048
  const { readFileSync: readFileSync18 } = await import("node:fs");
45451
- const content = readFileSync18(join25(eventsDir, file), "utf-8");
46049
+ const content = readFileSync18(join24(eventsDir, file), "utf-8");
45452
46050
  const eventLines = content.trim().split("\n").filter(Boolean);
45453
46051
  const tail = eventLines.slice(-lines);
45454
46052
  if (jsonMode) {
@@ -45518,7 +46116,7 @@ var init_event = __esm({
45518
46116
  const epicFilter = args.epic;
45519
46117
  const follow = args.follow === true;
45520
46118
  const lines = parseInt(args.lines ?? "50", 10);
45521
- const eventsDir = join25(projectRoot, ".cleo", "agent-events");
46119
+ const eventsDir = join24(projectRoot, ".cleo", "agent-events");
45522
46120
  let files = [];
45523
46121
  try {
45524
46122
  const entries = await readdir2(eventsDir);
@@ -45544,7 +46142,7 @@ var init_event = __esm({
45544
46142
  const agentId = file.replace(".jsonl", "");
45545
46143
  try {
45546
46144
  const { readFileSync: readFileSync18 } = await import("node:fs");
45547
- const content = readFileSync18(join25(eventsDir, file), "utf-8");
46145
+ const content = readFileSync18(join24(eventsDir, file), "utf-8");
45548
46146
  const eventLines = content.trim().split("\n").filter(Boolean);
45549
46147
  const tail = eventLines.slice(-lines);
45550
46148
  if (jsonMode) {
@@ -46083,7 +46681,7 @@ __export(gc_exports, {
46083
46681
  gcCommand: () => gcCommand
46084
46682
  });
46085
46683
  import { homedir as homedir4, tmpdir } from "node:os";
46086
- import { join as join26 } from "node:path";
46684
+ import { join as join25 } from "node:path";
46087
46685
  import { pruneOrphanTempDirs, pruneOrphanWorktrees } from "@cleocode/core/gc/cleanup.js";
46088
46686
  import { runGC } from "@cleocode/core/gc/runner.js";
46089
46687
  import { readGCState } from "@cleocode/core/gc/state.js";
@@ -46166,7 +46764,7 @@ var init_gc = __esm({
46166
46764
  },
46167
46765
  async run({ args }) {
46168
46766
  const cleoDir = resolveLegacyCleoDir3(args["cleo-dir"]);
46169
- const statePath = join26(cleoDir, "gc-state.json");
46767
+ const statePath = join25(cleoDir, "gc-state.json");
46170
46768
  try {
46171
46769
  const state = await readGCState(statePath);
46172
46770
  const diskStr = state.lastDiskUsedPct !== null ? `${state.lastDiskUsedPct.toFixed(1)}%` : "unknown";
@@ -46219,8 +46817,8 @@ var init_gc = __esm({
46219
46817
  }
46220
46818
  },
46221
46819
  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");
46820
+ const xdgData = process.env["XDG_DATA_HOME"] ?? join25(homedir4(), ".local", "share");
46821
+ const worktreesRoot = args["worktrees-root"] ?? join25(xdgData, "cleo", "worktrees");
46224
46822
  const projectHash = args["project-hash"];
46225
46823
  const dryRun = args["dry-run"];
46226
46824
  const preserveRaw = args["preserve-tasks"];
@@ -47433,7 +48031,7 @@ __export(init_exports, {
47433
48031
  initCommand: () => initCommand2
47434
48032
  });
47435
48033
  import { existsSync as existsSync15, readFileSync as readFileSync15 } from "node:fs";
47436
- import { join as join27 } from "node:path";
48034
+ import { join as join26 } from "node:path";
47437
48035
  import { fileURLToPath as fileURLToPath6 } from "node:url";
47438
48036
  import {
47439
48037
  CleoError as CleoError4,
@@ -47445,9 +48043,9 @@ import {
47445
48043
  function getGitignoreTemplate() {
47446
48044
  try {
47447
48045
  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");
48046
+ const packageRoot = join26(thisFile, "..", "..", "..", "..");
48047
+ const localTemplatePath = join26(packageRoot, "templates", "cleo-gitignore");
48048
+ const monorepoTemplatePath = join26(packageRoot, "..", "..", "templates", "cleo-gitignore");
47451
48049
  const templatePath = existsSync15(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
47452
48050
  if (existsSync15(templatePath)) {
47453
48051
  return readFileSync15(templatePath, "utf-8");
@@ -48372,7 +48970,7 @@ var llm_cost_exports = {};
48372
48970
  __export(llm_cost_exports, {
48373
48971
  costCommand: () => costCommand
48374
48972
  });
48375
- import { getProjectRoot as getProjectRoot36 } from "@cleocode/core/internal";
48973
+ import { getProjectRoot as getProjectRoot38 } from "@cleocode/core/internal";
48376
48974
  import { computeCost } from "@cleocode/core/llm/usage-pricing";
48377
48975
  function resolveSessionId(raw) {
48378
48976
  if (raw === "current") {
@@ -48445,7 +49043,7 @@ var init_llm_cost = __esm({
48445
49043
  process.exit(6);
48446
49044
  }
48447
49045
  const sessionId = resolveSessionId(rawSessionId);
48448
- const projectRoot = getProjectRoot36(process.cwd());
49046
+ const projectRoot = getProjectRoot38(process.cwd());
48449
49047
  let breakdown;
48450
49048
  try {
48451
49049
  breakdown = await loadSessionCostBreakdown(projectRoot, sessionId);
@@ -49992,7 +50590,7 @@ var memory_exports = {};
49992
50590
  __export(memory_exports, {
49993
50591
  memoryCommand: () => memoryCommand
49994
50592
  });
49995
- import { getProjectRoot as getProjectRoot37 } from "@cleocode/core";
50593
+ import { getProjectRoot as getProjectRoot39 } from "@cleocode/core";
49996
50594
  import {
49997
50595
  getBrainDb as getBrainDb2,
49998
50596
  getDreamStatus,
@@ -50916,7 +51514,7 @@ var init_memory3 = __esm({
50916
51514
  },
50917
51515
  args: {},
50918
51516
  async run() {
50919
- const root = getProjectRoot37();
51517
+ const root = getProjectRoot39();
50920
51518
  try {
50921
51519
  const result = await runConsolidation(root);
50922
51520
  cliOutput(result, { command: "memory-consolidate", operation: "memory.consolidate" });
@@ -50940,7 +51538,7 @@ var init_memory3 = __esm({
50940
51538
  }
50941
51539
  },
50942
51540
  async run({ args }) {
50943
- const root = getProjectRoot37();
51541
+ const root = getProjectRoot39();
50944
51542
  if (args.status) {
50945
51543
  try {
50946
51544
  const status = await getDreamStatus(root);
@@ -50977,7 +51575,7 @@ var init_memory3 = __esm({
50977
51575
  }
50978
51576
  },
50979
51577
  async run({ args }) {
50980
- const root = getProjectRoot37();
51578
+ const root = getProjectRoot39();
50981
51579
  try {
50982
51580
  const { runObserver, runReflector } = await import("@cleocode/core/memory");
50983
51581
  const observerResult = await runObserver(root, args.session, {
@@ -51017,7 +51615,7 @@ var init_memory3 = __esm({
51017
51615
  }
51018
51616
  },
51019
51617
  async run({ args }) {
51020
- const root = getProjectRoot37();
51618
+ const root = getProjectRoot39();
51021
51619
  try {
51022
51620
  await getBrainDb2(root);
51023
51621
  const { totalDuplicateRows, groups } = await scanDuplicateEntries();
@@ -51063,7 +51661,7 @@ var init_memory3 = __esm({
51063
51661
  async run({ args }) {
51064
51662
  const sourceDir = args.from;
51065
51663
  const isDryRun = !!args["dry-run"];
51066
- const projectRoot = getProjectRoot37();
51664
+ const projectRoot = getProjectRoot39();
51067
51665
  try {
51068
51666
  const result = await importMemoryFiles({
51069
51667
  sourceDir,
@@ -51214,7 +51812,7 @@ var init_memory3 = __esm({
51214
51812
  },
51215
51813
  args: {},
51216
51814
  async run() {
51217
- const root = getProjectRoot37();
51815
+ const root = getProjectRoot39();
51218
51816
  try {
51219
51817
  await getBrainDb2(root);
51220
51818
  const result = await getTierStats(root);
@@ -51257,7 +51855,7 @@ var init_memory3 = __esm({
51257
51855
  }
51258
51856
  },
51259
51857
  async run({ args }) {
51260
- const root = getProjectRoot37();
51858
+ const root = getProjectRoot39();
51261
51859
  const targetTier = args.to;
51262
51860
  const reason = args.reason;
51263
51861
  const validTiers = ["medium", "long"];
@@ -51323,7 +51921,7 @@ var init_memory3 = __esm({
51323
51921
  }
51324
51922
  },
51325
51923
  async run({ args }) {
51326
- const root = getProjectRoot37();
51924
+ const root = getProjectRoot39();
51327
51925
  const targetTier = args.to;
51328
51926
  const reason = args.reason;
51329
51927
  const validTiers = ["short", "medium"];
@@ -51783,7 +52381,7 @@ var migrate_claude_mem_exports = {};
51783
52381
  __export(migrate_claude_mem_exports, {
51784
52382
  migrateClaudeMemCommand: () => migrateClaudeMemCommand
51785
52383
  });
51786
- import { getProjectRoot as getProjectRoot38, migrateClaudeMem } from "@cleocode/core/internal";
52384
+ import { getProjectRoot as getProjectRoot40, migrateClaudeMem } from "@cleocode/core/internal";
51787
52385
  import { ingestLooseAgentOutputs, ingestRcasdDirectories } from "@cleocode/core/memory";
51788
52386
  import { getDb as getDb2 } from "@cleocode/core/store/sqlite";
51789
52387
  var storageCommand, claudeMemCommand, manifestIngestCommand, migrateClaudeMemCommand;
@@ -51846,7 +52444,7 @@ var init_migrate_claude_mem = __esm({
51846
52444
  }
51847
52445
  },
51848
52446
  async run({ args }) {
51849
- const root = getProjectRoot38();
52447
+ const root = getProjectRoot40();
51850
52448
  try {
51851
52449
  const result = await migrateClaudeMem(root, {
51852
52450
  sourcePath: args.source,
@@ -51895,7 +52493,7 @@ var init_migrate_claude_mem = __esm({
51895
52493
  }
51896
52494
  },
51897
52495
  async run({ args }) {
51898
- const projectRoot = getProjectRoot38();
52496
+ const projectRoot = getProjectRoot40();
51899
52497
  try {
51900
52498
  const db = await getDb2(projectRoot);
51901
52499
  const rcasdFlag = Boolean(args.rcasd);
@@ -51999,7 +52597,7 @@ __export(nexus_exports, {
51999
52597
  import { appendFile as appendFile2, mkdir as mkdir3 } from "node:fs/promises";
52000
52598
  import { homedir as homedir5 } from "node:os";
52001
52599
  import path4 from "node:path";
52002
- import { getProjectRoot as getProjectRoot39 } from "@cleocode/core";
52600
+ import { getProjectRoot as getProjectRoot41 } from "@cleocode/core";
52003
52601
  import { getSymbolImpact } from "@cleocode/core/nexus";
52004
52602
  import { runNexusAnalysis } from "@cleocode/core/nexus/analyze-orchestrator.js";
52005
52603
  import { exportNexusGraph } from "@cleocode/core/nexus/export.js";
@@ -52114,7 +52712,7 @@ var init_nexus3 = __esm({
52114
52712
  async run({ args }) {
52115
52713
  applyJsonFlag2(args.json);
52116
52714
  const projectIdOverride = args["project-id"];
52117
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
52715
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52118
52716
  const startTime = Date.now();
52119
52717
  try {
52120
52718
  const [{ getNexusDb, nexusSchema }, { getIndexStats }] = await Promise.all([
@@ -52629,7 +53227,7 @@ var init_nexus3 = __esm({
52629
53227
  applyJsonFlag2(args.json);
52630
53228
  const startTime = Date.now();
52631
53229
  const projectIdOverride = args["project-id"];
52632
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53230
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52633
53231
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
52634
53232
  const response = await dispatchRaw("query", "nexus", "clusters", { projectId, repoPath });
52635
53233
  const durationMs = Date.now() - startTime;
@@ -52673,7 +53271,7 @@ var init_nexus3 = __esm({
52673
53271
  applyJsonFlag2(args.json);
52674
53272
  const startTime = Date.now();
52675
53273
  const projectIdOverride = args["project-id"];
52676
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53274
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52677
53275
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
52678
53276
  const response = await dispatchRaw("query", "nexus", "flows", { projectId, repoPath });
52679
53277
  const durationMs = Date.now() - startTime;
@@ -52716,7 +53314,7 @@ var init_nexus3 = __esm({
52716
53314
  void appendDeprecationTelemetry("nexus.context", "cleo graph context");
52717
53315
  const startTime = Date.now();
52718
53316
  const projectIdOverride = args["project-id"];
52719
- const repoPath = getProjectRoot39();
53317
+ const repoPath = getProjectRoot41();
52720
53318
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
52721
53319
  const limit = parseInt(args.limit, 10);
52722
53320
  const symbolName = args.symbol;
@@ -52779,7 +53377,7 @@ var init_nexus3 = __esm({
52779
53377
  const startTime = Date.now();
52780
53378
  const whyFlag = !!args.why;
52781
53379
  const projectIdOverride = args["project-id"];
52782
- const repoPath = getProjectRoot39();
53380
+ const repoPath = getProjectRoot41();
52783
53381
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
52784
53382
  const maxDepth = Math.min(parseInt(args.depth, 10), 5);
52785
53383
  const symbolName = args.symbol;
@@ -52851,7 +53449,7 @@ var init_nexus3 = __esm({
52851
53449
  const projectIdOverride = args["project-id"];
52852
53450
  const isIncremental = !!args.incremental;
52853
53451
  const ctx = getFormatContext();
52854
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53452
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52855
53453
  humanInfo(`[nexus] Analyzing: ${repoPath}${isIncremental ? " (incremental)" : ""}`);
52856
53454
  if (!isIncremental) humanInfo("[nexus] Clearing existing index for project...");
52857
53455
  try {
@@ -52954,7 +53552,7 @@ var init_nexus3 = __esm({
52954
53552
  async run({ args }) {
52955
53553
  applyJsonFlag2(args.json);
52956
53554
  const startTime = Date.now();
52957
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53555
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
52958
53556
  const name = args.name;
52959
53557
  const response = await dispatchRaw("mutate", "nexus", "projects.register", {
52960
53558
  path: repoPath,
@@ -53312,7 +53910,7 @@ var init_nexus3 = __esm({
53312
53910
  applyJsonFlag2(args.json);
53313
53911
  const startTime = Date.now();
53314
53912
  const projectIdOverride = args["project-id"];
53315
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
53913
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53316
53914
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53317
53915
  const response = await dispatchRaw("mutate", "nexus", "refresh-bridge", {
53318
53916
  repoPath,
@@ -53418,7 +54016,7 @@ var init_nexus3 = __esm({
53418
54016
  async run({ args }) {
53419
54017
  applyJsonFlag2(args.json);
53420
54018
  const startTime = Date.now();
53421
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
54019
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53422
54020
  const projectIdOverride = args["project-id"];
53423
54021
  const beforeRef = args.before ?? "HEAD~1";
53424
54022
  const afterRef = args.after ?? "HEAD";
@@ -53536,7 +54134,7 @@ var init_nexus3 = __esm({
53536
54134
  applyJsonFlag2(args.json);
53537
54135
  const startTime = Date.now();
53538
54136
  const projectIdOverride = args["project-id"];
53539
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
54137
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53540
54138
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53541
54139
  const response = await dispatchRaw("query", "nexus", "route-map", { projectId });
53542
54140
  const durationMs = Date.now() - startTime;
@@ -53592,7 +54190,7 @@ var init_nexus3 = __esm({
53592
54190
  const startTime = Date.now();
53593
54191
  const routeSymbol = args.routeSymbol;
53594
54192
  const projectIdOverride = args["project-id"];
53595
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
54193
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53596
54194
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53597
54195
  const response = await dispatchRaw("query", "nexus", "shape-check", { routeSymbol, projectId });
53598
54196
  const durationMs = Date.now() - startTime;
@@ -53982,7 +54580,7 @@ var init_nexus3 = __esm({
53982
54580
  async run({ args }) {
53983
54581
  applyJsonFlag2(args.json);
53984
54582
  const startTime = Date.now();
53985
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
54583
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
53986
54584
  const projectIdOverride = args["project-id"];
53987
54585
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53988
54586
  const response = await dispatchRaw("mutate", "nexus", "contracts-sync", {
@@ -54086,7 +54684,7 @@ var init_nexus3 = __esm({
54086
54684
  async run({ args }) {
54087
54685
  applyJsonFlag2(args.json);
54088
54686
  const startTime = Date.now();
54089
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot39();
54687
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
54090
54688
  const projectId = Buffer.from(repoPath).toString("base64url").slice(0, 32);
54091
54689
  const response = await dispatchRaw("mutate", "nexus", "contracts-link-tasks", {
54092
54690
  projectId,
@@ -54167,7 +54765,7 @@ var init_nexus3 = __esm({
54167
54765
  const isIncremental = !!args.incremental;
54168
54766
  try {
54169
54767
  const result = await runNexusWiki({
54170
- projectRoot: getProjectRoot39(),
54768
+ projectRoot: getProjectRoot41(),
54171
54769
  outputDir,
54172
54770
  communityFilter,
54173
54771
  incremental: isIncremental
@@ -56594,7 +57192,7 @@ var refresh_memory_exports = {};
56594
57192
  __export(refresh_memory_exports, {
56595
57193
  refreshMemoryCommand: () => refreshMemoryCommand
56596
57194
  });
56597
- import { getProjectRoot as getProjectRoot40 } from "@cleocode/core";
57195
+ import { getProjectRoot as getProjectRoot42 } from "@cleocode/core";
56598
57196
  var refreshMemoryCommand;
56599
57197
  var init_refresh_memory = __esm({
56600
57198
  "packages/cleo/src/cli/commands/refresh-memory.ts"() {
@@ -56607,7 +57205,7 @@ var init_refresh_memory = __esm({
56607
57205
  description: "Regenerate .cleo/memory-bridge.md from brain.db"
56608
57206
  },
56609
57207
  async run() {
56610
- const projectDir = getProjectRoot40();
57208
+ const projectDir = getProjectRoot42();
56611
57209
  const { writeMemoryBridge } = await import("@cleocode/core/internal");
56612
57210
  const result = await writeMemoryBridge(projectDir);
56613
57211
  if (result.written) {
@@ -58008,7 +58606,7 @@ import fs3 from "node:fs";
58008
58606
  import path5 from "node:path";
58009
58607
  import {
58010
58608
  CleoError as CleoError7,
58011
- getProjectRoot as getProjectRoot41,
58609
+ getProjectRoot as getProjectRoot43,
58012
58610
  getTaskAccessor as getTaskAccessor3,
58013
58611
  parseConflictReport,
58014
58612
  setAtPath
@@ -58029,7 +58627,7 @@ var init_restore = __esm({
58029
58627
  description: "Apply manually-resolved conflicts from .cleo/restore-conflicts.md"
58030
58628
  },
58031
58629
  async run() {
58032
- const projectRoot = getProjectRoot41();
58630
+ const projectRoot = getProjectRoot43();
58033
58631
  const reportPath = path5.join(projectRoot, CLEO_DIR_NAME, RESTORE_CONFLICTS_MD);
58034
58632
  if (!fs3.existsSync(reportPath)) {
58035
58633
  humanLine("No pending restore conflicts. Nothing to finalize.");
@@ -58395,7 +58993,7 @@ __export(revert_exports, {
58395
58993
  revertCommand: () => revertCommand
58396
58994
  });
58397
58995
  import { readFile as readFile4 } from "node:fs/promises";
58398
- import { join as join28 } from "node:path";
58996
+ import { join as join27 } from "node:path";
58399
58997
  import { cwd as processCwd2 } from "node:process";
58400
58998
  import { E_RECEIPT_NOT_FOUND } from "@cleocode/core/sentient/chain-walker.js";
58401
58999
  import { SENTIENT_STATE_FILE } from "@cleocode/core/sentient/daemon.js";
@@ -58448,7 +59046,7 @@ async function loadOwnerAttestation(attestationFilePath) {
58448
59046
  return obj;
58449
59047
  }
58450
59048
  async function loadOwnerPubkeys(projectRoot) {
58451
- const path6 = join28(projectRoot, OWNER_PUBKEYS_FILE);
59049
+ const path6 = join27(projectRoot, OWNER_PUBKEYS_FILE);
58452
59050
  try {
58453
59051
  const raw = await readFile4(path6, "utf-8");
58454
59052
  const parsed = JSON.parse(raw);
@@ -58532,7 +59130,7 @@ var init_revert = __esm({
58532
59130
  if (attestation && allowedPubkeys.size > 0 && !allowedPubkeys.has(attestation.ownerPubkey)) {
58533
59131
  emitFailure2(
58534
59132
  E_OWNER_ATTESTATION_REQUIRED,
58535
- `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join28(projectRoot, OWNER_PUBKEYS_FILE)}`,
59133
+ `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join27(projectRoot, OWNER_PUBKEYS_FILE)}`,
58536
59134
  jsonMode
58537
59135
  );
58538
59136
  }
@@ -58585,7 +59183,7 @@ ${lines}`
58585
59183
  identity,
58586
59184
  includeHuman
58587
59185
  });
58588
- const statePath = join28(projectRoot, SENTIENT_STATE_FILE);
59186
+ const statePath = join27(projectRoot, SENTIENT_STATE_FILE);
58589
59187
  const state = await readSentientState(statePath);
58590
59188
  emitSuccess(
58591
59189
  {
@@ -59055,7 +59653,7 @@ __export(self_update_exports, {
59055
59653
  });
59056
59654
  import { execFile } from "node:child_process";
59057
59655
  import { readFile as readFile5 } from "node:fs/promises";
59058
- import { join as join29 } from "node:path";
59656
+ import { join as join28 } from "node:path";
59059
59657
  import * as readline2 from "node:readline";
59060
59658
  import { promisify } from "node:util";
59061
59659
  import {
@@ -59070,7 +59668,7 @@ import {
59070
59668
  async function getCurrentVersion() {
59071
59669
  const cleoHome = getCleoHome4();
59072
59670
  try {
59073
- const content = await readFile5(join29(cleoHome, "VERSION"), "utf-8");
59671
+ const content = await readFile5(join28(cleoHome, "VERSION"), "utf-8");
59074
59672
  return (content.split("\n")[0] ?? "unknown").trim();
59075
59673
  } catch {
59076
59674
  return "unknown";
@@ -59124,7 +59722,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
59124
59722
  ];
59125
59723
  await import("node:fs/promises").then(
59126
59724
  ({ writeFile: writeFile4, mkdir: mkdir5 }) => mkdir5(cleoHome, { recursive: true }).then(
59127
- () => writeFile4(join29(cleoHome, "VERSION"), `${lines.join("\n")}
59725
+ () => writeFile4(join28(cleoHome, "VERSION"), `${lines.join("\n")}
59128
59726
  `, "utf-8")
59129
59727
  )
59130
59728
  );
@@ -59535,7 +60133,7 @@ var sentient_exports = {};
59535
60133
  __export(sentient_exports, {
59536
60134
  sentientCommand: () => sentientCommand
59537
60135
  });
59538
- import { join as join30 } from "node:path";
60136
+ import { join as join29 } from "node:path";
59539
60137
  import { cwd as processCwd3 } from "node:process";
59540
60138
  import {
59541
60139
  getSentientDaemonStatus as getSentientDaemonStatus2,
@@ -59610,7 +60208,7 @@ var init_sentient3 = __esm({
59610
60208
  return;
59611
60209
  }
59612
60210
  if (dryRun) {
59613
- const statePath2 = join30(projectRoot, SENTIENT_STATE_FILE2);
60211
+ const statePath2 = join29(projectRoot, SENTIENT_STATE_FILE2);
59614
60212
  const outcome = await safeRunTick({ projectRoot, statePath: statePath2, dryRun: true });
59615
60213
  emitSuccess2(
59616
60214
  { dryRun: true, outcome },
@@ -59726,7 +60324,7 @@ Logs: ${logPath}`
59726
60324
  const jsonMode = args.json === true;
59727
60325
  const dryRun = args["dry-run"] === true;
59728
60326
  try {
59729
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60327
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59730
60328
  const outcome = await safeRunTick({ projectRoot, statePath, dryRun });
59731
60329
  emitSuccess2(
59732
60330
  { outcome, dryRun },
@@ -59795,7 +60393,7 @@ Logs: ${logPath}`
59795
60393
  return;
59796
60394
  }
59797
60395
  await db.update(tasks).set({ status: "pending", updatedAt: now }).where(eq2(tasks.id, id)).run();
59798
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60396
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59799
60397
  const state = await readSentientState2(statePath);
59800
60398
  await patchSentientState(statePath, {
59801
60399
  tier2Stats: {
@@ -59847,7 +60445,7 @@ Logs: ${logPath}`
59847
60445
  return;
59848
60446
  }
59849
60447
  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);
60448
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59851
60449
  const state = await readSentientState2(statePath);
59852
60450
  await patchSentientState(statePath, {
59853
60451
  tier2Stats: {
@@ -59892,7 +60490,7 @@ Logs: ${logPath}`
59892
60490
  const projectRoot = resolveProjectRoot6(args.project);
59893
60491
  const jsonMode = args.json === true;
59894
60492
  try {
59895
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60493
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59896
60494
  const outcome = await safeRunProposeTick({ projectRoot, statePath });
59897
60495
  emitSuccess2(
59898
60496
  { outcome },
@@ -59912,7 +60510,7 @@ Logs: ${logPath}`
59912
60510
  const projectRoot = resolveProjectRoot6(args.project);
59913
60511
  const jsonMode = args.json === true;
59914
60512
  try {
59915
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60513
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59916
60514
  const updated = await patchSentientState(statePath, { tier2Enabled: true });
59917
60515
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals enabled");
59918
60516
  } catch (err) {
@@ -59931,7 +60529,7 @@ Logs: ${logPath}`
59931
60529
  const projectRoot = resolveProjectRoot6(args.project);
59932
60530
  const jsonMode = args.json === true;
59933
60531
  try {
59934
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60532
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59935
60533
  const updated = await patchSentientState(statePath, { tier2Enabled: false });
59936
60534
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals disabled");
59937
60535
  } catch (err) {
@@ -59962,7 +60560,7 @@ Logs: ${logPath}`
59962
60560
  const projectRoot = resolveProjectRoot6(args.project);
59963
60561
  const jsonMode = args.json === true;
59964
60562
  try {
59965
- const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
60563
+ const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
59966
60564
  const state = await readSentientState2(statePath);
59967
60565
  emitSuccess2(
59968
60566
  {
@@ -60520,7 +61118,7 @@ var sequence_exports = {};
60520
61118
  __export(sequence_exports, {
60521
61119
  sequenceCommand: () => sequenceCommand
60522
61120
  });
60523
- import { getProjectRoot as getProjectRoot42 } from "@cleocode/core/internal";
61121
+ import { getProjectRoot as getProjectRoot44 } from "@cleocode/core/internal";
60524
61122
  var showCommand12, checkCommand6, repairCommand2, sequenceCommand;
60525
61123
  var init_sequence = __esm({
60526
61124
  "packages/cleo/src/cli/commands/sequence.ts"() {
@@ -60556,7 +61154,7 @@ var init_sequence = __esm({
60556
61154
  meta: { name: "repair", description: "Reset counter to max + 1 if behind" },
60557
61155
  async run() {
60558
61156
  const { repairSequence } = await import("@cleocode/core/internal");
60559
- const projectRoot = getProjectRoot42();
61157
+ const projectRoot = getProjectRoot44();
60560
61158
  const repair = await repairSequence(projectRoot);
60561
61159
  const result = {
60562
61160
  repaired: repair.repaired,
@@ -61011,8 +61609,8 @@ var init_session4 = __esm({
61011
61609
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
61012
61610
  },
61013
61611
  async run({ args }) {
61014
- const { detectSessionDrift, getProjectRoot: getProjectRoot46 } = await import("@cleocode/core");
61015
- const projectRoot = await getProjectRoot46();
61612
+ const { detectSessionDrift, getProjectRoot: getProjectRoot48 } = await import("@cleocode/core");
61613
+ const projectRoot = await getProjectRoot48();
61016
61614
  const scope = args["audit-scope"] === "local" ? "local" : "global";
61017
61615
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
61018
61616
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -63778,7 +64376,7 @@ __export(token_exports, {
63778
64376
  tokenCommand: () => tokenCommand
63779
64377
  });
63780
64378
  import { readFileSync as readFileSync16 } from "node:fs";
63781
- import { getProjectRoot as getProjectRoot43, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
64379
+ import { getProjectRoot as getProjectRoot45, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
63782
64380
  function readPayload(args, textKey, fileKey) {
63783
64381
  const text = args[textKey];
63784
64382
  const file = args[fileKey];
@@ -63942,7 +64540,7 @@ var init_token = __esm({
63942
64540
  domain: args.domain,
63943
64541
  operation: args.operation
63944
64542
  };
63945
- const result = args.record ? await recordTokenExchange2(getProjectRoot43(), input2) : await measureTokenExchange(input2);
64543
+ const result = args.record ? await recordTokenExchange2(getProjectRoot45(), input2) : await measureTokenExchange(input2);
63946
64544
  cliOutput(result, {
63947
64545
  command: "token",
63948
64546
  operation: args.record ? "admin.token.record" : "token.estimate"
@@ -63977,8 +64575,8 @@ __export(transcript_exports, {
63977
64575
  transcriptCommand: () => transcriptCommand
63978
64576
  });
63979
64577
  import { homedir as homedir6 } from "node:os";
63980
- import { join as join31 } from "node:path";
63981
- import { getProjectRoot as getProjectRoot44 } from "@cleocode/core";
64578
+ import { join as join30 } from "node:path";
64579
+ import { getProjectRoot as getProjectRoot46 } from "@cleocode/core";
63982
64580
  import {
63983
64581
  parseDurationMs,
63984
64582
  pruneTranscripts,
@@ -64008,7 +64606,7 @@ var init_transcript = __esm({
64008
64606
  async run({ args }) {
64009
64607
  if (args.pending) {
64010
64608
  try {
64011
- const projectRoot = getProjectRoot44();
64609
+ const projectRoot = getProjectRoot46();
64012
64610
  const { scanPendingTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
64013
64611
  const pending = await scanPendingTranscripts(projectRoot);
64014
64612
  cliOutput(
@@ -64031,7 +64629,7 @@ var init_transcript = __esm({
64031
64629
  }
64032
64630
  return;
64033
64631
  }
64034
- const projectsDir = args["projects-dir"] ?? join31(homedir6(), ".claude", "projects");
64632
+ const projectsDir = args["projects-dir"] ?? join30(homedir6(), ".claude", "projects");
64035
64633
  try {
64036
64634
  const result = await scanTranscripts(projectsDir);
64037
64635
  cliOutput(
@@ -64105,7 +64703,7 @@ var init_transcript = __esm({
64105
64703
  async run({ args }) {
64106
64704
  const tier = args.tier ?? "warm";
64107
64705
  const dryRun = args["dry-run"] ?? false;
64108
- const projectRoot = getProjectRoot44();
64706
+ const projectRoot = getProjectRoot46();
64109
64707
  try {
64110
64708
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
64111
64709
  const { findSessionTranscriptPath, listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -64217,7 +64815,7 @@ var init_transcript = __esm({
64217
64815
  const dryRun = args["dry-run"] ?? false;
64218
64816
  const olderThanHours = args["older-than-hours"] ? Number.parseInt(args["older-than-hours"], 10) : 24;
64219
64817
  const limit = args.limit ? Number.parseInt(args.limit, 10) : void 0;
64220
- const projectRoot = getProjectRoot44();
64818
+ const projectRoot = getProjectRoot46();
64221
64819
  try {
64222
64820
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
64223
64821
  const { listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -64337,7 +64935,7 @@ var init_transcript = __esm({
64337
64935
  process.exit(2);
64338
64936
  return;
64339
64937
  }
64340
- const projectsDir = args["projects-dir"] ?? join31(homedir6(), ".claude", "projects");
64938
+ const projectsDir = args["projects-dir"] ?? join30(homedir6(), ".claude", "projects");
64341
64939
  try {
64342
64940
  const pruneResult = await pruneTranscripts({
64343
64941
  olderThanMs,
@@ -65014,15 +65612,15 @@ __export(web_exports, {
65014
65612
  });
65015
65613
  import { execFileSync as execFileSync3, spawn as spawn3 } from "node:child_process";
65016
65614
  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";
65615
+ import { join as join31 } from "node:path";
65018
65616
  import { CleoError as CleoError11, formatError as formatError7, getCleoHome as getCleoHome5 } from "@cleocode/core";
65019
65617
  function getWebPaths() {
65020
65618
  const cleoHome = getCleoHome5();
65021
65619
  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")
65620
+ pidFile: join31(cleoHome, "web-server.pid"),
65621
+ configFile: join31(cleoHome, "web-server.json"),
65622
+ logDir: join31(cleoHome, "logs"),
65623
+ logFile: join31(cleoHome, "logs", "web-server.log")
65026
65624
  };
65027
65625
  }
65028
65626
  function isProcessRunning(pid) {
@@ -65061,7 +65659,7 @@ async function startWebServer(port, host) {
65061
65659
  throw new CleoError11(1 /* GENERAL_ERROR */, `Server already running (PID: ${status.pid})`);
65062
65660
  }
65063
65661
  const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
65064
- const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join32(projectRoot, "packages", "studio", "build");
65662
+ const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join31(projectRoot, "packages", "studio", "build");
65065
65663
  await mkdir4(logDir, { recursive: true });
65066
65664
  await writeFile3(
65067
65665
  configFile,
@@ -65071,7 +65669,7 @@ async function startWebServer(port, host) {
65071
65669
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
65072
65670
  })
65073
65671
  );
65074
- const webIndexPath = join32(studioDir, "index.js");
65672
+ const webIndexPath = join31(studioDir, "index.js");
65075
65673
  try {
65076
65674
  await stat2(webIndexPath);
65077
65675
  } catch {
@@ -65344,7 +65942,7 @@ __export(worktree_exports, {
65344
65942
  worktreeCommand: () => worktreeCommand
65345
65943
  });
65346
65944
  import readline4 from "node:readline";
65347
- import { getProjectRoot as getProjectRoot45, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
65945
+ import { getProjectRoot as getProjectRoot47, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
65348
65946
  async function promptYesNo2(question) {
65349
65947
  return new Promise((resolve7) => {
65350
65948
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
@@ -65449,7 +66047,7 @@ var init_worktree3 = __esm({
65449
66047
  const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
65450
66048
  const idleDaysRaw = typeof args["idle-days"] === "string" ? args["idle-days"] : void 0;
65451
66049
  const idleDays = idleDaysRaw !== void 0 ? Number.parseInt(idleDaysRaw, 10) : void 0;
65452
- const projectRoot = getProjectRoot45();
66050
+ const projectRoot = getProjectRoot47();
65453
66051
  const listResult = await listWorktrees2({
65454
66052
  projectRoot,
65455
66053
  ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
@@ -65685,7 +66283,7 @@ init_dist();
65685
66283
  init_field_context();
65686
66284
  init_format_context();
65687
66285
  import { readFileSync as readFileSync17 } from "node:fs";
65688
- import { dirname as dirname9, join as join34 } from "node:path";
66286
+ import { dirname as dirname9, join as join33 } from "node:path";
65689
66287
  import { fileURLToPath as fileURLToPath7 } from "node:url";
65690
66288
 
65691
66289
  // packages/cleo/src/cli/generated/command-manifest.ts
@@ -65777,7 +66375,7 @@ var COMMAND_MANIFEST = [
65777
66375
  {
65778
66376
  exportName: "backupRecoverSubCommand",
65779
66377
  name: "recover",
65780
- description: "Recover a malformed CLEO database from snapshot",
66378
+ description: "Recover a malformed CLEO database from snapshot \u2014 accepts any role from DB_INVENTORY (T10318)",
65781
66379
  load: async () => (await Promise.resolve().then(() => (init_backup_recover(), backup_recover_exports))).backupRecoverSubCommand
65782
66380
  },
65783
66381
  {
@@ -65984,6 +66582,18 @@ var COMMAND_MANIFEST = [
65984
66582
  description: "Documentation attachment management (add/list/fetch/remove), ",
65985
66583
  load: async () => (await Promise.resolve().then(() => (init_docs3(), docs_exports))).docsCommand
65986
66584
  },
66585
+ {
66586
+ exportName: "doctorDbSubstrateCommand",
66587
+ name: "db-substrate",
66588
+ description: "Walk every DB in the inventory + report integrity, row counts, orphan dirs. ",
66589
+ load: async () => (await Promise.resolve().then(() => (init_doctor_db_substrate(), doctor_db_substrate_exports))).doctorDbSubstrateCommand
66590
+ },
66591
+ {
66592
+ exportName: "doctorLegacyBackupsCommand",
66593
+ name: "legacy-backups",
66594
+ description: "Enumerate legacy *-pre-cleo.db.bak / brain.db.PRE-DUP-FIX-* / pre-untrack / rotation-overflow ",
66595
+ load: async () => (await Promise.resolve().then(() => (init_doctor_legacy_backups(), doctor_legacy_backups_exports))).doctorLegacyBackupsCommand
66596
+ },
65987
66597
  {
65988
66598
  exportName: "doctorProjectsCommand",
65989
66599
  name: "doctor-projects",
@@ -66682,12 +67292,12 @@ init_did_you_mean();
66682
67292
 
66683
67293
  // packages/cleo/src/cli/lib/first-run-detection.ts
66684
67294
  import { existsSync as existsSync16 } from "node:fs";
66685
- import { join as join33 } from "node:path";
67295
+ import { join as join32 } from "node:path";
66686
67296
  async function detectFirstRun() {
66687
67297
  const envKey = process.env["ANTHROPIC_API_KEY"];
66688
67298
  if (typeof envKey === "string" && envKey.length > 0) return false;
66689
67299
  const { getCleoPlatformPaths } = await import("@cleocode/paths");
66690
- const configPath = join33(getCleoPlatformPaths().config, "config.json");
67300
+ const configPath = join32(getCleoPlatformPaths().config, "config.json");
66691
67301
  if (existsSync16(configPath)) return false;
66692
67302
  try {
66693
67303
  const { getCredentialPool } = await import("@cleocode/core/llm/credential-pool.js");
@@ -66802,7 +67412,7 @@ Or via NodeSource: https://github.com/nodesource/distributions
66802
67412
  }
66803
67413
  }
66804
67414
  function getPackageVersion() {
66805
- const pkgPath = join34(dirname9(fileURLToPath7(import.meta.url)), "../../package.json");
67415
+ const pkgPath = join33(dirname9(fileURLToPath7(import.meta.url)), "../../package.json");
66806
67416
  const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
66807
67417
  return pkg.version;
66808
67418
  }
@@ -66955,7 +67565,7 @@ async function runStartupMaintenance() {
66955
67565
  detectAndRemoveStrayProjectNexus,
66956
67566
  getGlobalSalt,
66957
67567
  getLogger: getLogger21,
66958
- getProjectRoot: getProjectRoot46,
67568
+ getProjectRoot: getProjectRoot48,
66959
67569
  isCleanupMarkerSet,
66960
67570
  migrateSignaldockToConduit,
66961
67571
  needsSignaldockToConduitMigration,
@@ -66964,7 +67574,7 @@ async function runStartupMaintenance() {
66964
67574
  } = await import("@cleocode/core/internal");
66965
67575
  let projectRootForCleanup = "";
66966
67576
  try {
66967
- projectRootForCleanup = getProjectRoot46();
67577
+ projectRootForCleanup = getProjectRoot48();
66968
67578
  } catch {
66969
67579
  }
66970
67580
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -66984,7 +67594,7 @@ async function runStartupMaintenance() {
66984
67594
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
66985
67595
  if (!isInitInvocation) {
66986
67596
  try {
66987
- const _projectRootForMigration = getProjectRoot46();
67597
+ const _projectRootForMigration = getProjectRoot48();
66988
67598
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
66989
67599
  const migrationResult = migrateSignaldockToConduit(_projectRootForMigration);
66990
67600
  if (migrationResult.status === "failed") {