@cleocode/core 2026.6.18 → 2026.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/docs/export-document.js +1173 -334
  2. package/dist/docs/export-document.js.map +3 -3
  3. package/dist/lifecycle/effective-stage.js +3 -3
  4. package/dist/lifecycle/rollup.js +3 -3
  5. package/dist/llm/plugin-facade.js +1218 -383
  6. package/dist/llm/plugin-facade.js.map +3 -3
  7. package/dist/memory/brain-writer-handlers.d.ts.map +1 -1
  8. package/dist/memory/brain-writer-handlers.js +39 -0
  9. package/dist/memory/brain-writer-handlers.js.map +1 -1
  10. package/dist/orchestrate/admission.d.ts +65 -0
  11. package/dist/orchestrate/admission.d.ts.map +1 -0
  12. package/dist/orchestrate/admission.js +54 -0
  13. package/dist/orchestrate/admission.js.map +1 -0
  14. package/dist/orchestrate/lifecycle-ops.d.ts.map +1 -1
  15. package/dist/orchestrate/lifecycle-ops.js +10 -0
  16. package/dist/orchestrate/lifecycle-ops.js.map +1 -1
  17. package/dist/orchestrate/query-ops.d.ts.map +1 -1
  18. package/dist/orchestrate/query-ops.js +37 -8
  19. package/dist/orchestrate/query-ops.js.map +1 -1
  20. package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
  21. package/dist/orchestrate/spawn-ops.js +24 -0
  22. package/dist/orchestrate/spawn-ops.js.map +1 -1
  23. package/dist/release/pr-evidence.d.ts +14 -3
  24. package/dist/release/pr-evidence.d.ts.map +1 -1
  25. package/dist/release/pr-evidence.js +44 -4
  26. package/dist/release/pr-evidence.js.map +1 -1
  27. package/dist/resources/governor.d.ts +133 -0
  28. package/dist/resources/governor.d.ts.map +1 -0
  29. package/dist/resources/governor.js +377 -0
  30. package/dist/resources/governor.js.map +1 -0
  31. package/dist/resources/supervisor-admit.d.ts +42 -0
  32. package/dist/resources/supervisor-admit.d.ts.map +1 -0
  33. package/dist/resources/supervisor-admit.js +136 -0
  34. package/dist/resources/supervisor-admit.js.map +1 -0
  35. package/dist/selfimprove/fix-gen.js +1216 -381
  36. package/dist/selfimprove/fix-gen.js.map +3 -3
  37. package/dist/sentient/tick.d.ts.map +1 -1
  38. package/dist/sentient/tick.js +29 -0
  39. package/dist/sentient/tick.js.map +1 -1
  40. package/dist/store/agent-registry-store.d.ts.map +1 -1
  41. package/dist/store/agent-registry-store.js +17 -2
  42. package/dist/store/agent-registry-store.js.map +1 -1
  43. package/dist/store/dual-scope-db.d.ts.map +1 -1
  44. package/dist/store/dual-scope-db.js +35 -0
  45. package/dist/store/dual-scope-db.js.map +1 -1
  46. package/dist/store/sqlite.d.ts.map +1 -1
  47. package/dist/store/sqlite.js +15 -0
  48. package/dist/store/sqlite.js.map +1 -1
  49. package/dist/store/tasks-schema.d.ts +2 -0
  50. package/dist/store/tasks-schema.d.ts.map +1 -1
  51. package/dist/store/tasks-schema.js +17 -0
  52. package/dist/store/tasks-schema.js.map +1 -1
  53. package/dist/store/validation-schemas.d.ts +98 -98
  54. package/dist/tasks/compute-task-view.js +2 -2
  55. package/dist/tasks/evidence.d.ts +19 -0
  56. package/dist/tasks/evidence.d.ts.map +1 -1
  57. package/dist/tasks/evidence.js +32 -2
  58. package/dist/tasks/evidence.js.map +1 -1
  59. package/dist/tasks/tool-semaphore.d.ts +25 -0
  60. package/dist/tasks/tool-semaphore.d.ts.map +1 -1
  61. package/dist/tasks/tool-semaphore.js +68 -1
  62. package/dist/tasks/tool-semaphore.js.map +1 -1
  63. package/dist/tasks/update.d.ts +2 -0
  64. package/dist/tasks/update.d.ts.map +1 -1
  65. package/dist/tasks/update.js +1 -0
  66. package/dist/tasks/update.js.map +1 -1
  67. package/dist/validation/engine-ops.d.ts.map +1 -1
  68. package/dist/validation/engine-ops.js +33 -7
  69. package/dist/validation/engine-ops.js.map +1 -1
  70. package/package.json +12 -12
@@ -1914,6 +1914,7 @@ var init_tasks = __esm({
1914
1914
  severity: { type: "string", enum: ["P0", "P1", "P2", "P3"] },
1915
1915
  reason: { type: "string" },
1916
1916
  dependsWaiver: { type: "string" },
1917
+ blockedBy: { type: "string" },
1917
1918
  clearBlockedBy: { type: "boolean" },
1918
1919
  relates: {
1919
1920
  type: "array",
@@ -4613,6 +4614,12 @@ var init_operations_registry = __esm({
4613
4614
  required: false,
4614
4615
  description: "Justification to waive the critical-priority --depends requirement"
4615
4616
  },
4617
+ {
4618
+ name: "blockedBy",
4619
+ type: "string",
4620
+ required: false,
4621
+ description: "Set the free-text blockedBy reason (gh#1106)"
4622
+ },
4616
4623
  {
4617
4624
  name: "clearBlockedBy",
4618
4625
  type: "boolean",
@@ -12436,7 +12443,7 @@ var init_lafs = __esm({
12436
12443
 
12437
12444
  // packages/contracts/src/lease-ipc/messages.ts
12438
12445
  import { z as z11 } from "zod";
12439
- var LeaseScopeSchema, LeaseLaneSchema, LeaseAcquireRequestSchema, LeaseReleaseRequestSchema, LeaseRenewRequestSchema, RateCheckRequestSchema, ToolGrantRequestSchema, QueuePriorityClassSchema, QueueAdmitRequestSchema, WorkerHeartbeatRequestSchema, LeaseIpcRequestSchema, LeaseGrantedResponseSchema, LeaseQueuedResponseSchema, LeaseDeniedResponseSchema, RateResultResponseSchema, ToolGrantedResponseSchema, LeaseRevokedResponseSchema, ChildKilledUnresponsiveResponseSchema, QueueAdmitDispositionSchema, QueueAdmitResultResponseSchema, HeartbeatAckResponseSchema, LeaseErrorResponseSchema, LeaseIpcResponseSchema, LeaseIpcRequestEnvelopeSchema, LeaseIpcResponseEnvelopeSchema, LeaseIpcEnvelopeSchema, LEASE_IPC_REQUEST_KINDS, LEASE_IPC_RESPONSE_KINDS, LEASE_IPC_MESSAGE_KINDS;
12446
+ var LeaseScopeSchema, LeaseLaneSchema, LeaseAcquireRequestSchema, LeaseReleaseRequestSchema, LeaseRenewRequestSchema, RateCheckRequestSchema, ToolGrantRequestSchema, QueuePriorityClassSchema, QueueAdmitRequestSchema, WorkerHeartbeatRequestSchema, ResourceAdmitRequestSchema, ResourceReleaseRequestSchema, LeaseIpcRequestSchema, LeaseGrantedResponseSchema, LeaseQueuedResponseSchema, LeaseDeniedResponseSchema, RateResultResponseSchema, ToolGrantedResponseSchema, LeaseRevokedResponseSchema, ChildKilledUnresponsiveResponseSchema, QueueAdmitDispositionSchema, QueueAdmitResultResponseSchema, HeartbeatAckResponseSchema, ResourceAdmitDispositionSchema, ResourceAdmitResultResponseSchema, ResourceReleaseResultResponseSchema, LeaseErrorResponseSchema, LeaseIpcResponseSchema, LeaseIpcRequestEnvelopeSchema, LeaseIpcResponseEnvelopeSchema, LeaseIpcEnvelopeSchema, LEASE_IPC_REQUEST_KINDS, LEASE_IPC_RESPONSE_KINDS, LEASE_IPC_MESSAGE_KINDS;
12440
12447
  var init_messages2 = __esm({
12441
12448
  "packages/contracts/src/lease-ipc/messages.ts"() {
12442
12449
  "use strict";
@@ -12521,6 +12528,24 @@ var init_messages2 = __esm({
12521
12528
  /** The worker's own view of whether it is currently inside an LLM call. */
12522
12529
  in_flight_llm: z11.boolean()
12523
12530
  }).strict();
12531
+ ResourceAdmitRequestSchema = z11.object({
12532
+ /** Tag discriminating this request variant. */
12533
+ kind: z11.literal("resource_admit"),
12534
+ /** The resource class (e.g. `"db-heavy"`, `"full-build"`, `"test-run"`). */
12535
+ class: z11.string().min(1),
12536
+ /** The caller holding the slot — process/worktree-unique; the release key. */
12537
+ holder_id: z11.string().min(1),
12538
+ /** The client-computed budget: the max concurrent holders for this class. */
12539
+ budget: z11.number().int().nonnegative()
12540
+ }).strict();
12541
+ ResourceReleaseRequestSchema = z11.object({
12542
+ /** Tag discriminating this request variant. */
12543
+ kind: z11.literal("resource_release"),
12544
+ /** The resource class the slot belongs to. */
12545
+ class: z11.string().min(1),
12546
+ /** The holder that was admitted (matches the admit `holder_id`). */
12547
+ holder_id: z11.string().min(1)
12548
+ }).strict();
12524
12549
  LeaseIpcRequestSchema = z11.discriminatedUnion("kind", [
12525
12550
  LeaseAcquireRequestSchema,
12526
12551
  LeaseReleaseRequestSchema,
@@ -12528,7 +12553,9 @@ var init_messages2 = __esm({
12528
12553
  RateCheckRequestSchema,
12529
12554
  ToolGrantRequestSchema,
12530
12555
  QueueAdmitRequestSchema,
12531
- WorkerHeartbeatRequestSchema
12556
+ WorkerHeartbeatRequestSchema,
12557
+ ResourceAdmitRequestSchema,
12558
+ ResourceReleaseRequestSchema
12532
12559
  ]);
12533
12560
  LeaseGrantedResponseSchema = z11.object({
12534
12561
  /** Tag discriminating this response variant. */
@@ -12629,6 +12656,25 @@ var init_messages2 = __esm({
12629
12656
  /** Tag discriminating this response variant. */
12630
12657
  kind: z11.literal("heartbeat_ack")
12631
12658
  }).strict();
12659
+ ResourceAdmitDispositionSchema = z11.enum(["admitted", "deferred"]);
12660
+ ResourceAdmitResultResponseSchema = z11.object({
12661
+ /** Tag discriminating this response variant. */
12662
+ kind: z11.literal("resource_admit_result"),
12663
+ /** Whether the heavy op was admitted or deferred. */
12664
+ disposition: ResourceAdmitDispositionSchema,
12665
+ /** Back-off in ms before re-requesting (0 when admitted). */
12666
+ retry_after_ms: z11.number().int().nonnegative(),
12667
+ /** Remaining slots for the class after this decision. */
12668
+ slots_remaining: z11.number().int().nonnegative()
12669
+ }).strict();
12670
+ ResourceReleaseResultResponseSchema = z11.object({
12671
+ /** Tag discriminating this response variant. */
12672
+ kind: z11.literal("resource_release_result"),
12673
+ /** Whether a held slot was actually released (false = no such holder). */
12674
+ released: z11.boolean(),
12675
+ /** Remaining in-flight holders for the class after the release. */
12676
+ slots_remaining: z11.number().int().nonnegative()
12677
+ }).strict();
12632
12678
  LeaseErrorResponseSchema = z11.object({
12633
12679
  /** Tag discriminating this response variant. */
12634
12680
  kind: z11.literal("error"),
@@ -12647,6 +12693,8 @@ var init_messages2 = __esm({
12647
12693
  ChildKilledUnresponsiveResponseSchema,
12648
12694
  QueueAdmitResultResponseSchema,
12649
12695
  HeartbeatAckResponseSchema,
12696
+ ResourceAdmitResultResponseSchema,
12697
+ ResourceReleaseResultResponseSchema,
12650
12698
  LeaseErrorResponseSchema
12651
12699
  ]);
12652
12700
  LeaseIpcRequestEnvelopeSchema = z11.object({
@@ -12680,7 +12728,9 @@ var init_messages2 = __esm({
12680
12728
  "rate_check",
12681
12729
  "tool_grant",
12682
12730
  "queue_admit",
12683
- "worker_heartbeat"
12731
+ "worker_heartbeat",
12732
+ "resource_admit",
12733
+ "resource_release"
12684
12734
  ];
12685
12735
  LEASE_IPC_RESPONSE_KINDS = [
12686
12736
  "lease_granted",
@@ -12692,6 +12742,8 @@ var init_messages2 = __esm({
12692
12742
  "child_killed_unresponsive",
12693
12743
  "queue_admit_result",
12694
12744
  "heartbeat_ack",
12745
+ "resource_admit_result",
12746
+ "resource_release_result",
12695
12747
  "error"
12696
12748
  ];
12697
12749
  LEASE_IPC_MESSAGE_KINDS = [
@@ -12702,9 +12754,11 @@ var init_messages2 = __esm({
12702
12754
  });
12703
12755
 
12704
12756
  // packages/contracts/src/lease-ipc/version.ts
12757
+ var LEASE_IPC_PROTOCOL_VERSION;
12705
12758
  var init_version2 = __esm({
12706
12759
  "packages/contracts/src/lease-ipc/version.ts"() {
12707
12760
  "use strict";
12761
+ LEASE_IPC_PROTOCOL_VERSION = "1.2.0";
12708
12762
  }
12709
12763
  });
12710
12764
 
@@ -13964,6 +14018,25 @@ var init_render = __esm({
13964
14018
  }
13965
14019
  });
13966
14020
 
14021
+ // packages/contracts/src/resource-governor.ts
14022
+ var RESOURCE_CLASSES, DEFAULT_RESOURCE_RETRY_AFTER_MS;
14023
+ var init_resource_governor = __esm({
14024
+ "packages/contracts/src/resource-governor.ts"() {
14025
+ "use strict";
14026
+ RESOURCE_CLASSES = Object.freeze([
14027
+ "interactive-cli",
14028
+ "agent-session",
14029
+ "llm-call",
14030
+ "test-run",
14031
+ "scoped-build",
14032
+ "full-build",
14033
+ "db-heavy",
14034
+ "background-autonomous"
14035
+ ]);
14036
+ DEFAULT_RESOURCE_RETRY_AFTER_MS = 2e3;
14037
+ }
14038
+ });
14039
+
13967
14040
  // packages/contracts/src/session.ts
13968
14041
  var init_session2 = __esm({
13969
14042
  "packages/contracts/src/session.ts"() {
@@ -15714,6 +15787,7 @@ var init_src = __esm({
15714
15787
  init_evidence_atoms();
15715
15788
  init_plan();
15716
15789
  init_render();
15790
+ init_resource_governor();
15717
15791
  init_session2();
15718
15792
  init_session_journal();
15719
15793
  init_status_registry();
@@ -17649,7 +17723,7 @@ var init_sql = __esm({
17649
17723
  return new SQL([new StringChunk(str)]);
17650
17724
  }
17651
17725
  _sql.raw = raw;
17652
- function join29(chunks, separator) {
17726
+ function join31(chunks, separator) {
17653
17727
  const result = [];
17654
17728
  for (const [i, chunk] of chunks.entries()) {
17655
17729
  if (i > 0 && separator !== void 0) result.push(separator);
@@ -17657,7 +17731,7 @@ var init_sql = __esm({
17657
17731
  }
17658
17732
  return new SQL(result);
17659
17733
  }
17660
- _sql.join = join29;
17734
+ _sql.join = join31;
17661
17735
  function identifier(value) {
17662
17736
  return new Name(value);
17663
17737
  }
@@ -20044,7 +20118,7 @@ var init_select2 = __esm({
20044
20118
  const baseTableName = this.tableName;
20045
20119
  const tableName = getTableLikeName(table);
20046
20120
  for (const item of extractUsedTable(table)) this.usedTables.add(item);
20047
- if (typeof tableName === "string" && this.config.joins?.some((join29) => join29.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
20121
+ if (typeof tableName === "string" && this.config.joins?.some((join31) => join31.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
20048
20122
  if (!this.isPartialSelect) {
20049
20123
  if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
20050
20124
  if (typeof tableName === "string" && !is(table, SQL)) {
@@ -23854,7 +23928,7 @@ var init_dialect = __esm({
23854
23928
  if (!joins2) return;
23855
23929
  const withEntries = Object.entries(joins2).filter(([_, v]) => v);
23856
23930
  if (!withEntries.length) return;
23857
- return sql.join(withEntries.map(([k, join29]) => {
23931
+ return sql.join(withEntries.map(([k, join31]) => {
23858
23932
  const relation = tableConfig.relations[k];
23859
23933
  const isSingle2 = is(relation, One);
23860
23934
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
@@ -23865,7 +23939,7 @@ var init_dialect = __esm({
23865
23939
  table: targetTable,
23866
23940
  mode: isSingle2 ? "first" : "many",
23867
23941
  schema,
23868
- queryConfig: join29,
23942
+ queryConfig: join31,
23869
23943
  tableConfig: schema[relation.targetTableName],
23870
23944
  relationWhere: filter2,
23871
23945
  isNested: true,
@@ -23879,7 +23953,7 @@ var init_dialect = __esm({
23879
23953
  key: k,
23880
23954
  selection: innerQuery.selection,
23881
23955
  isArray: !isSingle2,
23882
- isOptional: (relation.optional ?? false) || join29 !== true && !!join29.where
23956
+ isOptional: (relation.optional ?? false) || join31 !== true && !!join31.where
23883
23957
  });
23884
23958
  const jsonColumns = sql.join(innerQuery.selection.map((s) => {
23885
23959
  return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`${jsonb3}(${sql.identifier(s.key)})` : sql.identifier(s.key)}`;
@@ -24700,7 +24774,7 @@ var init_update = __esm({
24700
24774
  createJoin(joinType) {
24701
24775
  return ((table, on) => {
24702
24776
  const tableName = getTableLikeName(table);
24703
- if (typeof tableName === "string" && this.config.joins.some((join29) => join29.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
24777
+ if (typeof tableName === "string" && this.config.joins.some((join31) => join31.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
24704
24778
  if (typeof on === "function") {
24705
24779
  const from = this.config.from ? is(table, SQLiteTable) ? table[Table.Symbol.Columns] : is(table, Subquery) ? table._.selectedFields : is(table, SQLiteViewBase) ? table[ViewBaseConfig].selectedFields : void 0 : void 0;
24706
24780
  on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
@@ -25798,8 +25872,8 @@ function probeAndMarkApplied(nativeDb, migration, logSubsystem, eliminatedTables
25798
25872
  });
25799
25873
  if (allAltersPresent && allTablesPresent && allIndexesPresent && allTriggersPresent) {
25800
25874
  insertJournalEntry(nativeDb, migration.hash, migration.folderMillis, migration.name ?? "");
25801
- const log8 = getLogger(logSubsystem);
25802
- log8.debug(
25875
+ const log9 = getLogger(logSubsystem);
25876
+ log9.debug(
25803
25877
  {
25804
25878
  migration: migration.name,
25805
25879
  alters: alterTargets.length,
@@ -25868,14 +25942,14 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
25868
25942
  if (hasOrphanedEntries) {
25869
25943
  const dbHashes = new Set(dbEntries.map((e) => e.hash));
25870
25944
  const allLocalHashesPresentInDb = localMigrations.every((m) => dbHashes.has(m.hash));
25871
- const log8 = getLogger(logSubsystem);
25945
+ const log9 = getLogger(logSubsystem);
25872
25946
  if (allLocalHashesPresentInDb) {
25873
- log8.debug(
25947
+ log9.debug(
25874
25948
  { extra: orphanedEntries.length },
25875
25949
  `Migration journal has ${orphanedEntries.length} entries for migrations not known to this install (DB is ahead). Skipping reconciliation.`
25876
25950
  );
25877
25951
  } else {
25878
- log8.warn(
25952
+ log9.warn(
25879
25953
  { orphaned: orphanedEntries.length },
25880
25954
  `Detected ${orphanedEntries.length} true-orphan journal entries from a previous CLEO lineage. Reconciling via DDL probe.`
25881
25955
  );
@@ -25911,8 +25985,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
25911
25985
  if (alterMatches.length === 0) {
25912
25986
  const stripped = stripSqlComments(fullSql).trim();
25913
25987
  if (stripped === "") {
25914
- const log8 = getLogger(logSubsystem);
25915
- log8.debug(
25988
+ const log9 = getLogger(logSubsystem);
25989
+ log9.debug(
25916
25990
  { migration: migration.name },
25917
25991
  `Migration ${migration.name} is a comment-only baseline marker \u2014 marking applied on existing DB.`
25918
25992
  );
@@ -25951,8 +26025,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
25951
26025
  }
25952
26026
  }
25953
26027
  if (missingColumns.length === 0) {
25954
- const log8 = getLogger(logSubsystem);
25955
- log8.warn(
26028
+ const log9 = getLogger(logSubsystem);
26029
+ log9.warn(
25956
26030
  { migration: migration.name, columns: alterMatches },
25957
26031
  `Detected partially-applied migration ${migration.name} \u2014 columns exist but journal entry missing. Auto-reconciling.`
25958
26032
  );
@@ -25960,8 +26034,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
25960
26034
  continue;
25961
26035
  }
25962
26036
  if (existingColumns.length > 0 && missingColumns.length > 0) {
25963
- const log8 = getLogger(logSubsystem);
25964
- log8.warn(
26037
+ const log9 = getLogger(logSubsystem);
26038
+ log9.warn(
25965
26039
  {
25966
26040
  migration: migration.name,
25967
26041
  existingColumns: existingColumns.map((c) => `${c.table}.${c.column}`),
@@ -25973,12 +26047,12 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
25973
26047
  if (!tableExists(nativeDb, table)) continue;
25974
26048
  try {
25975
26049
  nativeDb.exec(`ALTER TABLE ${table} ADD COLUMN ${column}${ddl ? ` ${ddl}` : ""}`);
25976
- log8.warn(
26050
+ log9.warn(
25977
26051
  { migration: migration.name, table, column },
25978
26052
  `T920: Added missing column ${table}.${column} to complete partial migration.`
25979
26053
  );
25980
26054
  } catch {
25981
- log8.warn(
26055
+ log9.warn(
25982
26056
  { migration: migration.name, table, column },
25983
26057
  `T920: Could not add missing column ${table}.${column} \u2014 will let Drizzle migrate() handle it.`
25984
26058
  );
@@ -25998,8 +26072,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
25998
26072
  for (const entry of unnamedEntries) {
25999
26073
  const migrationName = hashToName.get(entry.hash);
26000
26074
  if (!migrationName) continue;
26001
- const log8 = getLogger(logSubsystem);
26002
- log8.debug(
26075
+ const log9 = getLogger(logSubsystem);
26076
+ log9.debug(
26003
26077
  { id: entry.id, hash: entry.hash, name: migrationName },
26004
26078
  `Backfilling missing name on journal entry id=${entry.id} (Drizzle v1 beta legacy compat).`
26005
26079
  );
@@ -26083,13 +26157,13 @@ function ensureColumns(nativeDb, tableName, requiredColumns, logSubsystem, conte
26083
26157
  const existingCols = new Set(columns.map((c) => c.name));
26084
26158
  for (const req of requiredColumns) {
26085
26159
  if (!existingCols.has(req.name)) {
26086
- const log8 = getLogger(logSubsystem);
26160
+ const log9 = getLogger(logSubsystem);
26087
26161
  const message = `Adding missing column ${tableName}.${req.name} via ALTER TABLE`;
26088
26162
  const fields = { column: req.name, context };
26089
26163
  if (context === "fresh") {
26090
- log8.error(fields, `${message} \u2014 MIGRATION DEFECT (fresh DB should not need repair)`);
26164
+ log9.error(fields, `${message} \u2014 MIGRATION DEFECT (fresh DB should not need repair)`);
26091
26165
  } else {
26092
- log8.warn(fields, message);
26166
+ log9.warn(fields, message);
26093
26167
  }
26094
26168
  nativeDb.exec(`ALTER TABLE ${tableName} ADD COLUMN ${req.name} ${req.ddl}`);
26095
26169
  }
@@ -35170,11 +35244,750 @@ var init_cleo_global = __esm({
35170
35244
  }
35171
35245
  });
35172
35246
 
35173
- // packages/core/src/store/lock.ts
35247
+ // packages/core/src/resources/linux-backend.ts
35248
+ import { readFile as readFile2, stat } from "node:fs/promises";
35249
+ function parsePressureLine(line2) {
35250
+ const avg10Match = /avg10=([\d.]+)/.exec(line2);
35251
+ const avg60Match = /avg60=([\d.]+)/.exec(line2);
35252
+ const avg300Match = /avg300=([\d.]+)/.exec(line2);
35253
+ const totalMatch = /total=(\d+)/.exec(line2);
35254
+ if (!avg10Match?.[1] || !avg60Match?.[1] || !avg300Match?.[1] || !totalMatch?.[1]) {
35255
+ return null;
35256
+ }
35257
+ return {
35258
+ avg10: parseFloat(avg10Match[1]),
35259
+ avg60: parseFloat(avg60Match[1]),
35260
+ avg300: parseFloat(avg300Match[1]),
35261
+ totalUs: parseInt(totalMatch[1], 10)
35262
+ };
35263
+ }
35264
+ function parsePsiFile(content) {
35265
+ const lines = content.split("\n").map((l) => l.trim()).filter(Boolean);
35266
+ let some = null;
35267
+ let full = null;
35268
+ for (const line2 of lines) {
35269
+ if (line2.startsWith("some ")) {
35270
+ some = parsePressureLine(line2);
35271
+ } else if (line2.startsWith("full ")) {
35272
+ full = parsePressureLine(line2);
35273
+ }
35274
+ }
35275
+ if (!some) {
35276
+ return null;
35277
+ }
35278
+ return { some, full };
35279
+ }
35280
+ function parseMemAvailable(content) {
35281
+ for (const line2 of content.split("\n")) {
35282
+ if (line2.startsWith("MemAvailable:")) {
35283
+ const match = /MemAvailable:\s+(\d+)\s+kB/.exec(line2);
35284
+ if (match?.[1]) {
35285
+ return parseInt(match[1], 10) * 1024;
35286
+ }
35287
+ }
35288
+ }
35289
+ return null;
35290
+ }
35291
+ function parseSmapsRollup(content) {
35292
+ let rssKb = null;
35293
+ let pssKb = null;
35294
+ for (const line2 of content.split("\n")) {
35295
+ if (line2.startsWith("Rss:")) {
35296
+ const m = /Rss:\s+(\d+)\s+kB/.exec(line2);
35297
+ if (m?.[1]) rssKb = parseInt(m[1], 10);
35298
+ } else if (line2.startsWith("Pss:")) {
35299
+ const m = /Pss:\s+(\d+)\s+kB/.exec(line2);
35300
+ if (m?.[1]) pssKb = parseInt(m[1], 10);
35301
+ }
35302
+ }
35303
+ if (rssKb === null || pssKb === null) return null;
35304
+ return { rssBytes: rssKb * 1024, pssBytes: pssKb * 1024 };
35305
+ }
35306
+ var defaultReadFile, defaultStat, LinuxResourceBackend;
35307
+ var init_linux_backend = __esm({
35308
+ "packages/core/src/resources/linux-backend.ts"() {
35309
+ "use strict";
35310
+ defaultReadFile = (path, encoding) => readFile2(path, encoding);
35311
+ defaultStat = async (path) => {
35312
+ try {
35313
+ const s = await stat(path);
35314
+ return { size: s.size };
35315
+ } catch {
35316
+ return null;
35317
+ }
35318
+ };
35319
+ LinuxResourceBackend = class {
35320
+ globalPressurePath;
35321
+ cgroupSlicePressurePath;
35322
+ walPaths;
35323
+ readFileFn;
35324
+ statFileFn;
35325
+ constructor(opts = {}) {
35326
+ this.globalPressurePath = opts.globalPressurePath ?? "/proc/pressure/memory";
35327
+ this.cgroupSlicePressurePath = opts.cgroupSlicePressurePath ?? null;
35328
+ this.walPaths = opts.walPaths ?? [];
35329
+ this.readFileFn = opts.readFileFn ?? defaultReadFile;
35330
+ this.statFileFn = opts.statFileFn ?? defaultStat;
35331
+ }
35332
+ /**
35333
+ * Take a bounded point-in-time resource sample.
35334
+ *
35335
+ * Read-count (bounded by Amendment 1):
35336
+ * - 1 read: `/proc/pressure/memory`
35337
+ * - 0–1 reads: slice `memory.pressure` (if configured)
35338
+ * - 1 read: `/proc/meminfo`
35339
+ * - N stat calls: one per WAL path in `walPaths`
35340
+ *
35341
+ * Never spawns a child process.
35342
+ */
35343
+ async sample() {
35344
+ const sampledAtMs = Date.now();
35345
+ const globalPressure = await this._readPsi(this.globalPressurePath);
35346
+ const pressureAvailable = globalPressure !== null;
35347
+ let slicePressure = null;
35348
+ if (this.cgroupSlicePressurePath) {
35349
+ slicePressure = await this._readPsi(this.cgroupSlicePressurePath);
35350
+ }
35351
+ const memAvailableBytes = await this._readMemAvailable();
35352
+ const walObservations = await this._readWalObservations();
35353
+ return {
35354
+ sampledAtMs,
35355
+ pressureAvailable,
35356
+ memAvailableBytes,
35357
+ globalPressure,
35358
+ slicePressure,
35359
+ walObservations
35360
+ };
35361
+ }
35362
+ /**
35363
+ * Sweep per-child RSS via `/proc/<pid>/smaps_rollup`.
35364
+ *
35365
+ * **STRUCTURALLY SEPARATED from sample()** — smaps_rollup reads are
35366
+ * ms-scale per multi-GB process and must never appear in the hot path.
35367
+ * Call on a separate low-frequency cadence (e.g. every 60s or on
35368
+ * backoff→hold state transition).
35369
+ *
35370
+ * @param pids - PIDs to sweep. Dead/unknown PIDs are silently skipped.
35371
+ */
35372
+ async sweepChildRss(pids) {
35373
+ const sampledAtMs = Date.now();
35374
+ const entries = [];
35375
+ for (const pid of pids) {
35376
+ try {
35377
+ const content = await this.readFileFn(`/proc/${pid}/smaps_rollup`, "utf-8");
35378
+ const parsed = parseSmapsRollup(content);
35379
+ if (parsed) {
35380
+ entries.push({ pid, ...parsed });
35381
+ }
35382
+ } catch {
35383
+ }
35384
+ }
35385
+ return { sampledAtMs, entries };
35386
+ }
35387
+ // -------------------------------------------------------------------------
35388
+ // Private helpers
35389
+ // -------------------------------------------------------------------------
35390
+ async _readPsi(path) {
35391
+ try {
35392
+ const content = await this.readFileFn(path, "utf-8");
35393
+ return parsePsiFile(content);
35394
+ } catch {
35395
+ return null;
35396
+ }
35397
+ }
35398
+ async _readMemAvailable() {
35399
+ try {
35400
+ const content = await this.readFileFn("/proc/meminfo", "utf-8");
35401
+ return parseMemAvailable(content);
35402
+ } catch {
35403
+ return null;
35404
+ }
35405
+ }
35406
+ async _readWalObservations() {
35407
+ const results = [];
35408
+ for (const walPath of this.walPaths) {
35409
+ const info = await this.statFileFn(walPath);
35410
+ results.push({ walPath, sizeBytes: info?.size ?? null });
35411
+ }
35412
+ return results;
35413
+ }
35414
+ };
35415
+ }
35416
+ });
35417
+
35418
+ // packages/core/src/resources/monitor.ts
35419
+ import { EventEmitter as EventEmitter2 } from "node:events";
35420
+ function resolveThresholds(cfg) {
35421
+ return {
35422
+ holdSomeAvg10: cfg.psi?.holdSomeAvg10 ?? DEFAULTS.holdSomeAvg10,
35423
+ backoffSomeAvg10: cfg.psi?.backoffSomeAvg10 ?? DEFAULTS.backoffSomeAvg10,
35424
+ holdFullAvg10: cfg.psi?.holdFullAvg10 ?? DEFAULTS.holdFullAvg10,
35425
+ backoffFullAvg10: cfg.psi?.backoffFullAvg10 ?? DEFAULTS.backoffFullAvg10,
35426
+ hysteresisPoints: cfg.hysteresisPoints ?? DEFAULTS.hysteresisPoints,
35427
+ headroomBytes: cfg.headroomBytes ?? DEFAULTS.headroomBytes,
35428
+ walWarnThresholdBytes: cfg.walWarnThresholdBytes ?? DEFAULTS.walWarnThresholdBytes,
35429
+ pollIntervalMs: cfg.pollIntervalMs ?? DEFAULTS.pollIntervalMs
35430
+ };
35431
+ }
35432
+ function evaluateState(sample, thresholds, currentState) {
35433
+ if (!sample.pressureAvailable) {
35434
+ if (sample.memAvailableBytes !== null && sample.memAvailableBytes < thresholds.headroomBytes) {
35435
+ return { state: "hold", reason: "degraded: memAvailable below headroom" };
35436
+ }
35437
+ return { state: "ok", reason: "degraded: PSI unavailable, memAvailable sufficient" };
35438
+ }
35439
+ const somePressure = sample.globalPressure?.some ?? sample.slicePressure?.some;
35440
+ const fullPressure = sample.globalPressure?.full ?? sample.slicePressure?.full;
35441
+ const someAvg102 = somePressure?.avg10 ?? 0;
35442
+ const fullAvg10 = fullPressure?.avg10 ?? 0;
35443
+ if (someAvg102 > thresholds.backoffSomeAvg10 || fullAvg10 > thresholds.backoffFullAvg10) {
35444
+ return {
35445
+ state: "backoff",
35446
+ reason: `some avg10=${someAvg102.toFixed(2)} full avg10=${fullAvg10.toFixed(2)} \u2014 above backoff threshold`
35447
+ };
35448
+ }
35449
+ if (someAvg102 > thresholds.holdSomeAvg10 || fullAvg10 > thresholds.holdFullAvg10) {
35450
+ return {
35451
+ state: "hold",
35452
+ reason: `some avg10=${someAvg102.toFixed(2)} full avg10=${fullAvg10.toFixed(2)} \u2014 above hold threshold`
35453
+ };
35454
+ }
35455
+ if (currentState !== "ok") {
35456
+ const hysteresisFloor = thresholds.holdSomeAvg10 - thresholds.hysteresisPoints;
35457
+ const fullHysteresisFloor = thresholds.holdFullAvg10 - thresholds.hysteresisPoints;
35458
+ if (someAvg102 > hysteresisFloor || fullAvg10 > fullHysteresisFloor) {
35459
+ const clamped = currentState === "backoff" ? "hold" : currentState;
35460
+ return {
35461
+ state: clamped,
35462
+ reason: `some avg10=${someAvg102.toFixed(2)} full avg10=${fullAvg10.toFixed(2)} \u2014 hysteresis hold (floor: some ${hysteresisFloor}, full ${fullHysteresisFloor})`
35463
+ };
35464
+ }
35465
+ }
35466
+ return {
35467
+ state: "ok",
35468
+ reason: `some avg10=${someAvg102.toFixed(2)} full avg10=${fullAvg10.toFixed(2)} \u2014 below thresholds`
35469
+ };
35470
+ }
35471
+ var DEFAULTS, ResourceMonitor;
35472
+ var init_monitor = __esm({
35473
+ "packages/core/src/resources/monitor.ts"() {
35474
+ "use strict";
35475
+ init_linux_backend();
35476
+ DEFAULTS = {
35477
+ holdSomeAvg10: 10,
35478
+ backoffSomeAvg10: 20,
35479
+ holdFullAvg10: 5,
35480
+ backoffFullAvg10: 10,
35481
+ hysteresisPoints: 3,
35482
+ headroomBytes: 256 * 1024 * 1024,
35483
+ walWarnThresholdBytes: 256 * 1024 * 1024,
35484
+ pollIntervalMs: 1500
35485
+ };
35486
+ ResourceMonitor = class extends EventEmitter2 {
35487
+ thresholds;
35488
+ backend;
35489
+ _state = "ok";
35490
+ _timer = null;
35491
+ _running = false;
35492
+ constructor(cfg = {}) {
35493
+ super();
35494
+ this.thresholds = resolveThresholds(cfg);
35495
+ this.backend = cfg.backend ?? new LinuxResourceBackend();
35496
+ }
35497
+ // -------------------------------------------------------------------------
35498
+ // Public API
35499
+ // -------------------------------------------------------------------------
35500
+ /**
35501
+ * Current pressure state (only meaningful after at least one sample).
35502
+ */
35503
+ get state() {
35504
+ return this._state;
35505
+ }
35506
+ /**
35507
+ * `true` while the continuous loop is running.
35508
+ */
35509
+ get running() {
35510
+ return this._running;
35511
+ }
35512
+ /**
35513
+ * Take a single point-in-time resource sample.
35514
+ *
35515
+ * Safe to call with the daemon off (no child processes, bounded reads).
35516
+ * Does NOT update `this.state` — use {@link startContinuous} for that.
35517
+ */
35518
+ async sample() {
35519
+ return this.backend.sample();
35520
+ }
35521
+ /**
35522
+ * Start the continuous polling loop.
35523
+ *
35524
+ * Returns a `stop()` function. Calling `stop()` is idempotent.
35525
+ *
35526
+ * Emits:
35527
+ * - `'sample'` on every poll (even if state did not change)
35528
+ * - `'transition'` when `PressureState` changes
35529
+ * - `'error'` if the backend throws (loop continues regardless)
35530
+ */
35531
+ startContinuous() {
35532
+ if (this._running) {
35533
+ return () => this._stopLoop();
35534
+ }
35535
+ this._running = true;
35536
+ this._scheduleNext();
35537
+ return () => this._stopLoop();
35538
+ }
35539
+ /**
35540
+ * Stop the continuous polling loop. Idempotent.
35541
+ */
35542
+ stop() {
35543
+ this._stopLoop();
35544
+ }
35545
+ // -------------------------------------------------------------------------
35546
+ // Private loop machinery
35547
+ // -------------------------------------------------------------------------
35548
+ _scheduleNext() {
35549
+ this._timer = setTimeout(() => {
35550
+ void this._tick();
35551
+ }, this.thresholds.pollIntervalMs);
35552
+ if (typeof this._timer.unref === "function") {
35553
+ this._timer.unref();
35554
+ }
35555
+ }
35556
+ async _tick() {
35557
+ if (!this._running) return;
35558
+ try {
35559
+ const sample = await this.backend.sample();
35560
+ this.emit("sample", sample);
35561
+ const { state: newState, reason } = evaluateState(sample, this.thresholds, this._state);
35562
+ if (newState !== this._state) {
35563
+ const transition = {
35564
+ from: this._state,
35565
+ to: newState,
35566
+ sample,
35567
+ reason
35568
+ };
35569
+ this._state = newState;
35570
+ this.emit("transition", transition);
35571
+ }
35572
+ } catch (err) {
35573
+ this.emit("error", err instanceof Error ? err : new Error(String(err)));
35574
+ }
35575
+ if (this._running) {
35576
+ this._scheduleNext();
35577
+ }
35578
+ }
35579
+ _stopLoop() {
35580
+ this._running = false;
35581
+ if (this._timer !== null) {
35582
+ clearTimeout(this._timer);
35583
+ this._timer = null;
35584
+ }
35585
+ }
35586
+ };
35587
+ }
35588
+ });
35589
+
35590
+ // packages/core/src/resources/supervisor-admit.ts
35591
+ import { connect } from "node:net";
35592
+ import { join as join5 } from "node:path";
35593
+ import { getCleoHome as getCleoHome2 } from "@cleocode/paths";
35594
+ function resolveSupervisorSocketPath() {
35595
+ return process.env.CLEO_SUPERVISOR_SOCKET ?? join5(getCleoHome2(), SUPERVISOR_SOCKET_NAME);
35596
+ }
35597
+ async function sendResourceAdmit(socketPath, cls, holderId, budget) {
35598
+ const result = await sendLeaseRequest(
35599
+ socketPath,
35600
+ { kind: "resource_admit", class: cls, holder_id: holderId, budget },
35601
+ "resource_admit_result"
35602
+ );
35603
+ if ("unavailable" in result) return result;
35604
+ if (result.kind === "resource_admit_result") return result;
35605
+ return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
35606
+ }
35607
+ async function sendResourceRelease(socketPath, cls, holderId) {
35608
+ const result = await sendLeaseRequest(
35609
+ socketPath,
35610
+ { kind: "resource_release", class: cls, holder_id: holderId },
35611
+ "resource_release_result"
35612
+ );
35613
+ if ("unavailable" in result) return result;
35614
+ if (result.kind === "resource_release_result") return result;
35615
+ return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
35616
+ }
35617
+ function sendLeaseRequest(socketPath, request, expectedKind) {
35618
+ return new Promise((resolve5) => {
35619
+ const id = `ra-${process.pid}-${request.kind}`;
35620
+ const envelope = LeaseIpcRequestEnvelopeSchema.parse({
35621
+ protocol_version: LEASE_IPC_PROTOCOL_VERSION,
35622
+ id,
35623
+ direction: "request",
35624
+ request
35625
+ });
35626
+ const line2 = `${JSON.stringify(envelope)}
35627
+ `;
35628
+ let settled = false;
35629
+ let buffer = "";
35630
+ const socket = connect(socketPath);
35631
+ const done = (value) => {
35632
+ if (settled) return;
35633
+ settled = true;
35634
+ socket.removeAllListeners();
35635
+ socket.destroy();
35636
+ resolve5(value);
35637
+ };
35638
+ const degrade = (reason) => done({ unavailable: true, reason });
35639
+ socket.setTimeout(REQUEST_TIMEOUT_MS);
35640
+ const connectTimer = setTimeout(
35641
+ () => degrade("supervisor connect timeout"),
35642
+ CONNECT_TIMEOUT_MS
35643
+ );
35644
+ socket.on("connect", () => {
35645
+ clearTimeout(connectTimer);
35646
+ socket.write(line2);
35647
+ });
35648
+ socket.on("timeout", () => degrade("supervisor request timeout"));
35649
+ socket.on("error", (err) => {
35650
+ clearTimeout(connectTimer);
35651
+ degrade(err.message);
35652
+ });
35653
+ socket.on("close", () => {
35654
+ if (!settled) degrade("supervisor closed the connection before responding");
35655
+ });
35656
+ socket.on("data", (chunk) => {
35657
+ buffer += chunk.toString("utf8");
35658
+ const nl = buffer.indexOf("\n");
35659
+ if (nl < 0) return;
35660
+ let json3;
35661
+ try {
35662
+ json3 = JSON.parse(buffer.slice(0, nl));
35663
+ } catch (cause) {
35664
+ degrade(`malformed lease-ipc frame: ${cause instanceof Error ? cause.message : cause}`);
35665
+ return;
35666
+ }
35667
+ const parsed = LeaseIpcResponseEnvelopeSchema.safeParse(json3);
35668
+ if (!parsed.success) {
35669
+ degrade(`off-contract lease-ipc response: ${parsed.error.message}`);
35670
+ return;
35671
+ }
35672
+ const { response } = parsed.data;
35673
+ if (response.kind === expectedKind) {
35674
+ done(response);
35675
+ return;
35676
+ }
35677
+ if (response.kind === "error") {
35678
+ degrade(`${response.code}: ${response.message}`);
35679
+ return;
35680
+ }
35681
+ degrade(`unexpected lease-ipc response kind for ${request.kind}: ${response.kind}`);
35682
+ });
35683
+ });
35684
+ }
35685
+ var SUPERVISOR_SOCKET_NAME, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS;
35686
+ var init_supervisor_admit = __esm({
35687
+ "packages/core/src/resources/supervisor-admit.ts"() {
35688
+ "use strict";
35689
+ init_src();
35690
+ SUPERVISOR_SOCKET_NAME = "cleo-supervisor.sock";
35691
+ CONNECT_TIMEOUT_MS = 250;
35692
+ REQUEST_TIMEOUT_MS = 2e3;
35693
+ }
35694
+ });
35695
+
35696
+ // packages/core/src/resources/governor.ts
35697
+ var governor_exports = {};
35698
+ __export(governor_exports, {
35699
+ ResourceGovernor: () => ResourceGovernor,
35700
+ _resetGovernorStateForTest: () => _resetGovernorStateForTest,
35701
+ computeClassBudget: () => computeClassBudget,
35702
+ governor: () => governor,
35703
+ governorSlotDir: () => governorSlotDir,
35704
+ resolveGovernorMode: () => resolveGovernorMode,
35705
+ slotFileCount: () => slotFileCount
35706
+ });
35707
+ import { existsSync as existsSync3, mkdirSync, readdirSync as readdirSync2, writeFileSync } from "node:fs";
35708
+ import { availableParallelism, totalmem } from "node:os";
35709
+ import { join as join6 } from "node:path";
35174
35710
  import lockfile from "proper-lockfile";
35711
+ function log2() {
35712
+ if (_log2 === null) _log2 = getLogger("resource-governor");
35713
+ return _log2;
35714
+ }
35715
+ function resolveGovernorMode() {
35716
+ if (_cachedMode2 !== null) return _cachedMode2;
35717
+ const raw = process.env.CLEO_RESOURCES_MODE;
35718
+ _cachedMode2 = raw === "supervisor" || raw === "local" || raw === "off" ? raw : "local";
35719
+ return _cachedMode2;
35720
+ }
35721
+ function logSupervisorDegradeOnce(reason) {
35722
+ if (_supervisorDegradeLogged) return;
35723
+ _supervisorDegradeLogged = true;
35724
+ log2().info(
35725
+ `CLEO_RESOURCES_MODE=supervisor but the arbiter is unreachable (${reason}); degrading to local-mode admission for the process lifetime.`
35726
+ );
35727
+ }
35728
+ function _resetGovernorStateForTest() {
35729
+ _cachedMode2 = null;
35730
+ _supervisorDegradeLogged = false;
35731
+ }
35732
+ function someAvg10(sample) {
35733
+ const some = sample.globalPressure?.some ?? sample.slicePressure?.some;
35734
+ return some?.avg10 ?? 0;
35735
+ }
35736
+ function computeClassBudget(cls, sample, opts = {}) {
35737
+ if (cls === "interactive-cli") return Number.POSITIVE_INFINITY;
35738
+ const cpus = Math.max(1, opts.cpuCount ?? availableParallelism());
35739
+ const totalBytes = opts.totalMemBytes ?? totalmem();
35740
+ const headroomBytes = (opts.headroomMb ?? 2048) * MB;
35741
+ const hold = opts.holdSomeAvg10 ?? 10;
35742
+ const floor = opts.floorSomeAvg10 ?? 25;
35743
+ const some = someAvg10(sample);
35744
+ const availBytes = sample.memAvailableBytes ?? totalBytes;
35745
+ const fullStall = sample.globalPressure?.full?.avg10 ?? sample.slicePressure?.full?.avg10 ?? 0;
35746
+ const backoff = some > floor || fullStall > 10;
35747
+ switch (cls) {
35748
+ case "full-build":
35749
+ return 1;
35750
+ case "agent-session": {
35751
+ const estRamBytes = (opts.agentEstRamMb ?? 4096) * MB;
35752
+ const byMem = Math.floor((availBytes - headroomBytes) / estRamBytes);
35753
+ return clamp(1, byMem, Math.max(1, cpus - 2));
35754
+ }
35755
+ case "llm-call":
35756
+ return Math.max(1, cpus - 2);
35757
+ case "test-run":
35758
+ case "scoped-build": {
35759
+ const base = Math.max(1, Math.floor(cpus / 4));
35760
+ if (some > floor) return 1;
35761
+ if (some > hold) return Math.max(1, Math.floor(base / 2));
35762
+ return base;
35763
+ }
35764
+ case "db-heavy":
35765
+ return backoff ? 0 : 1;
35766
+ case "background-autonomous":
35767
+ return some > hold || fullStall > 5 ? 0 : 1;
35768
+ default:
35769
+ return 1;
35770
+ }
35771
+ }
35772
+ function clamp(lo, v, hi) {
35773
+ return Math.max(lo, Math.min(v, hi));
35774
+ }
35775
+ function governorSlotDir(cls) {
35776
+ return join6(getCleoHome(), "locks", `resource-${cls}`);
35777
+ }
35778
+ function ensureSlotFiles(dir, count) {
35779
+ if (!existsSync3(dir)) mkdirSync(dir, { recursive: true });
35780
+ const paths = [];
35781
+ for (let i = 0; i < count; i++) {
35782
+ const p = join6(dir, `slot-${i}.lock`);
35783
+ if (!existsSync3(p)) writeFileSync(p, "", { flag: "a" });
35784
+ paths.push(p);
35785
+ }
35786
+ return paths;
35787
+ }
35788
+ function sleep(ms) {
35789
+ return new Promise((r) => setTimeout(r, ms));
35790
+ }
35791
+ function passThroughGrant(cls) {
35792
+ return {
35793
+ deferred: false,
35794
+ class: cls,
35795
+ slot: -1,
35796
+ acquiredAtMs: Date.now(),
35797
+ release: async () => {
35798
+ }
35799
+ };
35800
+ }
35801
+ function deferral(cls, reason, retryAfterMs) {
35802
+ return { deferred: true, class: cls, retryAfterMs, reason };
35803
+ }
35804
+ function supervisorHolderId(cls) {
35805
+ _supervisorHolderSeq += 1;
35806
+ return `${process.pid}:${cls}:${_supervisorHolderSeq}`;
35807
+ }
35808
+ function shuffledIndices(n) {
35809
+ const order = Array.from({ length: n }, (_, i) => i);
35810
+ for (let i = order.length - 1; i > 0; i--) {
35811
+ const j = Math.floor(Math.random() * (i + 1));
35812
+ const a = order[i];
35813
+ const b = order[j];
35814
+ if (a !== void 0 && b !== void 0) {
35815
+ order[i] = b;
35816
+ order[j] = a;
35817
+ }
35818
+ }
35819
+ return order;
35820
+ }
35821
+ async function countHeldSlots(cls, budget) {
35822
+ const dir = governorSlotDir(cls);
35823
+ if (!existsSync3(dir)) return 0;
35824
+ const slots = ensureSlotFiles(dir, budget);
35825
+ let held = 0;
35826
+ for (const path of slots) {
35827
+ try {
35828
+ const release = await lockfile.lock(path, { retries: 0, stale: STALE_MS, realpath: false });
35829
+ await release();
35830
+ } catch {
35831
+ held++;
35832
+ }
35833
+ }
35834
+ return held;
35835
+ }
35836
+ function slotFileCount(cls) {
35837
+ const dir = governorSlotDir(cls);
35838
+ if (!existsSync3(dir)) return 0;
35839
+ return readdirSync2(dir).filter((f) => f.startsWith("slot-") && f.endsWith(".lock")).length;
35840
+ }
35841
+ var _log2, _cachedMode2, _supervisorDegradeLogged, MB, STALE_MS, _supervisorHolderSeq, ResourceGovernor, governor;
35842
+ var init_governor = __esm({
35843
+ "packages/core/src/resources/governor.ts"() {
35844
+ "use strict";
35845
+ init_src();
35846
+ init_logger2();
35847
+ init_paths();
35848
+ init_monitor();
35849
+ init_supervisor_admit();
35850
+ _log2 = null;
35851
+ _cachedMode2 = null;
35852
+ _supervisorDegradeLogged = false;
35853
+ MB = 1024 * 1024;
35854
+ STALE_MS = 6e5;
35855
+ _supervisorHolderSeq = 0;
35856
+ ResourceGovernor = class {
35857
+ /**
35858
+ * Acquire one slot of `cls`. Returns a {@link ResourceGrant} on success or a
35859
+ * {@link ResourceDeferral} on denial. Never throws for admission control;
35860
+ * only genuinely unexpected I/O errors propagate.
35861
+ */
35862
+ async acquire(cls, opts = {}) {
35863
+ const mode = resolveGovernorMode();
35864
+ if (mode === "off" || cls === "interactive-cli") {
35865
+ return passThroughGrant(cls);
35866
+ }
35867
+ const sample = opts.sample ?? await (opts.monitor ?? new ResourceMonitor()).sample();
35868
+ const budget = computeClassBudget(cls, sample, opts);
35869
+ if (!Number.isFinite(budget)) return passThroughGrant(cls);
35870
+ if (budget <= 0) {
35871
+ return deferral(
35872
+ cls,
35873
+ `class '${cls}' budget is 0 under current pressure (some avg10=${someAvg10(sample).toFixed(1)})`,
35874
+ DEFAULT_RESOURCE_RETRY_AFTER_MS
35875
+ );
35876
+ }
35877
+ if (mode === "supervisor") {
35878
+ const viaSupervisor = await this.acquireViaSupervisor(cls, Math.floor(budget));
35879
+ if (viaSupervisor !== null) return viaSupervisor;
35880
+ }
35881
+ const dir = governorSlotDir(cls);
35882
+ const slots = ensureSlotFiles(dir, budget);
35883
+ const blocking = opts.blocking ?? true;
35884
+ const timeoutMs = opts.timeoutMs ?? 36e5;
35885
+ const pollMs = opts.pollMs ?? 200;
35886
+ const startedAt = Date.now();
35887
+ do {
35888
+ const order = shuffledIndices(slots.length);
35889
+ for (const idx of order) {
35890
+ const path = slots[idx];
35891
+ if (!path) continue;
35892
+ try {
35893
+ const release = await lockfile.lock(path, {
35894
+ retries: 0,
35895
+ stale: STALE_MS,
35896
+ realpath: false
35897
+ });
35898
+ let released = false;
35899
+ return {
35900
+ deferred: false,
35901
+ class: cls,
35902
+ slot: idx,
35903
+ acquiredAtMs: Date.now(),
35904
+ release: async () => {
35905
+ if (released) return;
35906
+ released = true;
35907
+ try {
35908
+ await release();
35909
+ } catch {
35910
+ }
35911
+ }
35912
+ };
35913
+ } catch {
35914
+ }
35915
+ }
35916
+ if (!blocking) break;
35917
+ await sleep(pollMs);
35918
+ } while (Date.now() - startedAt < timeoutMs);
35919
+ return deferral(
35920
+ cls,
35921
+ `class '${cls}' is at capacity (${budget} slot(s)); ` + (blocking ? `timed out after ${timeoutMs}ms` : "no slot free"),
35922
+ Math.min(pollMs * 4, DEFAULT_RESOURCE_RETRY_AFTER_MS)
35923
+ );
35924
+ }
35925
+ /**
35926
+ * Route an admission through the supervisor's central `resource_admit` verb.
35927
+ * Returns a grant (whose `release` calls `resource_release`) or a deferral, or
35928
+ * `null` when the supervisor is unreachable so the caller degrades to the
35929
+ * local slot engine. Never throws — a dead arbiter never deadlocks work.
35930
+ *
35931
+ * @task T12001
35932
+ */
35933
+ async acquireViaSupervisor(cls, budget) {
35934
+ const socketPath = resolveSupervisorSocketPath();
35935
+ const holderId = supervisorHolderId(cls);
35936
+ const reply = await sendResourceAdmit(socketPath, cls, holderId, budget);
35937
+ if ("unavailable" in reply) {
35938
+ logSupervisorDegradeOnce(reply.reason);
35939
+ return null;
35940
+ }
35941
+ if (reply.disposition === "deferred") {
35942
+ return deferral(
35943
+ cls,
35944
+ `class '${cls}' deferred by supervisor (budget ${budget})`,
35945
+ reply.retry_after_ms || DEFAULT_RESOURCE_RETRY_AFTER_MS
35946
+ );
35947
+ }
35948
+ let released = false;
35949
+ return {
35950
+ deferred: false,
35951
+ class: cls,
35952
+ slot: 0,
35953
+ acquiredAtMs: Date.now(),
35954
+ release: async () => {
35955
+ if (released) return;
35956
+ released = true;
35957
+ await sendResourceRelease(socketPath, cls, holderId).catch(() => {
35958
+ });
35959
+ }
35960
+ };
35961
+ }
35962
+ /** Non-blocking single-pass acquire (admission semantics). */
35963
+ async tryAcquire(cls, opts = {}) {
35964
+ return this.acquire(cls, { ...opts, blocking: false });
35965
+ }
35966
+ /**
35967
+ * Currently-grantable slot count for `cls` = budget − held. Held is the count
35968
+ * of slot files currently locked. `Infinity` for ungated classes.
35969
+ */
35970
+ async available(cls, opts = {}) {
35971
+ if (resolveGovernorMode() === "off" || cls === "interactive-cli") {
35972
+ return Number.POSITIVE_INFINITY;
35973
+ }
35974
+ const sample = opts.sample ?? await (opts.monitor ?? new ResourceMonitor()).sample();
35975
+ const budget = computeClassBudget(cls, sample, opts);
35976
+ if (!Number.isFinite(budget)) return Number.POSITIVE_INFINITY;
35977
+ if (budget <= 0) return 0;
35978
+ const held = await countHeldSlots(cls, budget);
35979
+ return Math.max(0, budget - held);
35980
+ }
35981
+ };
35982
+ governor = new ResourceGovernor();
35983
+ }
35984
+ });
35985
+
35986
+ // packages/core/src/store/lock.ts
35987
+ import lockfile2 from "proper-lockfile";
35175
35988
  async function acquireLock(filePath, options) {
35176
35989
  try {
35177
- const release = await lockfile.lock(filePath, {
35990
+ const release = await lockfile2.lock(filePath, {
35178
35991
  ...DEFAULT_LOCK_OPTIONS,
35179
35992
  ...options?.stale !== void 0 && { stale: options.stale },
35180
35993
  ...options?.retries !== void 0 && {
@@ -35220,7 +36033,7 @@ var init_lock = __esm({
35220
36033
  });
35221
36034
 
35222
36035
  // packages/core/src/store/atomic.ts
35223
- import { mkdir, readFile as readFile2, rename, unlink } from "node:fs/promises";
36036
+ import { mkdir, readFile as readFile3, rename, unlink } from "node:fs/promises";
35224
36037
  import { dirname as dirname3 } from "node:path";
35225
36038
  import writeFileAtomic from "write-file-atomic";
35226
36039
  async function atomicWrite(filePath, data, options) {
@@ -35236,7 +36049,7 @@ async function atomicWrite(filePath, data, options) {
35236
36049
  }
35237
36050
  async function safeReadFile(filePath) {
35238
36051
  try {
35239
- return await readFile2(filePath, "utf8");
36052
+ return await readFile3(filePath, "utf8");
35240
36053
  } catch (err) {
35241
36054
  if (err instanceof Error && "code" in err && err.code === "ENOENT") {
35242
36055
  return null;
@@ -35257,34 +36070,34 @@ var init_atomic = __esm({
35257
36070
  });
35258
36071
 
35259
36072
  // packages/core/src/store/backup.ts
35260
- import { copyFile, rename as fsRename, mkdir as mkdir2, readdir, stat, unlink as unlink2 } from "node:fs/promises";
35261
- import { basename, join as join5 } from "node:path";
36073
+ import { copyFile, rename as fsRename, mkdir as mkdir2, readdir, stat as stat2, unlink as unlink2 } from "node:fs/promises";
36074
+ import { basename, join as join7 } from "node:path";
35262
36075
  async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUPS) {
35263
36076
  try {
35264
36077
  await mkdir2(backupDir, { recursive: true });
35265
36078
  const fileName = basename(filePath);
35266
36079
  try {
35267
- await stat(filePath);
36080
+ await stat2(filePath);
35268
36081
  } catch {
35269
36082
  throw new CleoError(3 /* FILE_ERROR */, `Cannot backup: source file not found: ${filePath}`);
35270
36083
  }
35271
36084
  for (let i = maxBackups; i >= 1; i--) {
35272
- const current = join5(backupDir, `${fileName}.${i}`);
36085
+ const current = join7(backupDir, `${fileName}.${i}`);
35273
36086
  if (i === maxBackups) {
35274
36087
  try {
35275
36088
  await unlink2(current);
35276
36089
  } catch {
35277
36090
  }
35278
36091
  } else {
35279
- const next = join5(backupDir, `${fileName}.${i + 1}`);
36092
+ const next = join7(backupDir, `${fileName}.${i + 1}`);
35280
36093
  try {
35281
- await stat(current);
36094
+ await stat2(current);
35282
36095
  await fsRename(current, next);
35283
36096
  } catch {
35284
36097
  }
35285
36098
  }
35286
36099
  }
35287
- const backupPath = join5(backupDir, `${fileName}.1`);
36100
+ const backupPath = join7(backupDir, `${fileName}.1`);
35288
36101
  await copyFile(filePath, backupPath);
35289
36102
  return backupPath;
35290
36103
  } catch (err) {
@@ -35563,8 +36376,8 @@ var init_json2 = __esm({
35563
36376
  });
35564
36377
 
35565
36378
  // packages/core/src/scaffold/ensure-config.ts
35566
- import { existsSync as existsSync3, readFileSync } from "node:fs";
35567
- import { basename as basename2, dirname as dirname4, join as join6, resolve as resolve2 } from "node:path";
36379
+ import { existsSync as existsSync4, readFileSync } from "node:fs";
36380
+ import { basename as basename2, dirname as dirname4, join as join8, resolve as resolve2 } from "node:path";
35568
36381
  import { fileURLToPath as fileURLToPath2 } from "node:url";
35569
36382
  function getPackageRoot() {
35570
36383
  const thisFile = fileURLToPath2(import.meta.url);
@@ -35572,7 +36385,7 @@ function getPackageRoot() {
35572
36385
  }
35573
36386
  function getCleoVersion() {
35574
36387
  try {
35575
- const pkgPath = join6(getPackageRoot(), "package.json");
36388
+ const pkgPath = join8(getPackageRoot(), "package.json");
35576
36389
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
35577
36390
  return pkg.version ?? "0.0.0";
35578
36391
  } catch {
@@ -35591,25 +36404,25 @@ var init_ensure_config = __esm({
35591
36404
  // packages/core/src/store/exodus/archive.ts
35592
36405
  import {
35593
36406
  copyFileSync as copyFileSync2,
35594
- existsSync as existsSync4,
35595
- mkdirSync,
36407
+ existsSync as existsSync5,
36408
+ mkdirSync as mkdirSync2,
35596
36409
  renameSync,
35597
36410
  unlinkSync,
35598
- writeFileSync
36411
+ writeFileSync as writeFileSync2
35599
36412
  } from "node:fs";
35600
- import { basename as basename3, join as join7 } from "node:path";
36413
+ import { basename as basename3, join as join9 } from "node:path";
35601
36414
  function scopeBaseDir(scope, cwd) {
35602
36415
  return scope === "project" ? resolveCleoDir(cwd) : getCleoHome();
35603
36416
  }
35604
36417
  function exodusArchiveDir(scope, cwd) {
35605
- return join7(scopeBaseDir(scope, cwd), ARCHIVE_DIR_NAME);
36418
+ return join9(scopeBaseDir(scope, cwd), ARCHIVE_DIR_NAME);
35606
36419
  }
35607
36420
  function exodusMarkerPath(scope, cwd) {
35608
- return join7(scopeBaseDir(scope, cwd), MARKER_FILENAME_BY_SCOPE[scope]);
36421
+ return join9(scopeBaseDir(scope, cwd), MARKER_FILENAME_BY_SCOPE[scope]);
35609
36422
  }
35610
36423
  function hasExodusCompleteMarker(scope, cwd) {
35611
36424
  try {
35612
- return existsSync4(exodusMarkerPath(scope, cwd));
36425
+ return existsSync5(exodusMarkerPath(scope, cwd));
35613
36426
  } catch {
35614
36427
  return false;
35615
36428
  }
@@ -35617,7 +36430,7 @@ function hasExodusCompleteMarker(scope, cwd) {
35617
36430
  function writeExodusCompleteMarker(scope, archivedSources, cwd) {
35618
36431
  const markerPath = exodusMarkerPath(scope, cwd);
35619
36432
  const baseDir = scopeBaseDir(scope, cwd);
35620
- mkdirSync(baseDir, { recursive: true });
36433
+ mkdirSync2(baseDir, { recursive: true });
35621
36434
  const marker16 = {
35622
36435
  version: 1,
35623
36436
  scope,
@@ -35626,17 +36439,17 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd) {
35626
36439
  archivedSources: [...archivedSources]
35627
36440
  };
35628
36441
  const tmpPath = `${markerPath}.tmp`;
35629
- writeFileSync(tmpPath, JSON.stringify(marker16, null, 2) + "\n", "utf8");
36442
+ writeFileSync2(tmpPath, JSON.stringify(marker16, null, 2) + "\n", "utf8");
35630
36443
  renameSync(tmpPath, markerPath);
35631
- log2.info({ scope, markerPath, archivedSources }, "exodus: wrote completion marker");
36444
+ log3.info({ scope, markerPath, archivedSources }, "exodus: wrote completion marker");
35632
36445
  return markerPath;
35633
36446
  }
35634
36447
  function moveFileInto(srcPath, destDir) {
35635
- mkdirSync(destDir, { recursive: true });
35636
- let dest = join7(destDir, basename3(srcPath));
35637
- if (existsSync4(dest)) {
36448
+ mkdirSync2(destDir, { recursive: true });
36449
+ let dest = join9(destDir, basename3(srcPath));
36450
+ if (existsSync5(dest)) {
35638
36451
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/Z$/, "Z");
35639
- dest = join7(destDir, `${basename3(srcPath)}.${stamp}`);
36452
+ dest = join9(destDir, `${basename3(srcPath)}.${stamp}`);
35640
36453
  }
35641
36454
  try {
35642
36455
  renameSync(srcPath, dest);
@@ -35647,25 +36460,25 @@ function moveFileInto(srcPath, destDir) {
35647
36460
  return dest;
35648
36461
  }
35649
36462
  function archiveSourceDb(source, cwd) {
35650
- if (!existsSync4(source.path)) {
36463
+ if (!existsSync5(source.path)) {
35651
36464
  return { name: source.name, sourcePath: source.path, archivedTo: null, action: "absent" };
35652
36465
  }
35653
36466
  const destDir = exodusArchiveDir(source.targetScope, cwd);
35654
36467
  const archivedTo = moveFileInto(source.path, destDir);
35655
36468
  for (const suffix of SIDECAR_SUFFIXES) {
35656
36469
  const sidecar = `${source.path}${suffix}`;
35657
- if (existsSync4(sidecar)) {
36470
+ if (existsSync5(sidecar)) {
35658
36471
  try {
35659
36472
  moveFileInto(sidecar, destDir);
35660
36473
  } catch (err) {
35661
- log2.warn(
36474
+ log3.warn(
35662
36475
  { err, sidecar, sourceName: source.name },
35663
36476
  "exodus-archive: failed to archive sidecar (non-fatal)"
35664
36477
  );
35665
36478
  }
35666
36479
  }
35667
36480
  }
35668
- log2.info(
36481
+ log3.info(
35669
36482
  { sourceName: source.name, sourcePath: source.path, archivedTo, scope: source.targetScope },
35670
36483
  "exodus-archive: archived legacy source DB"
35671
36484
  );
@@ -35700,7 +36513,7 @@ function detectStrandedResidue(sources, cwd) {
35700
36513
  const stranded = [];
35701
36514
  for (const source of sources) {
35702
36515
  if (!markedScopes.has(source.targetScope)) continue;
35703
- if (existsSync4(source.path)) {
36516
+ if (existsSync5(source.path)) {
35704
36517
  stranded.push({ name: source.name, path: source.path, scope: source.targetScope });
35705
36518
  }
35706
36519
  }
@@ -35716,14 +36529,14 @@ function archiveStrandedResidue(stranded, sources, cwd) {
35716
36529
  }
35717
36530
  return results;
35718
36531
  }
35719
- var log2, ARCHIVE_DIR_NAME, MARKER_FILENAME_BY_SCOPE, SIDECAR_SUFFIXES;
36532
+ var log3, ARCHIVE_DIR_NAME, MARKER_FILENAME_BY_SCOPE, SIDECAR_SUFFIXES;
35720
36533
  var init_archive2 = __esm({
35721
36534
  "packages/core/src/store/exodus/archive.ts"() {
35722
36535
  "use strict";
35723
36536
  init_logger2();
35724
36537
  init_paths();
35725
36538
  init_ensure_config();
35726
- log2 = getLogger("exodus-archive");
36539
+ log3 = getLogger("exodus-archive");
35727
36540
  ARCHIVE_DIR_NAME = "_archive";
35728
36541
  MARKER_FILENAME_BY_SCOPE = {
35729
36542
  project: "exodus-complete",
@@ -36117,7 +36930,7 @@ var init_table_name_map = __esm({
36117
36930
  });
36118
36931
 
36119
36932
  // packages/core/src/store/exodus/count-parity.ts
36120
- import { existsSync as existsSync5 } from "node:fs";
36933
+ import { existsSync as existsSync6 } from "node:fs";
36121
36934
  function listTables(db) {
36122
36935
  return db.prepare(
36123
36936
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%' ORDER BY name"
@@ -36138,14 +36951,14 @@ function rowCount(db, tableName) {
36138
36951
  function computeCountParity(sources, projectDbPath, globalDbPath) {
36139
36952
  const entries = [];
36140
36953
  let skipped = 0;
36141
- if (!existsSync5(projectDbPath) || !existsSync5(globalDbPath)) {
36954
+ if (!existsSync6(projectDbPath) || !existsSync6(globalDbPath)) {
36142
36955
  return { ok: false, entries: [], deficits: [], checked: 0, skipped: 0 };
36143
36956
  }
36144
36957
  const projectSnap = openCleoDbSnapshot(projectDbPath, { readOnly: true });
36145
36958
  const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
36146
36959
  try {
36147
36960
  for (const src of sources) {
36148
- if (!existsSync5(src.path)) continue;
36961
+ if (!existsSync6(src.path)) continue;
36149
36962
  const srcSnap = openCleoDbSnapshot(src.path, { readOnly: true });
36150
36963
  try {
36151
36964
  for (const legacyTable of listTables(srcSnap.db)) {
@@ -36184,27 +36997,27 @@ function computeCountParity(sources, projectDbPath, globalDbPath) {
36184
36997
  }
36185
36998
  const deficits = entries.filter((e) => e.deficit > 0);
36186
36999
  if (deficits.length > 0) {
36187
- log3.warn(
37000
+ log4.warn(
36188
37001
  { deficitCount: deficits.length, sample: deficits.slice(0, 5) },
36189
37002
  `exodus count-parity: ${deficits.length} table(s) have FEWER rows in the consolidated target than the legacy source`
36190
37003
  );
36191
37004
  }
36192
37005
  return { ok: deficits.length === 0, entries, deficits, checked: entries.length, skipped };
36193
37006
  }
36194
- var log3;
37007
+ var log4;
36195
37008
  var init_count_parity = __esm({
36196
37009
  "packages/core/src/store/exodus/count-parity.ts"() {
36197
37010
  "use strict";
36198
37011
  init_logger2();
36199
37012
  init_open_cleo_db();
36200
37013
  init_table_name_map();
36201
- log3 = getLogger("exodus-count-parity");
37014
+ log4 = getLogger("exodus-count-parity");
36202
37015
  }
36203
37016
  });
36204
37017
 
36205
37018
  // packages/core/src/store/exodus/plan.ts
36206
- import { existsSync as existsSync6, readdirSync as readdirSync2, statfsSync, statSync } from "node:fs";
36207
- import { join as join8 } from "node:path";
37019
+ import { existsSync as existsSync7, readdirSync as readdirSync3, statfsSync, statSync } from "node:fs";
37020
+ import { join as join10 } from "node:path";
36208
37021
  function computeRequiredBytes(totalSourceBytes, largestSourceBytes) {
36209
37022
  return Math.ceil(STAGING_HEADROOM_FACTOR * largestSourceBytes) + totalSourceBytes;
36210
37023
  }
@@ -36215,33 +37028,33 @@ function buildSourceDescriptors(cwd) {
36215
37028
  // Project-tier — go into consolidated project-scope cleo.db
36216
37029
  {
36217
37030
  name: "tasks",
36218
- path: join8(cleoDir, "tasks.db"),
37031
+ path: join10(cleoDir, "tasks.db"),
36219
37032
  targetScope: "project"
36220
37033
  },
36221
37034
  {
36222
37035
  name: "brain (project)",
36223
- path: join8(cleoDir, "brain.db"),
37036
+ path: join10(cleoDir, "brain.db"),
36224
37037
  targetScope: "project"
36225
37038
  },
36226
37039
  {
36227
37040
  name: "conduit",
36228
- path: join8(cleoDir, "conduit.db"),
37041
+ path: join10(cleoDir, "conduit.db"),
36229
37042
  targetScope: "project"
36230
37043
  },
36231
37044
  // Global-tier — go into consolidated global-scope cleo.db
36232
37045
  {
36233
37046
  name: "nexus",
36234
- path: join8(cleoHome, "nexus.db"),
37047
+ path: join10(cleoHome, "nexus.db"),
36235
37048
  targetScope: "global"
36236
37049
  },
36237
37050
  {
36238
37051
  name: "signaldock",
36239
- path: join8(cleoHome, "signaldock.db"),
37052
+ path: join10(cleoHome, "signaldock.db"),
36240
37053
  targetScope: "global"
36241
37054
  },
36242
37055
  {
36243
37056
  name: "skills",
36244
- path: join8(cleoHome, "skills.db"),
37057
+ path: join10(cleoHome, "skills.db"),
36245
37058
  targetScope: "global"
36246
37059
  }
36247
37060
  ];
@@ -36267,10 +37080,10 @@ function deriveStagingDirName() {
36267
37080
  }
36268
37081
  function findExistingStaging(cleoDir) {
36269
37082
  try {
36270
- const entries = readdirSync2(cleoDir, { withFileTypes: true });
37083
+ const entries = readdirSync3(cleoDir, { withFileTypes: true });
36271
37084
  const stagingDirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => e.name).sort().reverse();
36272
37085
  if (stagingDirs.length > 0) {
36273
- return join8(cleoDir, stagingDirs[0]);
37086
+ return join10(cleoDir, stagingDirs[0]);
36274
37087
  }
36275
37088
  } catch {
36276
37089
  }
@@ -36286,7 +37099,7 @@ function buildExodusPlan(cwd) {
36286
37099
  const availableBytes = getAvailableBytes(cleoDir);
36287
37100
  const diskPreflight = totalSourceBytes === 0 || availableBytes >= requiredBytes;
36288
37101
  const existingStaging = findExistingStaging(cleoDir);
36289
- const stagingDir = existingStaging ?? join8(cleoDir, deriveStagingDirName());
37102
+ const stagingDir = existingStaging ?? join10(cleoDir, deriveStagingDirName());
36290
37103
  const resumeFromStaging = existingStaging !== null;
36291
37104
  const projectDbPath = resolveDualScopeDbPath("project", cwd);
36292
37105
  const globalDbPath = resolveDualScopeDbPath("global");
@@ -36305,7 +37118,7 @@ function buildExodusPlan(cwd) {
36305
37118
  };
36306
37119
  }
36307
37120
  function sourcesPresent(sources) {
36308
- return sources.some((s) => existsSync6(s.path));
37121
+ return sources.some((s) => existsSync7(s.path));
36309
37122
  }
36310
37123
  var STAGING_HEADROOM_FACTOR, STAGING_COPY_SKIP_THRESHOLD_BYTES;
36311
37124
  var init_plan2 = __esm({
@@ -36319,18 +37132,18 @@ var init_plan2 = __esm({
36319
37132
  });
36320
37133
 
36321
37134
  // packages/core/src/store/exodus/health.ts
36322
- import { existsSync as existsSync7, statSync as statSync2 } from "node:fs";
37135
+ import { existsSync as existsSync8, statSync as statSync2 } from "node:fs";
36323
37136
  function buildExodusHealth(cwd) {
36324
37137
  const plan = buildExodusPlan(cwd);
36325
- const anyLegacyPresent = plan.sources.some((s) => existsSync7(s.path));
37138
+ const anyLegacyPresent = plan.sources.some((s) => existsSync8(s.path));
36326
37139
  const parity = anyLegacyPresent ? computeCountParity(plan.sources, plan.projectDbPath, plan.globalDbPath) : { ok: true, entries: [], deficits: [], checked: 0, skipped: 0 };
36327
37140
  const consolidatedExistsByScope = {
36328
- project: existsSync7(plan.projectDbPath),
36329
- global: existsSync7(plan.globalDbPath)
37141
+ project: existsSync8(plan.projectDbPath),
37142
+ global: existsSync8(plan.globalDbPath)
36330
37143
  };
36331
37144
  const buildScope = (scope) => {
36332
37145
  const sources = plan.sources.filter((s) => s.targetScope === scope).map((s) => {
36333
- const present = existsSync7(s.path);
37146
+ const present = existsSync8(s.path);
36334
37147
  let bytes = 0;
36335
37148
  if (present) {
36336
37149
  try {
@@ -36597,15 +37410,15 @@ var init_types = __esm({
36597
37410
  // packages/core/src/store/exodus/migrate.ts
36598
37411
  import {
36599
37412
  copyFileSync as copyFileSync3,
36600
- existsSync as existsSync8,
36601
- mkdirSync as mkdirSync2,
37413
+ existsSync as existsSync9,
37414
+ mkdirSync as mkdirSync3,
36602
37415
  readFileSync as readFileSync2,
36603
37416
  renameSync as renameSync2,
36604
37417
  statSync as statSync3,
36605
37418
  unlinkSync as unlinkSync2,
36606
- writeFileSync as writeFileSync2
37419
+ writeFileSync as writeFileSync3
36607
37420
  } from "node:fs";
36608
- import { join as join9 } from "node:path";
37421
+ import { join as join11 } from "node:path";
36609
37422
  function getSqliteVersion(db) {
36610
37423
  try {
36611
37424
  const row = db.prepare("SELECT sqlite_version() AS v").get();
@@ -36621,14 +37434,14 @@ function listTables2(db) {
36621
37434
  return rows.map((r) => r.name);
36622
37435
  }
36623
37436
  function writeJournal(stagingDir, journal) {
36624
- const journalPath = join9(stagingDir, JOURNAL_FILENAME);
37437
+ const journalPath = join11(stagingDir, JOURNAL_FILENAME);
36625
37438
  const tmpPath = `${journalPath}.tmp`;
36626
- writeFileSync2(tmpPath, JSON.stringify(journal, null, 2) + "\n", "utf8");
37439
+ writeFileSync3(tmpPath, JSON.stringify(journal, null, 2) + "\n", "utf8");
36627
37440
  renameSync2(tmpPath, journalPath);
36628
37441
  }
36629
37442
  function readJournal(stagingDir) {
36630
- const journalPath = join9(stagingDir, JOURNAL_FILENAME);
36631
- if (!existsSync8(journalPath)) return null;
37443
+ const journalPath = join11(stagingDir, JOURNAL_FILENAME);
37444
+ if (!existsSync9(journalPath)) return null;
36632
37445
  try {
36633
37446
  return JSON.parse(readFileSync2(journalPath, "utf8"));
36634
37447
  } catch {
@@ -36636,17 +37449,17 @@ function readJournal(stagingDir) {
36636
37449
  }
36637
37450
  }
36638
37451
  function clearExodusJournal(stagingDir) {
36639
- const journalPath = join9(stagingDir, JOURNAL_FILENAME);
37452
+ const journalPath = join11(stagingDir, JOURNAL_FILENAME);
36640
37453
  try {
36641
- if (!existsSync8(journalPath)) return false;
37454
+ if (!existsSync9(journalPath)) return false;
36642
37455
  unlinkSync2(journalPath);
36643
- log4.info(
37456
+ log5.info(
36644
37457
  { stagingDir },
36645
37458
  "exodus: cleared migrate journal after abort/rollback \u2014 a retry will RE-COPY all tables"
36646
37459
  );
36647
37460
  return true;
36648
37461
  } catch (err) {
36649
- log4.warn(
37462
+ log5.warn(
36650
37463
  { err, stagingDir },
36651
37464
  'exodus: failed to clear migrate journal after rollback (a retry may skip already-"done" tables)'
36652
37465
  );
@@ -36671,7 +37484,7 @@ function lockPath(dbPath) {
36671
37484
  }
36672
37485
  function acquireAdvisoryLock(dbPath) {
36673
37486
  const lp = lockPath(dbPath);
36674
- writeFileSync2(lp, JSON.stringify({ pid: process.pid, ts: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
37487
+ writeFileSync3(lp, JSON.stringify({ pid: process.pid, ts: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
36675
37488
  }
36676
37489
  function releaseAdvisoryLock(dbPath) {
36677
37490
  try {
@@ -36734,7 +37547,7 @@ function buildSelectExpr(attachAlias, legacyTable, targetTableName, col, srcType
36734
37547
  function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyTableName, sourceName, targetSchema = "main") {
36735
37548
  const resolution = resolveConsolidatedTableName(sourceName, legacyTableName);
36736
37549
  if (resolution.kind === "skip") {
36737
- log4.warn(
37550
+ log5.warn(
36738
37551
  { legacyTableName, sourceName, reason: resolution.reason },
36739
37552
  `Exodus: explicitly skipping table \u2014 ${resolution.reason}`
36740
37553
  );
@@ -36753,7 +37566,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36753
37566
  ).get();
36754
37567
  if (!existsRow) {
36755
37568
  const reason = `consolidated target '${targetTableName}' not found (mapped from legacy '${legacyTableName}')`;
36756
- log4.warn(
37569
+ log5.warn(
36757
37570
  { legacyTableName, targetTableName, sourceName, attachAlias, targetSchema },
36758
37571
  `Exodus: ${reason}`
36759
37572
  );
@@ -36764,13 +37577,13 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36764
37577
  const sharedColumns = srcPragma.map((r) => r.name).filter((col) => tgtColMap.has(col));
36765
37578
  if (sharedColumns.length === 0) {
36766
37579
  const reason = `no overlapping columns between source '${legacyTableName}' and target '${targetTableName}'`;
36767
- log4.warn({ legacyTableName, targetTableName, sourceName }, `Exodus: ${reason}`);
37580
+ log5.warn({ legacyTableName, targetTableName, sourceName }, `Exodus: ${reason}`);
36768
37581
  return { rowsCopied: 0, skipped: true, reason };
36769
37582
  }
36770
37583
  const srcOnlyColumns = srcPragma.map((r) => r.name).filter((c) => !tgtColMap.has(c));
36771
37584
  const tgtOnlyColumns = tgtPragma.map((r) => r.name).filter((c) => !srcColumns.has(c));
36772
37585
  if (srcOnlyColumns.length > 0 || tgtOnlyColumns.length > 0) {
36773
- log4.info(
37586
+ log5.info(
36774
37587
  { legacyTableName, targetTableName, sourceName, srcOnlyColumns, tgtOnlyColumns },
36775
37588
  "Exodus: column drift detected \u2014 copying intersection, dropping src-only cols, using defaults for tgt-only cols"
36776
37589
  );
@@ -36785,7 +37598,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36785
37598
  return isoGlobCols.has(col) && (upper.includes("INT") || upper === "" || upper === "NUMERIC");
36786
37599
  });
36787
37600
  if (coercedCols.length > 0) {
36788
- log4.info(
37601
+ log5.info(
36789
37602
  {
36790
37603
  legacyTableName,
36791
37604
  targetTableName,
@@ -36801,7 +37614,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36801
37614
  (col) => ENUM_NORMALIZATIONS.has(`${targetTableName}.${col}`)
36802
37615
  );
36803
37616
  if (normalizedCols.length > 0) {
36804
- log4.info(
37617
+ log5.info(
36805
37618
  { legacyTableName, targetTableName, sourceName, normalizedCols },
36806
37619
  `Exodus: applying enum-value normalization for ${normalizedCols.length} column(s) (T11547)`
36807
37620
  );
@@ -36810,7 +37623,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36810
37623
  (col) => NUMERIC_CLAMPS.has(`${targetTableName}.${col}`)
36811
37624
  );
36812
37625
  if (clampedCols.length > 0) {
36813
- log4.info(
37626
+ log5.info(
36814
37627
  { legacyTableName, targetTableName, sourceName, clampedCols },
36815
37628
  `Exodus: applying non-finite numeric clamp for ${clampedCols.length} column(s) (T11782)`
36816
37629
  );
@@ -36852,7 +37665,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36852
37665
  if (rowsCopied < sourceCount) {
36853
37666
  const presentAccountedFor = existingBefore + rowsCopied;
36854
37667
  if (presentAccountedFor >= sourceCount) {
36855
- log4.info(
37668
+ log5.info(
36856
37669
  { legacyTableName, targetTableName, sourceName, sourceCount, rowsCopied, existingBefore },
36857
37670
  `Exodus: '${legacyTableName}'\u2192'${targetTableName}' \u2014 ${sourceCount - rowsCopied} of ${sourceCount} row(s) already present in target (idempotent PK dedup), ${rowsCopied} newly copied; no loss`
36858
37671
  );
@@ -36860,7 +37673,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36860
37673
  }
36861
37674
  const missing = sourceCount - presentAccountedFor;
36862
37675
  const reason = `INSERT OR IGNORE lost ${missing} of ${sourceCount} rows from '${legacyTableName}'\u2192'${targetTableName}' (rowsCopied=${rowsCopied}, existingBefore=${existingBefore}) \u2014 a CHECK/NOT NULL/type/enum constraint rejected them (NOT PK dedup); inspect epoch coercion + enum normalization. verify will confirm.`;
36863
- log4.error(
37676
+ log5.error(
36864
37677
  {
36865
37678
  legacyTableName,
36866
37679
  targetTableName,
@@ -36880,10 +37693,10 @@ function checkSchemaVersion(journal, forceCrossVersion) {
36880
37693
  if (journal.targetSchemaVersion !== EXODUS_TARGET_SCHEMA_VERSION) {
36881
37694
  const msg = `Schema version mismatch: journal=${journal.targetSchemaVersion}, expected=${EXODUS_TARGET_SCHEMA_VERSION}`;
36882
37695
  if (forceCrossVersion) {
36883
- log4.warn(msg + " (--force-cross-version: continuing anyway)");
37696
+ log5.warn(msg + " (--force-cross-version: continuing anyway)");
36884
37697
  return true;
36885
37698
  }
36886
- log4.error(msg + " \u2014 pass --force-cross-version to override");
37699
+ log5.error(msg + " \u2014 pass --force-cross-version to override");
36887
37700
  return false;
36888
37701
  }
36889
37702
  return true;
@@ -36900,10 +37713,10 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress) {
36900
37713
  error: `Insufficient disk space for exodus: need \u2265${plan.requiredBytes} bytes (\u2248${STAGING_HEADROOM_FACTOR}\xD7 largest source ${plan.largestSourceBytes} + consolidated estimate ${plan.totalSourceBytes}), but only ${plan.availableBytes} bytes are free on the target filesystem \u2014 ${shortfall} bytes short. Free up at least ${shortfall} bytes (e.g. \`cleo backup prune\`, clear caches), or move the .cleo/ directory to a larger volume, then retry.`
36901
37714
  };
36902
37715
  }
36903
- mkdirSync2(stagingDir, { recursive: true });
37716
+ mkdirSync3(stagingDir, { recursive: true });
36904
37717
  let sqliteVersion = "unknown";
36905
37718
  for (const src of sources) {
36906
- if (existsSync8(src.path)) {
37719
+ if (existsSync9(src.path)) {
36907
37720
  const snap = openCleoDbSnapshot(src.path, { readOnly: true });
36908
37721
  sqliteVersion = getSqliteVersion(snap.db);
36909
37722
  snap.close();
@@ -36944,15 +37757,15 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress) {
36944
37757
  };
36945
37758
  var extractNativeDb = extractNativeDb2;
36946
37759
  for (const src of sources) {
36947
- if (!existsSync8(src.path)) continue;
36948
- const backupDest = join9(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
37760
+ if (!existsSync9(src.path)) continue;
37761
+ const backupDest = join11(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
36949
37762
  const srcBytes = safeStatBytes(src.path);
36950
37763
  const skipStagingCopy = srcBytes > plan.stagingCopyThresholdBytes;
36951
37764
  if (skipStagingCopy) {
36952
37765
  onProgress?.(
36953
37766
  `Skipping full staging copy of ${src.name} (${srcBytes} bytes > ${plan.stagingCopyThresholdBytes} threshold) \u2014 source is archived, not deleted, on success.`
36954
37767
  );
36955
- } else if (!existsSync8(backupDest)) {
37768
+ } else if (!existsSync9(backupDest)) {
36956
37769
  onProgress?.(`Backing up ${src.name} \u2192 staging dir\u2026`);
36957
37770
  copyFileSync3(src.path, backupDest);
36958
37771
  backupPaths.push(backupDest);
@@ -36970,8 +37783,8 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress) {
36970
37783
  });
36971
37784
  const projectNative = extractNativeDb2(projectHandle);
36972
37785
  const globalNative = extractNativeDb2(globalHandle);
36973
- const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync8(s.path));
36974
- const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync8(s.path));
37786
+ const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync9(s.path));
37787
+ const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync9(s.path));
36975
37788
  await migrateScope(
36976
37789
  "project",
36977
37790
  projectSources,
@@ -36996,7 +37809,7 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress) {
36996
37809
  return { ok: true, tables: allTableResults, stagingDir, backupPaths };
36997
37810
  } catch (err) {
36998
37811
  const error48 = err instanceof Error ? err.message : String(err);
36999
- log4.error({ err }, "Exodus migration failed");
37812
+ log5.error({ err }, "Exodus migration failed");
37000
37813
  return { ok: false, tables: allTableResults, stagingDir, backupPaths, error: error48 };
37001
37814
  } finally {
37002
37815
  try {
@@ -37016,7 +37829,7 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37016
37829
  if (sources.length === 0) return;
37017
37830
  onProgress?.(`Migrating ${scope}-scope sources\u2026`);
37018
37831
  targetNativeDb.exec("PRAGMA foreign_keys = OFF");
37019
- log4.info({ scope }, "Exodus: foreign_keys=OFF for bulk copy (T11533 FK-defer)");
37832
+ log5.info({ scope }, "Exodus: foreign_keys=OFF for bulk copy (T11533 FK-defer)");
37020
37833
  try {
37021
37834
  for (let i = 0; i < sources.length; i++) {
37022
37835
  const src = sources[i];
@@ -37083,7 +37896,7 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37083
37896
  }
37084
37897
  } catch (err) {
37085
37898
  const msg = err instanceof Error ? err.message : String(err);
37086
- log4.warn({ tableName, sourceDb: src.name, err }, "Table copy failed \u2014 skipping");
37899
+ log5.warn({ tableName, sourceDb: src.name, err }, "Table copy failed \u2014 skipping");
37087
37900
  status = "skipped";
37088
37901
  errorMsg = msg;
37089
37902
  skipped = true;
@@ -37131,7 +37944,7 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37131
37944
  targetNativeDb.exec(`DETACH DATABASE "${attachAlias}"`);
37132
37945
  onProgress?.(` [${src.name}] Detached "${attachAlias}"`);
37133
37946
  } catch (detachErr) {
37134
- log4.warn(
37947
+ log5.warn(
37135
37948
  { attachAlias, sourceDb: src.name, err: detachErr },
37136
37949
  "DETACH failed \u2014 alias will be released on DB close"
37137
37950
  );
@@ -37141,7 +37954,7 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37141
37954
  targetNativeDb.exec(`DETACH DATABASE "${crossAlias}"`);
37142
37955
  onProgress?.(` [${src.name}] Cross-scope target detached "${crossAlias}"`);
37143
37956
  } catch (detachErr) {
37144
- log4.warn(
37957
+ log5.warn(
37145
37958
  { crossAlias, sourceDb: src.name, err: detachErr },
37146
37959
  "Cross-scope DETACH failed \u2014 alias will be released on DB close"
37147
37960
  );
@@ -37153,28 +37966,28 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37153
37966
  try {
37154
37967
  const orphans = targetNativeDb.prepare("PRAGMA foreign_key_check").all();
37155
37968
  if (orphans.length > 0) {
37156
- log4.warn(
37969
+ log5.warn(
37157
37970
  { scope, orphanCount: orphans.length, sample: orphans.slice(0, 5) },
37158
37971
  `Exodus: PRAGMA foreign_key_check found ${orphans.length} orphan row(s) after bulk copy \u2014 these are genuine data orphans (not ordering artifacts)`
37159
37972
  );
37160
37973
  } else {
37161
- log4.info({ scope }, "Exodus: PRAGMA foreign_key_check PASSED \u2014 no orphan rows");
37974
+ log5.info({ scope }, "Exodus: PRAGMA foreign_key_check PASSED \u2014 no orphan rows");
37162
37975
  }
37163
37976
  } catch (checkErr) {
37164
- log4.warn(
37977
+ log5.warn(
37165
37978
  { scope, err: checkErr },
37166
37979
  "Exodus: PRAGMA foreign_key_check failed (non-fatal) \u2014 target schema may not have FK constraints enabled"
37167
37980
  );
37168
37981
  }
37169
37982
  try {
37170
37983
  targetNativeDb.exec("PRAGMA foreign_keys = ON");
37171
- log4.info({ scope }, "Exodus: foreign_keys=ON restored after bulk copy");
37984
+ log5.info({ scope }, "Exodus: foreign_keys=ON restored after bulk copy");
37172
37985
  } catch (fkErr) {
37173
- log4.warn({ scope, err: fkErr }, "Exodus: could not restore foreign_keys=ON (non-fatal)");
37986
+ log5.warn({ scope, err: fkErr }, "Exodus: could not restore foreign_keys=ON (non-fatal)");
37174
37987
  }
37175
37988
  }
37176
37989
  }
37177
- var log4, LOCK_SENTINEL_SUFFIX, JOURNAL_FILENAME, SOURCE_EPOCH_UNITS;
37990
+ var log5, LOCK_SENTINEL_SUFFIX, JOURNAL_FILENAME, SOURCE_EPOCH_UNITS;
37178
37991
  var init_migrate = __esm({
37179
37992
  "packages/core/src/store/exodus/migrate.ts"() {
37180
37993
  "use strict";
@@ -37186,7 +37999,7 @@ var init_migrate = __esm({
37186
37999
  init_plan2();
37187
38000
  init_table_name_map();
37188
38001
  init_types();
37189
- log4 = getLogger("exodus-migrate");
38002
+ log5 = getLogger("exodus-migrate");
37190
38003
  LOCK_SENTINEL_SUFFIX = ".exodus-lock";
37191
38004
  JOURNAL_FILENAME = "exodus-journal.json";
37192
38005
  SOURCE_EPOCH_UNITS = /* @__PURE__ */ new Map([
@@ -37210,7 +38023,7 @@ function sealExodus(plan, scopeArg, cwd) {
37210
38023
  const parity = computeCountParity(plan.sources, plan.projectDbPath, plan.globalDbPath);
37211
38024
  if (!parity.ok) {
37212
38025
  const refusedReason = `Refusing to seal: ${parity.deficits.length} table(s) have FEWER rows in the consolidated cleo.db than the legacy source \u2014 the data is NOT fully migrated. Run \`cleo exodus migrate\` first. Deficits: ${parity.deficits.map((d) => `${d.targetTable}(${d.sourceCount}\u2192${d.targetCount})`).join(", ")}`;
37213
- log5.error({ deficits: parity.deficits.length }, `exodus seal refused \u2014 ${refusedReason}`);
38026
+ log6.error({ deficits: parity.deficits.length }, `exodus seal refused \u2014 ${refusedReason}`);
37214
38027
  return { ok: false, refusedReason, parity, scopes: [] };
37215
38028
  }
37216
38029
  const outcomes = [];
@@ -37226,7 +38039,7 @@ function sealExodus(plan, scopeArg, cwd) {
37226
38039
  scopeSources.map((s) => s.name),
37227
38040
  cwd
37228
38041
  );
37229
- log5.info(
38042
+ log6.info(
37230
38043
  { scope, alreadySealed, archived: archived.filter((a) => a.action === "archived").length },
37231
38044
  `exodus seal: scope '${scope}' certified (count-parity verified, ${parity.checked} tables)`
37232
38045
  );
@@ -37234,23 +38047,23 @@ function sealExodus(plan, scopeArg, cwd) {
37234
38047
  }
37235
38048
  return { ok: true, parity, scopes: outcomes };
37236
38049
  }
37237
- var log5;
38050
+ var log6;
37238
38051
  var init_seal = __esm({
37239
38052
  "packages/core/src/store/exodus/seal.ts"() {
37240
38053
  "use strict";
37241
38054
  init_logger2();
37242
38055
  init_archive2();
37243
38056
  init_count_parity();
37244
- log5 = getLogger("exodus-seal");
38057
+ log6 = getLogger("exodus-seal");
37245
38058
  }
37246
38059
  });
37247
38060
 
37248
38061
  // packages/core/src/store/exodus/status.ts
37249
- import { existsSync as existsSync9, readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync4 } from "node:fs";
37250
- import { join as join10 } from "node:path";
38062
+ import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync3, statSync as statSync4 } from "node:fs";
38063
+ import { join as join12 } from "node:path";
37251
38064
  function readJournal2(stagingDir) {
37252
- const p = join10(stagingDir, JOURNAL_FILENAME2);
37253
- if (!existsSync9(p)) return null;
38065
+ const p = join12(stagingDir, JOURNAL_FILENAME2);
38066
+ if (!existsSync10(p)) return null;
37254
38067
  try {
37255
38068
  return JSON.parse(readFileSync3(p, "utf8"));
37256
38069
  } catch {
@@ -37259,7 +38072,7 @@ function readJournal2(stagingDir) {
37259
38072
  }
37260
38073
  function findStagingDirs(cleoDir) {
37261
38074
  try {
37262
- return readdirSync3(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join10(cleoDir, e.name)).sort().reverse();
38075
+ return readdirSync4(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join12(cleoDir, e.name)).sort().reverse();
37263
38076
  } catch {
37264
38077
  return [];
37265
38078
  }
@@ -37282,15 +38095,15 @@ function runExodusStatus(cwd) {
37282
38095
  const sourcesInfo = plan.sources.map((s) => ({
37283
38096
  name: s.name,
37284
38097
  path: s.path,
37285
- exists: existsSync9(s.path),
38098
+ exists: existsSync10(s.path),
37286
38099
  bytes: safeBytes(s.path)
37287
38100
  }));
37288
38101
  return {
37289
38102
  hasStaging: latestStaging !== null,
37290
38103
  stagingDir: latestStaging,
37291
38104
  journal,
37292
- projectDbExists: existsSync9(projectDbPath),
37293
- globalDbExists: existsSync9(globalDbPath),
38105
+ projectDbExists: existsSync10(projectDbPath),
38106
+ globalDbExists: existsSync10(globalDbPath),
37294
38107
  sourcesPresent: sourcesInfo.some((s) => s.exists),
37295
38108
  sources: sourcesInfo
37296
38109
  };
@@ -37307,7 +38120,7 @@ var init_status = __esm({
37307
38120
  });
37308
38121
 
37309
38122
  // packages/core/src/store/exodus/verify-migration.ts
37310
- import { existsSync as existsSync10 } from "node:fs";
38123
+ import { existsSync as existsSync11 } from "node:fs";
37311
38124
  import { createRequire as createRequire3 } from "node:module";
37312
38125
  function orderByClause(db, tableName) {
37313
38126
  try {
@@ -37327,7 +38140,7 @@ function computeTableDigest(db, tableName, columns, transform2) {
37327
38140
  count = Number(row?.c ?? 0);
37328
38141
  } catch (err) {
37329
38142
  const msg = err instanceof Error ? err.message : String(err);
37330
- log6.warn(
38143
+ log7.warn(
37331
38144
  { tableName, err: msg },
37332
38145
  "computeTableDigest: COUNT(*) failed (possibly a virtual/FTS table) \u2014 treating as 0 rows"
37333
38146
  );
@@ -37362,7 +38175,7 @@ function computeTableDigest(db, tableName, columns, transform2) {
37362
38175
  }
37363
38176
  } catch (err) {
37364
38177
  const msg = err instanceof Error ? err.message : String(err);
37365
- log6.warn(
38178
+ log7.warn(
37366
38179
  { tableName, err: msg },
37367
38180
  "computeTableDigest: streamed SELECT failed (possibly a virtual/FTS table) \u2014 digest skipped (COUNT(*) parity still enforced)"
37368
38181
  );
@@ -37488,7 +38301,7 @@ function foreignKeyCheck(db, scope) {
37488
38301
  try {
37489
38302
  const rows = db.prepare("PRAGMA foreign_key_check").all();
37490
38303
  if (rows.length > 0) {
37491
- log6.warn(
38304
+ log7.warn(
37492
38305
  { scope, count: rows.length, sample: rows.slice(0, 5) },
37493
38306
  `verifyMigration: PRAGMA foreign_key_check found ${rows.length} orphan row(s)`
37494
38307
  );
@@ -37500,7 +38313,7 @@ function foreignKeyCheck(db, scope) {
37500
38313
  fkid: r.fkid
37501
38314
  }));
37502
38315
  } catch (err) {
37503
- log6.warn({ scope, err }, "verifyMigration: PRAGMA foreign_key_check failed (non-fatal)");
38316
+ log7.warn({ scope, err }, "verifyMigration: PRAGMA foreign_key_check failed (non-fatal)");
37504
38317
  return [];
37505
38318
  }
37506
38319
  }
@@ -37537,13 +38350,13 @@ function sourceOrphanSignatures(db, sourceName, scope) {
37537
38350
  const rows = db.prepare("PRAGMA foreign_key_check").all();
37538
38351
  for (const r of rows) sigs.add(orphanSignature(db, r, sourceName));
37539
38352
  if (rows.length > 0) {
37540
- log6.warn(
38353
+ log7.warn(
37541
38354
  { scope, count: rows.length, sample: rows.slice(0, 5) },
37542
38355
  `verifyMigration: source already has ${rows.length} pre-existing FK orphan(s) \u2014 these are tolerated (carried forward losslessly, flagged for data-hygiene)`
37543
38356
  );
37544
38357
  }
37545
38358
  } catch (err) {
37546
- log6.warn({ scope, err }, "verifyMigration: source PRAGMA foreign_key_check failed (non-fatal)");
38359
+ log7.warn({ scope, err }, "verifyMigration: source PRAGMA foreign_key_check failed (non-fatal)");
37547
38360
  }
37548
38361
  return sigs;
37549
38362
  }
@@ -37555,7 +38368,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37555
38368
  const preExistingForeignKeyViolations = [];
37556
38369
  const failureLines = [];
37557
38370
  const sourceOrphanSigs = /* @__PURE__ */ new Set();
37558
- if (!existsSync10(projectDbPath)) {
38371
+ if (!existsSync11(projectDbPath)) {
37559
38372
  return {
37560
38373
  ok: false,
37561
38374
  tables: [],
@@ -37566,7 +38379,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37566
38379
  error: `Consolidated project cleo.db not found at ${projectDbPath}. Run 'cleo exodus migrate' first.`
37567
38380
  };
37568
38381
  }
37569
- if (!existsSync10(globalDbPath)) {
38382
+ if (!existsSync11(globalDbPath)) {
37570
38383
  return {
37571
38384
  ok: false,
37572
38385
  tables: [],
@@ -37581,7 +38394,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37581
38394
  const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
37582
38395
  try {
37583
38396
  for (const src of sources) {
37584
- if (!existsSync10(src.path)) {
38397
+ if (!existsSync11(src.path)) {
37585
38398
  onProgress?.(`Skipping ${src.name} (not present)`);
37586
38399
  continue;
37587
38400
  }
@@ -37666,7 +38479,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37666
38479
  `[${scope}] ${src.name}.${legacyTableName} \u2192 ${targetTableName}: DEFICIT \u2014 source=${srcDigest.count} rows, target=${tgtDigest.count} rows (${srcDigest.count - tgtDigest.count} missing), hashMatch=${hashMatch}`
37667
38480
  );
37668
38481
  } else if (tgtDigest.count > srcDigest.count) {
37669
- log6.warn(
38482
+ log7.warn(
37670
38483
  {
37671
38484
  scope,
37672
38485
  source: src.name,
@@ -37716,7 +38529,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37716
38529
  }
37717
38530
  }
37718
38531
  if (preExistingForeignKeyViolations.length > 0) {
37719
- log6.warn(
38532
+ log7.warn(
37720
38533
  {
37721
38534
  count: preExistingForeignKeyViolations.length,
37722
38535
  sample: preExistingForeignKeyViolations.slice(0, 5)
@@ -37726,7 +38539,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37726
38539
  }
37727
38540
  } catch (err) {
37728
38541
  const error48 = err instanceof Error ? err.message : String(err);
37729
- log6.error({ err }, "verifyMigration failed");
38542
+ log7.error({ err }, "verifyMigration failed");
37730
38543
  return {
37731
38544
  ok: false,
37732
38545
  tables,
@@ -37743,7 +38556,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37743
38556
  if (failureLines.length > 0) {
37744
38557
  const error48 = `verifyMigration FAILED: ${failureLines.length} issue(s):
37745
38558
  ${failureLines.map((l) => ` \u2022 ${l}`).join("\n")}`;
37746
- log6.error({ failureCount: failureLines.length }, error48);
38559
+ log7.error({ failureCount: failureLines.length }, error48);
37747
38560
  return {
37748
38561
  ok: false,
37749
38562
  tables,
@@ -37763,7 +38576,7 @@ ${failureLines.map((l) => ` \u2022 ${l}`).join("\n")}`;
37763
38576
  enumDrift
37764
38577
  };
37765
38578
  }
37766
- var log6, _require, CHECK_ENUM_REGEX;
38579
+ var log7, _require, CHECK_ENUM_REGEX;
37767
38580
  var init_verify_migration = __esm({
37768
38581
  "packages/core/src/store/exodus/verify-migration.ts"() {
37769
38582
  "use strict";
@@ -37772,7 +38585,7 @@ var init_verify_migration = __esm({
37772
38585
  init_open_cleo_db();
37773
38586
  init_column_transforms();
37774
38587
  init_table_name_map();
37775
- log6 = getLogger("verify-migration");
38588
+ log7 = getLogger("verify-migration");
37776
38589
  _require = createRequire3(import.meta.url);
37777
38590
  CHECK_ENUM_REGEX = /CHECK\s*\(\s*"([^"]+)"\s+(?:IS\s+NULL\s+OR\s+"[^"]+"\s+)?IN\s*\(([^)]*)\)\s*\)/gi;
37778
38591
  }
@@ -37864,7 +38677,7 @@ __export(on_open_exports, {
37864
38677
  isDataContinuityOk: () => isDataContinuityOk,
37865
38678
  maybeRunExodusOnOpen: () => maybeRunExodusOnOpen
37866
38679
  });
37867
- import { existsSync as existsSync11 } from "node:fs";
38680
+ import { existsSync as existsSync12 } from "node:fs";
37868
38681
  function isDisabledByEnv() {
37869
38682
  const v = process.env.CLEO_DISABLE_EXODUS_ON_OPEN;
37870
38683
  return v === "1" || v === "true";
@@ -37890,7 +38703,7 @@ function rollbackConsolidatedToEmpty(nativeDb, scope) {
37890
38703
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%'"
37891
38704
  ).all().map((r) => r.name);
37892
38705
  } catch (err) {
37893
- log7.error({ err, scope }, "exodus-on-open: failed to enumerate tables for rollback");
38706
+ log8.error({ err, scope }, "exodus-on-open: failed to enumerate tables for rollback");
37894
38707
  return;
37895
38708
  }
37896
38709
  try {
@@ -37900,7 +38713,7 @@ function rollbackConsolidatedToEmpty(nativeDb, scope) {
37900
38713
  try {
37901
38714
  nativeDb.exec(`DELETE FROM "${table}"`);
37902
38715
  } catch (err) {
37903
- log7.warn({ err, table, scope }, "exodus-on-open: failed to clear table during rollback");
38716
+ log8.warn({ err, table, scope }, "exodus-on-open: failed to clear table during rollback");
37904
38717
  }
37905
38718
  }
37906
38719
  nativeDb.exec("COMMIT");
@@ -37909,7 +38722,7 @@ function rollbackConsolidatedToEmpty(nativeDb, scope) {
37909
38722
  nativeDb.exec("ROLLBACK");
37910
38723
  } catch {
37911
38724
  }
37912
- log7.error({ err, scope }, "exodus-on-open: rollback transaction failed");
38725
+ log8.error({ err, scope }, "exodus-on-open: rollback transaction failed");
37913
38726
  } finally {
37914
38727
  try {
37915
38728
  nativeDb.exec("PRAGMA foreign_keys = ON");
@@ -37929,7 +38742,7 @@ async function rollbackBothScopes(scope, projectDbPath, globalDbPath) {
37929
38742
  rollbackConsolidatedToEmpty(native, s);
37930
38743
  }
37931
38744
  } catch (err) {
37932
- log7.warn(
38745
+ log8.warn(
37933
38746
  { err, scope: s, openingScope: scope },
37934
38747
  "exodus-on-open: could not roll back scope (best-effort)"
37935
38748
  );
@@ -37945,7 +38758,7 @@ function isDataContinuityOk(result) {
37945
38758
  const deficits = result.tables.filter((t) => t.targetCount < t.sourceCount);
37946
38759
  const surpluses = result.tables.filter((t) => t.targetCount > t.sourceCount);
37947
38760
  if (surpluses.length > 0) {
37948
- log7.warn(
38761
+ log8.warn(
37949
38762
  {
37950
38763
  surpluses: surpluses.map((t) => ({
37951
38764
  table: t.targetTable,
@@ -37979,7 +38792,7 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
37979
38792
  const { buildExodusPlan: buildExodusPlan2, runExodusMigrate: runExodusMigrate2, verifyMigration: verifyMigration2, clearExodusJournal: clearExodusJournal2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
37980
38793
  const plan = buildExodusPlan2(cwd);
37981
38794
  const scopeSources = plan.sources.filter((s) => s.targetScope === scope);
37982
- if (!scopeSources.some((s) => existsSync11(s.path))) {
38795
+ if (!scopeSources.some((s) => existsSync12(s.path))) {
37983
38796
  return {
37984
38797
  outcome: "skipped",
37985
38798
  reason: `no legacy ${scope}-scope source DBs present (fresh install or cross-scope-only)`
@@ -37992,11 +38805,11 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
37992
38805
  if (!consolidatedIsEmpty(nativeDb, scope)) {
37993
38806
  return { outcome: "skipped", reason: "migrated by a concurrent process (lock winner)" };
37994
38807
  }
37995
- log7.info(
38808
+ log8.info(
37996
38809
  {
37997
38810
  scope,
37998
38811
  dbPath,
37999
- sources: plan.sources.filter((s) => existsSync11(s.path)).map((s) => s.name)
38812
+ sources: plan.sources.filter((s) => existsSync12(s.path)).map((s) => s.name)
38000
38813
  },
38001
38814
  "exodus-on-open: consolidated cleo.db is empty and legacy data present \u2014 auto-migrating"
38002
38815
  );
@@ -38005,23 +38818,23 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38005
38818
  const migrateResult = await runExodusMigrate2(
38006
38819
  plan,
38007
38820
  false,
38008
- (msg) => log7.debug({ scope }, `exodus-on-open: ${msg}`)
38821
+ (msg) => log8.debug({ scope }, `exodus-on-open: ${msg}`)
38009
38822
  );
38010
38823
  if (!migrateResult.ok) {
38011
38824
  await rollbackBothScopes(scope, plan.projectDbPath, plan.globalDbPath);
38012
38825
  clearExodusJournal2(migrateResult.stagingDir);
38013
38826
  const reason = `migration failed: ${migrateResult.error ?? "unknown error"} \u2014 legacy DBs kept as source`;
38014
- log7.error({ scope, error: migrateResult.error }, `exodus-on-open: ${reason}`);
38827
+ log8.error({ scope, error: migrateResult.error }, `exodus-on-open: ${reason}`);
38015
38828
  return { outcome: "aborted", reason };
38016
38829
  }
38017
38830
  const verifyResult = verifyMigration2(
38018
38831
  plan.sources,
38019
38832
  plan.projectDbPath,
38020
38833
  plan.globalDbPath,
38021
- (msg) => log7.debug({ scope }, `exodus-on-open verify: ${msg}`)
38834
+ (msg) => log8.debug({ scope }, `exodus-on-open verify: ${msg}`)
38022
38835
  );
38023
38836
  if (!verifyResult.ok) {
38024
- log7.warn(
38837
+ log8.warn(
38025
38838
  {
38026
38839
  scope,
38027
38840
  enumDrift: verifyResult.enumDrift.length,
@@ -38035,7 +38848,7 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38035
38848
  clearExodusJournal2(plan.stagingDir);
38036
38849
  const deficits = verifyResult.tables.filter((t) => t.targetCount < t.sourceCount).map((t) => `${t.targetTable}(${t.sourceCount}\u2192${t.targetCount})`);
38037
38850
  const reason = `parity verification failed \u2014 cutover aborted, legacy DBs kept as source. count deficits: [${deficits.join(", ")}]; INTRODUCED fk orphans: ${verifyResult.introducedForeignKeyViolations.length} (pre-existing source orphans tolerated: ${verifyResult.preExistingForeignKeyViolations.length}). ` + `${verifyResult.error ?? ""}`.trim();
38038
- log7.error(
38851
+ log8.error(
38039
38852
  {
38040
38853
  scope,
38041
38854
  countDeficits: deficits,
@@ -38047,14 +38860,14 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38047
38860
  return { outcome: "aborted", reason };
38048
38861
  }
38049
38862
  const rowsCopied = migrateResult.tables.filter((t) => !t.skipped).reduce((n, t) => n + t.rowsCopied, 0);
38050
- log7.info(
38863
+ log8.info(
38051
38864
  { scope, rowsCopied, tables: migrateResult.tables.length },
38052
38865
  "exodus-on-open: parity verified \u2014 legacy data migrated into consolidated cleo.db"
38053
38866
  );
38054
38867
  try {
38055
- const consumed = plan.sources.filter((s) => existsSync11(s.path));
38868
+ const consumed = plan.sources.filter((s) => existsSync12(s.path));
38056
38869
  const archiveResult = archiveMigratedSources(consumed, cwd);
38057
- log7.info(
38870
+ log8.info(
38058
38871
  {
38059
38872
  scope,
38060
38873
  archived: archiveResult.sources.filter((s) => s.action === "archived").length,
@@ -38063,7 +38876,7 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38063
38876
  "exodus-on-open: archived legacy sources + sealed completion marker(s)"
38064
38877
  );
38065
38878
  } catch (err) {
38066
- log7.error(
38879
+ log8.error(
38067
38880
  { err, scope },
38068
38881
  "exodus-on-open: post-migration archive/marker step failed (migration itself succeeded \u2014 legacy DBs left in place, will be re-checked by `cleo doctor exodus-residue`)"
38069
38882
  );
@@ -38085,14 +38898,14 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38085
38898
  function _isExodusInProgress() {
38086
38899
  return _exodusInProgress;
38087
38900
  }
38088
- var log7, _exodusInProgress;
38901
+ var log8, _exodusInProgress;
38089
38902
  var init_on_open = __esm({
38090
38903
  "packages/core/src/store/exodus/on-open.ts"() {
38091
38904
  "use strict";
38092
38905
  init_logger2();
38093
38906
  init_lock();
38094
38907
  init_archive2();
38095
- log7 = getLogger("exodus-on-open");
38908
+ log8 = getLogger("exodus-on-open");
38096
38909
  _exodusInProgress = false;
38097
38910
  }
38098
38911
  });
@@ -38109,9 +38922,9 @@ __export(dual_scope_db_exports, {
38109
38922
  resolveDualScopeDbPath: () => resolveDualScopeDbPath,
38110
38923
  upsertIdempotent: () => upsertIdempotent
38111
38924
  });
38112
- import { existsSync as existsSync12, mkdirSync as mkdirSync3 } from "node:fs";
38925
+ import { existsSync as existsSync13, mkdirSync as mkdirSync4 } from "node:fs";
38113
38926
  import { createRequire as createRequire4 } from "node:module";
38114
- import { dirname as dirname5, join as join11 } from "node:path";
38927
+ import { dirname as dirname5, join as join13 } from "node:path";
38115
38928
  function assertWriteDurable(handle) {
38116
38929
  if (handle.exodusAbort) {
38117
38930
  throw new ExodusAbortWriteUnsafeError(handle.exodusAbort);
@@ -38128,9 +38941,9 @@ function cacheKey(scope, dbPath) {
38128
38941
  }
38129
38942
  function resolveDualScopeDbPath(scope, cwd) {
38130
38943
  if (scope === "project") {
38131
- return join11(resolveCleoDir(cwd), "cleo.db");
38944
+ return join13(resolveCleoDir(cwd), "cleo.db");
38132
38945
  }
38133
- return join11(getCleoHome(), "cleo.db");
38946
+ return join13(getCleoHome(), "cleo.db");
38134
38947
  }
38135
38948
  function migrationsSetName(scope) {
38136
38949
  return scope === "project" ? "drizzle-cleo-project" : "drizzle-cleo-global";
@@ -38173,11 +38986,11 @@ async function openDualScopeDb(scope, cwd) {
38173
38986
  const dbPath = resolveDualScopeDbPath(scope, cwd);
38174
38987
  return scope === "project" ? openDualScopeDbAtPath("project", dbPath, cwd) : openDualScopeDbAtPath("global", dbPath, cwd);
38175
38988
  }
38176
- async function openDedicatedDualScopeDb(scope, dbPath, log8) {
38177
- log8.debug({ scope, dbPath }, "opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)");
38989
+ async function openDedicatedDualScopeDb(scope, dbPath, log9) {
38990
+ log9.debug({ scope, dbPath }, "opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)");
38178
38991
  const dir = dirname5(dbPath);
38179
- if (!existsSync12(dir)) {
38180
- mkdirSync3(dir, { recursive: true });
38992
+ if (!existsSync13(dir)) {
38993
+ mkdirSync4(dir, { recursive: true });
38181
38994
  }
38182
38995
  const DatabaseSyncCtor = getDatabaseSyncCtor();
38183
38996
  const nativeDb = new DatabaseSyncCtor(dbPath, { allowExtension: true });
@@ -38200,7 +39013,7 @@ async function openDedicatedDualScopeDb(scope, dbPath, log8) {
38200
39013
  existenceTable(scope),
38201
39014
  `dual-scope-db[${scope}]`
38202
39015
  );
38203
- log8.debug({ scope, dbPath }, "DEDICATED dual-scope cleo.db ready (T11782 FIX D)");
39016
+ log9.debug({ scope, dbPath }, "DEDICATED dual-scope cleo.db ready (T11782 FIX D)");
38204
39017
  return {
38205
39018
  db,
38206
39019
  scope,
@@ -38225,15 +39038,15 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38225
39038
  return existing.handle;
38226
39039
  }
38227
39040
  }
38228
- const log8 = getLogger("dual-scope-db");
39041
+ const log9 = getLogger("dual-scope-db");
38229
39042
  if (dedicated) {
38230
- return openDedicatedDualScopeDb(scope, dbPath, log8);
39043
+ return openDedicatedDualScopeDb(scope, dbPath, log9);
38231
39044
  }
38232
39045
  const initPromise = (async () => {
38233
- log8.debug({ scope, dbPath }, "opening dual-scope cleo.db");
39046
+ log9.debug({ scope, dbPath }, "opening dual-scope cleo.db");
38234
39047
  const dir = dirname5(dbPath);
38235
- if (!existsSync12(dir)) {
38236
- mkdirSync3(dir, { recursive: true });
39048
+ if (!existsSync13(dir)) {
39049
+ mkdirSync4(dir, { recursive: true });
38237
39050
  }
38238
39051
  const DatabaseSyncCtor = getDatabaseSyncCtor();
38239
39052
  const nativeDb = new DatabaseSyncCtor(dbPath, { allowExtension: true });
@@ -38260,7 +39073,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38260
39073
  existenceTable(scope),
38261
39074
  `dual-scope-db[${scope}]`
38262
39075
  );
38263
- log8.debug({ scope, dbPath }, "dual-scope cleo.db ready");
39076
+ log9.debug({ scope, dbPath }, "dual-scope cleo.db ready");
38264
39077
  const built = {
38265
39078
  db,
38266
39079
  scope,
@@ -38286,6 +39099,25 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38286
39099
  { dbPath }
38287
39100
  );
38288
39101
  if (exodusCwd !== void 0 && dbPath === resolveDualScopeDbPath(scope, exodusCwd)) {
39102
+ let releaseDbHeavy = null;
39103
+ let dbHeavyDeferred = false;
39104
+ try {
39105
+ const { governor: governor2 } = await Promise.resolve().then(() => (init_governor(), governor_exports));
39106
+ const admit = await governor2.tryAcquire("db-heavy");
39107
+ if (admit.deferred) {
39108
+ dbHeavyDeferred = true;
39109
+ } else {
39110
+ releaseDbHeavy = admit.release;
39111
+ }
39112
+ } catch {
39113
+ }
39114
+ if (dbHeavyDeferred) {
39115
+ log9.debug(
39116
+ { scope, dbPath },
39117
+ "exodus-on-open skipped this open \u2014 db-heavy deferred under memory pressure (re-runs idempotently on a calmer open)"
39118
+ );
39119
+ return handle;
39120
+ }
38289
39121
  try {
38290
39122
  const { maybeRunExodusOnOpen: maybeRunExodusOnOpen2 } = await Promise.resolve().then(() => (init_on_open(), on_open_exports));
38291
39123
  const result = await maybeRunExodusOnOpen2(scope, dbPath, nativeDb, exodusCwd);
@@ -38298,7 +39130,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38298
39130
  reason: result.reason,
38299
39131
  at: Date.now()
38300
39132
  };
38301
- log8.warn(
39133
+ log9.warn(
38302
39134
  { scope, reason: result.reason },
38303
39135
  "exodus-on-open aborted; consolidated cleo.db left empty, legacy kept as source \u2014 mutating callers must check handle.exodusAbort / call assertWriteDurable (T11828)"
38304
39136
  );
@@ -38311,11 +39143,14 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38311
39143
  return reopened;
38312
39144
  }
38313
39145
  } catch (err) {
38314
- log8.warn(
39146
+ log9.warn(
38315
39147
  { err, scope },
38316
39148
  "exodus-on-open hook failed (non-fatal); re-opening consolidated handle"
38317
39149
  );
38318
39150
  return scope === "project" ? openDualScopeDbAtPath("project", dbPath) : openDualScopeDbAtPath("global", dbPath);
39151
+ } finally {
39152
+ if (releaseDbHeavy) await releaseDbHeavy().catch(() => {
39153
+ });
38319
39154
  }
38320
39155
  }
38321
39156
  return handle;
@@ -38938,8 +39773,8 @@ __export(nexus_sqlite_exports, {
38938
39773
  resetNexusDbState: () => resetNexusDbState,
38939
39774
  resolveNexusMigrationsFolder: () => resolveNexusMigrationsFolder
38940
39775
  });
38941
- import { copyFileSync as copyFileSync4, existsSync as existsSync13 } from "node:fs";
38942
- import { join as join12 } from "node:path";
39776
+ import { copyFileSync as copyFileSync4, existsSync as existsSync14 } from "node:fs";
39777
+ import { join as join14 } from "node:path";
38943
39778
  function getNexusDbPath(cwd) {
38944
39779
  return resolveDualScopeDbPath("project", cwd);
38945
39780
  }
@@ -38971,7 +39806,7 @@ function resolveNexusMigrationsFolder() {
38971
39806
  return resolveCorePackageMigrationsFolder("drizzle-nexus");
38972
39807
  }
38973
39808
  function getNestedNexusSentinelPath() {
38974
- return join12(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
39809
+ return join14(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
38975
39810
  }
38976
39811
  function detectAndWarnOnNestedNexus() {
38977
39812
  let nestedPath;
@@ -38980,12 +39815,12 @@ function detectAndWarnOnNestedNexus() {
38980
39815
  } catch {
38981
39816
  return false;
38982
39817
  }
38983
- if (!existsSync13(nestedPath)) return false;
39818
+ if (!existsSync14(nestedPath)) return false;
38984
39819
  if (_warnedNestedPaths.has(nestedPath)) return false;
38985
39820
  _warnedNestedPaths.add(nestedPath);
38986
39821
  const canonicalPath = getNexusDbPath();
38987
- const log8 = getLogger("nexus-sqlite");
38988
- log8.warn(
39822
+ const log9 = getLogger("nexus-sqlite");
39823
+ log9.warn(
38989
39824
  {
38990
39825
  nestedPath,
38991
39826
  canonicalPath,
@@ -39139,7 +39974,7 @@ function runNexusMigrations(nativeDb, db) {
39139
39974
  const migrationsFolder = resolveNexusMigrationsFolder();
39140
39975
  if (tableExists4(nativeDb, "nexus_nodes") && _nexusDbPath) {
39141
39976
  const backupPath = _nexusDbPath.replace(/\.db$/, "-pre-cleo.db.bak");
39142
- if (!existsSync13(backupPath)) {
39977
+ if (!existsSync14(backupPath)) {
39143
39978
  try {
39144
39979
  copyFileSync4(_nexusDbPath, backupPath);
39145
39980
  } catch {
@@ -39277,10 +40112,10 @@ var init_nexus_sqlite = __esm({
39277
40112
 
39278
40113
  // packages/core/src/paths.ts
39279
40114
  import { AsyncLocalStorage } from "node:async_hooks";
39280
- import { existsSync as existsSync14, readFileSync as readFileSync4, statSync as statSync5 } from "node:fs";
40115
+ import { existsSync as existsSync15, readFileSync as readFileSync4, statSync as statSync5 } from "node:fs";
39281
40116
  import { createRequire as createRequire5 } from "node:module";
39282
40117
  import { homedir } from "node:os";
39283
- import { basename as basename4, dirname as dirname6, join as join13, resolve as resolve3 } from "node:path";
40118
+ import { basename as basename4, dirname as dirname6, join as join15, resolve as resolve3 } from "node:path";
39284
40119
  import {
39285
40120
  computeCanonicalProjectId as _computeCanonicalProjectId,
39286
40121
  getCanonicalTemplatesTildePath as _getCanonicalTemplatesTildePath,
@@ -39370,8 +40205,8 @@ function getCleoDirAbsolute(cwd, opts) {
39370
40205
  function _resolveProjectByCwdFromNexus(cwd) {
39371
40206
  try {
39372
40207
  const cleoHome = getCleoHome();
39373
- const globalDbPath = join13(cleoHome, "cleo.db");
39374
- if (!existsSync14(globalDbPath)) return null;
40208
+ const globalDbPath = join15(cleoHome, "cleo.db");
40209
+ if (!existsSync15(globalDbPath)) return null;
39375
40210
  const start = resolve3(cwd ?? process.cwd());
39376
40211
  let current = start;
39377
40212
  const DatabaseSync2 = _getDatabaseSyncCtor();
@@ -39410,7 +40245,7 @@ function _findCleoDirRoot(cwd) {
39410
40245
  const isDangerousRoot = current === homeRoot || current === "/" || current === "";
39411
40246
  if (!isDangerousRoot) {
39412
40247
  try {
39413
- if (statSync5(join13(current, ".cleo")).isDirectory()) {
40248
+ if (statSync5(join15(current, ".cleo")).isDirectory()) {
39414
40249
  return current;
39415
40250
  }
39416
40251
  } catch {
@@ -39425,7 +40260,7 @@ function _findCleoDirRoot(cwd) {
39425
40260
  function resolveCleoDir(cwd) {
39426
40261
  const scope = worktreeScope.getStore();
39427
40262
  if (scope !== void 0) {
39428
- return join13(scope.worktreeRoot, ".cleo");
40263
+ return join15(scope.worktreeRoot, ".cleo");
39429
40264
  }
39430
40265
  const override = _cleoDirEnvOverride();
39431
40266
  if (override !== null) {
@@ -39433,14 +40268,14 @@ function resolveCleoDir(cwd) {
39433
40268
  }
39434
40269
  const root = _findCleoDirRoot(cwd);
39435
40270
  if (root !== null) {
39436
- return join13(root, ".cleo");
40271
+ return join15(root, ".cleo");
39437
40272
  }
39438
40273
  const start = resolve3(cwd ?? process.cwd());
39439
40274
  let current = start;
39440
40275
  while (true) {
39441
40276
  const mainRepo = _resolveMainRepoFromGitlink(current);
39442
40277
  if (mainRepo !== null) {
39443
- return join13(mainRepo, ".cleo");
40278
+ return join15(mainRepo, ".cleo");
39444
40279
  }
39445
40280
  const parent = dirname6(current);
39446
40281
  if (parent === current) {
@@ -39482,9 +40317,9 @@ function _cwdHasGitAncestor(cwd) {
39482
40317
  const start = resolve3(cwd ?? process.cwd());
39483
40318
  let current = start;
39484
40319
  while (true) {
39485
- const gitMarker = join13(current, ".git");
40320
+ const gitMarker = join15(current, ".git");
39486
40321
  try {
39487
- if (existsSync14(gitMarker)) {
40322
+ if (existsSync15(gitMarker)) {
39488
40323
  return true;
39489
40324
  }
39490
40325
  } catch {
@@ -39496,16 +40331,16 @@ function _cwdHasGitAncestor(cwd) {
39496
40331
  }
39497
40332
  function _resolveMainRepoFromGitlink(gitlinkDir) {
39498
40333
  try {
39499
- const gitLinkPath = join13(gitlinkDir, ".git");
39500
- if (!existsSync14(gitLinkPath)) return null;
39501
- const stat2 = statSync5(gitLinkPath);
39502
- if (!stat2.isFile()) return null;
40334
+ const gitLinkPath = join15(gitlinkDir, ".git");
40335
+ if (!existsSync15(gitLinkPath)) return null;
40336
+ const stat3 = statSync5(gitLinkPath);
40337
+ if (!stat3.isFile()) return null;
39503
40338
  const gitLinkContent = readFileSync4(gitLinkPath, "utf-8").trim();
39504
40339
  const match = gitLinkContent.match(/^gitdir:\s*(.+)$/m);
39505
40340
  if (!match) return null;
39506
40341
  const gitdir = match[1].trim();
39507
40342
  const mainRepo = dirname6(dirname6(dirname6(gitdir)));
39508
- if (existsSync14(join13(mainRepo, ".cleo")) && validateProjectRoot(mainRepo)) {
40343
+ if (existsSync15(join15(mainRepo, ".cleo")) && validateProjectRoot(mainRepo)) {
39509
40344
  return mainRepo;
39510
40345
  }
39511
40346
  } catch {
@@ -39513,18 +40348,18 @@ function _resolveMainRepoFromGitlink(gitlinkDir) {
39513
40348
  return null;
39514
40349
  }
39515
40350
  function validateProjectRoot(candidate) {
39516
- const cleoDir = join13(candidate, ".cleo");
39517
- if (!existsSync14(cleoDir)) {
40351
+ const cleoDir = join15(candidate, ".cleo");
40352
+ if (!existsSync15(cleoDir)) {
39518
40353
  return false;
39519
40354
  }
39520
- const projectInfoPath = join13(cleoDir, "project-info.json");
39521
- if (existsSync14(projectInfoPath)) {
40355
+ const projectInfoPath = join15(cleoDir, "project-info.json");
40356
+ if (existsSync15(projectInfoPath)) {
39522
40357
  try {
39523
40358
  const raw = readFileSync4(projectInfoPath, "utf-8");
39524
40359
  const parsed = JSON.parse(raw);
39525
40360
  if (typeof parsed === "object" && parsed !== null && "projectId" in parsed && typeof parsed["projectId"] === "string" && parsed["projectId"] !== "") {
39526
- const gitMarker = join13(candidate, ".git");
39527
- if (existsSync14(gitMarker)) {
40361
+ const gitMarker = join15(candidate, ".git");
40362
+ if (existsSync15(gitMarker)) {
39528
40363
  try {
39529
40364
  if (!statSync5(gitMarker).isDirectory()) {
39530
40365
  return false;
@@ -39538,12 +40373,12 @@ function validateProjectRoot(candidate) {
39538
40373
  } catch {
39539
40374
  }
39540
40375
  }
39541
- const gitDir = join13(candidate, ".git");
39542
- if (existsSync14(gitDir)) {
40376
+ const gitDir = join15(candidate, ".git");
40377
+ if (existsSync15(gitDir)) {
39543
40378
  let isRealGitDir = false;
39544
40379
  try {
39545
- const stat2 = statSync5(gitDir);
39546
- isRealGitDir = stat2.isDirectory();
40380
+ const stat3 = statSync5(gitDir);
40381
+ isRealGitDir = stat3.isDirectory();
39547
40382
  } catch {
39548
40383
  isRealGitDir = false;
39549
40384
  }
@@ -39586,16 +40421,16 @@ function getProjectRoot(cwd) {
39586
40421
  const homeRoot = homedir();
39587
40422
  const skippedCleoDirs = [];
39588
40423
  while (true) {
39589
- const cleoDir = join13(current, ".cleo");
39590
- const gitDir = join13(current, ".git");
40424
+ const cleoDir = join15(current, ".cleo");
40425
+ const gitDir = join15(current, ".git");
39591
40426
  const isDangerousRoot = current === homeRoot || current === "/" || current === "";
39592
- if (existsSync14(cleoDir) && !isDangerousRoot) {
40427
+ if (existsSync15(cleoDir) && !isDangerousRoot) {
39593
40428
  if (validateProjectRoot(current)) {
39594
40429
  return current;
39595
40430
  }
39596
40431
  skippedCleoDirs.push(current);
39597
40432
  }
39598
- if (existsSync14(gitDir) && !isDangerousRoot) {
40433
+ if (existsSync15(gitDir) && !isDangerousRoot) {
39599
40434
  let isRealGitDir = false;
39600
40435
  try {
39601
40436
  isRealGitDir = statSync5(gitDir).isDirectory();
@@ -39640,18 +40475,18 @@ function resolveOrCwd(maybeRoot) {
39640
40475
  return getProjectRoot();
39641
40476
  }
39642
40477
  function getConfigPath(cwd) {
39643
- return join13(_resolveCleoDir(cwd), "config.json");
40478
+ return join15(_resolveCleoDir(cwd), "config.json");
39644
40479
  }
39645
40480
  function getGlobalConfigPath() {
39646
- return join13(getCleoHome(), "config.json");
40481
+ return join15(getCleoHome(), "config.json");
39647
40482
  }
39648
40483
  function isAbsolutePath(path) {
39649
40484
  return _isAbsolutePath(path);
39650
40485
  }
39651
40486
  function _readProjectNameFromInfo(projectRoot) {
39652
40487
  try {
39653
- const infoPath = join13(projectRoot, ".cleo", "project-info.json");
39654
- if (!existsSync14(infoPath)) return void 0;
40488
+ const infoPath = join15(projectRoot, ".cleo", "project-info.json");
40489
+ if (!existsSync15(infoPath)) return void 0;
39655
40490
  const raw = readFileSync4(infoPath, "utf-8");
39656
40491
  const data = JSON.parse(raw);
39657
40492
  return typeof data.name === "string" && data.name.length > 0 ? data.name : void 0;
@@ -39677,8 +40512,8 @@ async function registerProjectOnEncounter(projectRoot, infoProjectId) {
39677
40512
  if (existingRows.length > 0) {
39678
40513
  const existingPath = existingRows[0].projectPath;
39679
40514
  if (existingPath !== resolvedPath) {
39680
- const newBrainDbPath = join13(resolvedPath, ".cleo", "brain.db");
39681
- const newTasksDbPath = join13(resolvedPath, ".cleo", "tasks.db");
40515
+ const newBrainDbPath = join15(resolvedPath, ".cleo", "brain.db");
40516
+ const newTasksDbPath = join15(resolvedPath, ".cleo", "tasks.db");
39682
40517
  await db.update(projectRegistry2).set({
39683
40518
  projectPath: resolvedPath,
39684
40519
  projectHash: generateProjectHash2(resolvedPath),
@@ -39709,8 +40544,8 @@ async function registerProjectOnEncounter(projectRoot, infoProjectId) {
39709
40544
  lastSync: now,
39710
40545
  taskCount: 0,
39711
40546
  labelsJson: "[]",
39712
- brainDbPath: join13(resolvedPath, ".cleo", "brain.db"),
39713
- tasksDbPath: join13(resolvedPath, ".cleo", "tasks.db"),
40547
+ brainDbPath: join15(resolvedPath, ".cleo", "brain.db"),
40548
+ tasksDbPath: join15(resolvedPath, ".cleo", "tasks.db"),
39714
40549
  statsJson: "{}"
39715
40550
  }).onConflictDoNothing();
39716
40551
  const aliases = canonicalResult.legacyAliases ?? [];
@@ -39743,46 +40578,46 @@ var init_paths = __esm({
39743
40578
  // packages/core/src/store/file-utils.ts
39744
40579
  import { randomBytes } from "node:crypto";
39745
40580
  import {
39746
- existsSync as existsSync15,
39747
- mkdirSync as mkdirSync4,
39748
- readdirSync as readdirSync4,
40581
+ existsSync as existsSync16,
40582
+ mkdirSync as mkdirSync5,
40583
+ readdirSync as readdirSync5,
39749
40584
  readFileSync as readFileSync5,
39750
40585
  renameSync as renameSync3,
39751
40586
  unlinkSync as unlinkSync3,
39752
- writeFileSync as writeFileSync3
40587
+ writeFileSync as writeFileSync4
39753
40588
  } from "node:fs";
39754
- import { basename as basename5, dirname as dirname7, join as join14 } from "node:path";
39755
- import * as lockfile2 from "proper-lockfile";
40589
+ import { basename as basename5, dirname as dirname7, join as join16 } from "node:path";
40590
+ import * as lockfile3 from "proper-lockfile";
39756
40591
  function rotateBackup(filePath, mode) {
39757
40592
  const dir = dirname7(filePath);
39758
40593
  const name15 = basename5(filePath);
39759
- const backupDir = join14(dir, ".backups");
40594
+ const backupDir = join16(dir, ".backups");
39760
40595
  const dirMode = typeof mode === "number" ? modeToDirMode(mode) : void 0;
39761
- if (!existsSync15(backupDir)) {
39762
- mkdirSync4(backupDir, { recursive: true, mode: dirMode });
40596
+ if (!existsSync16(backupDir)) {
40597
+ mkdirSync5(backupDir, { recursive: true, mode: dirMode });
39763
40598
  }
39764
40599
  for (let i = MAX_BACKUPS; i >= 1; i--) {
39765
- const current = join14(backupDir, `${name15}.${i}`);
40600
+ const current = join16(backupDir, `${name15}.${i}`);
39766
40601
  if (i === MAX_BACKUPS) {
39767
40602
  try {
39768
40603
  unlinkSync3(current);
39769
40604
  } catch {
39770
40605
  }
39771
40606
  } else {
39772
- const next = join14(backupDir, `${name15}.${i + 1}`);
40607
+ const next = join16(backupDir, `${name15}.${i + 1}`);
39773
40608
  try {
39774
- if (existsSync15(current)) renameSync3(current, next);
40609
+ if (existsSync16(current)) renameSync3(current, next);
39775
40610
  } catch {
39776
40611
  }
39777
40612
  }
39778
40613
  }
39779
40614
  try {
39780
40615
  const content = readFileSync5(filePath, "utf-8");
39781
- const backupPath = join14(backupDir, `${name15}.1`);
40616
+ const backupPath = join16(backupDir, `${name15}.1`);
39782
40617
  if (typeof mode === "number") {
39783
- writeFileSync3(backupPath, content, { encoding: "utf-8", mode });
40618
+ writeFileSync4(backupPath, content, { encoding: "utf-8", mode });
39784
40619
  } else {
39785
- writeFileSync3(backupPath, content, "utf-8");
40620
+ writeFileSync4(backupPath, content, "utf-8");
39786
40621
  }
39787
40622
  } catch {
39788
40623
  }
@@ -39799,15 +40634,15 @@ function writeJsonFileAtomic(filePath, data, optsOrIndent = 2) {
39799
40634
  const indent = opts.indent ?? 2;
39800
40635
  const mode = opts.mode;
39801
40636
  const dir = dirname7(filePath);
39802
- const tempPath = join14(dir, `.${basename5(filePath)}.${randomBytes(6).toString("hex")}.tmp`);
40637
+ const tempPath = join16(dir, `.${basename5(filePath)}.${randomBytes(6).toString("hex")}.tmp`);
39803
40638
  const content = JSON.stringify(data, null, indent) + "\n";
39804
40639
  if (typeof mode === "number") {
39805
- writeFileSync3(tempPath, content, { encoding: "utf-8", mode });
40640
+ writeFileSync4(tempPath, content, { encoding: "utf-8", mode });
39806
40641
  } else {
39807
- writeFileSync3(tempPath, content, "utf-8");
40642
+ writeFileSync4(tempPath, content, "utf-8");
39808
40643
  }
39809
40644
  try {
39810
- if (existsSync15(filePath)) {
40645
+ if (existsSync16(filePath)) {
39811
40646
  rotateBackup(filePath, mode);
39812
40647
  }
39813
40648
  renameSync3(tempPath, filePath);
@@ -39833,19 +40668,19 @@ function readJsonFile(filePath) {
39833
40668
  async function withLock2(filePath, transform2, opts = {}) {
39834
40669
  const dir = dirname7(filePath);
39835
40670
  const dirMode = typeof opts.mode === "number" ? modeToDirMode(opts.mode) : void 0;
39836
- if (!existsSync15(dir)) {
39837
- mkdirSync4(dir, { recursive: true, mode: dirMode });
40671
+ if (!existsSync16(dir)) {
40672
+ mkdirSync5(dir, { recursive: true, mode: dirMode });
39838
40673
  }
39839
- if (!existsSync15(filePath)) {
40674
+ if (!existsSync16(filePath)) {
39840
40675
  if (typeof opts.mode === "number") {
39841
- writeFileSync3(filePath, "", { encoding: "utf-8", mode: opts.mode });
40676
+ writeFileSync4(filePath, "", { encoding: "utf-8", mode: opts.mode });
39842
40677
  } else {
39843
- writeFileSync3(filePath, "", "utf-8");
40678
+ writeFileSync4(filePath, "", "utf-8");
39844
40679
  }
39845
40680
  }
39846
40681
  let release;
39847
40682
  try {
39848
- release = await lockfile2.lock(filePath, LOCK_OPTIONS);
40683
+ release = await lockfile3.lock(filePath, LOCK_OPTIONS);
39849
40684
  const current = readJsonFile(filePath);
39850
40685
  const updated = transform2(current);
39851
40686
  writeJsonFileAtomic(filePath, updated, { mode: opts.mode });
@@ -39858,15 +40693,15 @@ async function withLock2(filePath, transform2, opts = {}) {
39858
40693
  }
39859
40694
  async function withFileLock(filePath, operation) {
39860
40695
  const dir = dirname7(filePath);
39861
- if (!existsSync15(dir)) {
39862
- mkdirSync4(dir, { recursive: true });
40696
+ if (!existsSync16(dir)) {
40697
+ mkdirSync5(dir, { recursive: true });
39863
40698
  }
39864
- if (!existsSync15(filePath)) {
39865
- writeFileSync3(filePath, "", "utf-8");
40699
+ if (!existsSync16(filePath)) {
40700
+ writeFileSync4(filePath, "", "utf-8");
39866
40701
  }
39867
40702
  let release;
39868
40703
  try {
39869
- release = await lockfile2.lock(filePath, LOCK_OPTIONS);
40704
+ release = await lockfile3.lock(filePath, LOCK_OPTIONS);
39870
40705
  return await operation();
39871
40706
  } finally {
39872
40707
  if (release) {
@@ -39895,10 +40730,10 @@ var init_file_utils = __esm({
39895
40730
 
39896
40731
  // packages/core/src/llm/credential-removal.ts
39897
40732
  import { unlinkSync as unlinkSync4 } from "node:fs";
39898
- import { join as join15 } from "node:path";
39899
- import { getCleoHome as getCleoHome2 } from "@cleocode/paths";
40733
+ import { join as join17 } from "node:path";
40734
+ import { getCleoHome as getCleoHome3 } from "@cleocode/paths";
39900
40735
  function suppressionStatePath() {
39901
- return join15(getCleoHome2(), SUPPRESSION_FILENAME);
40736
+ return join17(getCleoHome3(), SUPPRESSION_FILENAME);
39902
40737
  }
39903
40738
  function readSuppressionFile() {
39904
40739
  const data = readJsonFile(suppressionStatePath());
@@ -40002,7 +40837,7 @@ var init_credential_removal = __esm({
40002
40837
  sourceId: "cleo-pkce",
40003
40838
  description: "Delete CLEO-issued PKCE token at <CLEO_HOME>/anthropic-oauth.json",
40004
40839
  async remove() {
40005
- const path = join15(getCleoHome2(), "anthropic-oauth.json");
40840
+ const path = join17(getCleoHome3(), "anthropic-oauth.json");
40006
40841
  const cleaned = [];
40007
40842
  try {
40008
40843
  unlinkSync4(path);
@@ -40081,7 +40916,7 @@ __export(config_exports, {
40081
40916
  parseConfigValue: () => parseConfigValue,
40082
40917
  setConfigValue: () => setConfigValue
40083
40918
  });
40084
- import { existsSync as existsSync16 } from "node:fs";
40919
+ import { existsSync as existsSync17 } from "node:fs";
40085
40920
  function getNestedValue(obj, path) {
40086
40921
  const parts = path.split(".");
40087
40922
  let current = obj;
@@ -40129,7 +40964,7 @@ function parseEnvValue(value) {
40129
40964
  return value;
40130
40965
  }
40131
40966
  async function loadConfig(cwd) {
40132
- let merged = JSON.parse(JSON.stringify(DEFAULTS));
40967
+ let merged = JSON.parse(JSON.stringify(DEFAULTS2));
40133
40968
  const globalConfig2 = await readJson(getGlobalConfigPath());
40134
40969
  if (globalConfig2) {
40135
40970
  merged = deepMerge(merged, globalConfig2);
@@ -40175,7 +41010,7 @@ async function getConfigValue(path, cwd) {
40175
41010
  return { value: val, source: "global" };
40176
41011
  }
40177
41012
  }
40178
- const defaultVal = getNestedValue({ ...DEFAULTS }, path);
41013
+ const defaultVal = getNestedValue({ ...DEFAULTS2 }, path);
40179
41014
  return { value: defaultVal, source: "default" };
40180
41015
  }
40181
41016
  async function getRawConfigValue(key, cwd) {
@@ -40203,7 +41038,7 @@ function parseConfigValue(value) {
40203
41038
  }
40204
41039
  async function setConfigValue(key, value, cwd, opts) {
40205
41040
  const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
40206
- if (!existsSync16(configPath)) {
41041
+ if (!existsSync17(configPath)) {
40207
41042
  await atomicWriteJson(configPath, {});
40208
41043
  }
40209
41044
  const config2 = await readJson(configPath) ?? {};
@@ -40215,7 +41050,7 @@ async function setConfigValue(key, value, cwd, opts) {
40215
41050
  async function applyStrictnessPreset(preset, cwd, opts) {
40216
41051
  const definition = STRICTNESS_PRESETS[preset];
40217
41052
  const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
40218
- if (!existsSync16(configPath)) {
41053
+ if (!existsSync17(configPath)) {
40219
41054
  await atomicWriteJson(configPath, {});
40220
41055
  }
40221
41056
  const config2 = await readJson(configPath) ?? {};
@@ -40239,7 +41074,7 @@ function listStrictnessPresets() {
40239
41074
  })
40240
41075
  );
40241
41076
  }
40242
- var DEFAULTS, ENV_MAP, STRICTNESS_PRESETS;
41077
+ var DEFAULTS2, ENV_MAP, STRICTNESS_PRESETS;
40243
41078
  var init_config = __esm({
40244
41079
  "packages/core/src/config.ts"() {
40245
41080
  "use strict";
@@ -40247,7 +41082,7 @@ var init_config = __esm({
40247
41082
  init_paths();
40248
41083
  init_atomic();
40249
41084
  init_json2();
40250
- DEFAULTS = {
41085
+ DEFAULTS2 = {
40251
41086
  version: "2.10.0",
40252
41087
  output: {
40253
41088
  defaultFormat: "json",
@@ -40422,10 +41257,10 @@ var init_config = __esm({
40422
41257
  // packages/core/src/llm/credential-seeders/claude-code-seeder.ts
40423
41258
  import { readFileSync as readFileSync6 } from "node:fs";
40424
41259
  import { homedir as homedir2 } from "node:os";
40425
- import { join as join16 } from "node:path";
41260
+ import { join as join18 } from "node:path";
40426
41261
  function defaultReadCredentialFile() {
40427
41262
  try {
40428
- return readFileSync6(join16(homedir2(), ".claude", ".credentials.json"), "utf-8");
41263
+ return readFileSync6(join18(homedir2(), ".claude", ".credentials.json"), "utf-8");
40429
41264
  } catch {
40430
41265
  return null;
40431
41266
  }
@@ -40520,9 +41355,9 @@ var init_claude_code_seeder = __esm({
40520
41355
 
40521
41356
  // packages/core/src/llm/credential-seeders/cleo-pkce-seeder.ts
40522
41357
  import { readFileSync as readFileSync7 } from "node:fs";
40523
- import { join as join17 } from "node:path";
41358
+ import { join as join19 } from "node:path";
40524
41359
  function defaultCleoPkcePath() {
40525
- return join17(getCleoHome(), "anthropic-oauth.json");
41360
+ return join19(getCleoHome(), "anthropic-oauth.json");
40526
41361
  }
40527
41362
  function defaultReadCredentialFile2() {
40528
41363
  try {
@@ -40593,13 +41428,13 @@ var init_cleo_pkce_seeder = __esm({
40593
41428
  });
40594
41429
 
40595
41430
  // packages/core/src/llm/credential-seeders/codex-cli-seeder.ts
40596
- import { existsSync as existsSync17, readFileSync as readFileSync8 } from "node:fs";
41431
+ import { existsSync as existsSync18, readFileSync as readFileSync8 } from "node:fs";
40597
41432
  import { homedir as homedir3 } from "node:os";
40598
- import { join as join18 } from "node:path";
41433
+ import { join as join20 } from "node:path";
40599
41434
  function getCodexAuthPath() {
40600
41435
  const codexHome = (process.env["CODEX_HOME"] ?? "").trim();
40601
- const root = codexHome || join18(homedir3(), ".codex");
40602
- return join18(root, "auth.json");
41436
+ const root = codexHome || join20(homedir3(), ".codex");
41437
+ return join20(root, "auth.json");
40603
41438
  }
40604
41439
  var CodexCliSeeder, codexCliSeeder;
40605
41440
  var init_codex_cli_seeder = __esm({
@@ -40618,7 +41453,7 @@ var init_codex_cli_seeder = __esm({
40618
41453
  */
40619
41454
  async seed() {
40620
41455
  const authPath = getCodexAuthPath();
40621
- if (!existsSync17(authPath)) {
41456
+ if (!existsSync18(authPath)) {
40622
41457
  return { entries: [] };
40623
41458
  }
40624
41459
  let raw;
@@ -40813,11 +41648,11 @@ var init_google_pkce = __esm({
40813
41648
  });
40814
41649
 
40815
41650
  // packages/core/src/llm/credential-seeders/gemini-cli-seeder.ts
40816
- import { existsSync as existsSync18, readFileSync as readFileSync9 } from "node:fs";
40817
- import { join as join19 } from "node:path";
40818
- import { getCleoHome as getCleoHome3 } from "@cleocode/paths";
41651
+ import { existsSync as existsSync19, readFileSync as readFileSync9 } from "node:fs";
41652
+ import { join as join21 } from "node:path";
41653
+ import { getCleoHome as getCleoHome4 } from "@cleocode/paths";
40819
41654
  function getGoogleOauthPath() {
40820
- return join19(getCleoHome3(), "google_oauth.json");
41655
+ return join21(getCleoHome4(), "google_oauth.json");
40821
41656
  }
40822
41657
  function parseGoogleOauthFile(raw) {
40823
41658
  let json3;
@@ -40862,7 +41697,7 @@ var init_gemini_cli_seeder = __esm({
40862
41697
  */
40863
41698
  async seed() {
40864
41699
  const path = getGoogleOauthPath();
40865
- if (!existsSync18(path)) {
41700
+ if (!existsSync19(path)) {
40866
41701
  return { entries: [] };
40867
41702
  }
40868
41703
  let raw;
@@ -41087,23 +41922,23 @@ var init_credential_seeders = __esm({
41087
41922
 
41088
41923
  // packages/core/src/llm/global-config-migration.ts
41089
41924
  import {
41090
- existsSync as existsSync19,
41091
- mkdirSync as mkdirSync5,
41925
+ existsSync as existsSync20,
41926
+ mkdirSync as mkdirSync6,
41092
41927
  readFileSync as readFileSync10,
41093
41928
  renameSync as renameSync4,
41094
41929
  unlinkSync as unlinkSync5,
41095
- writeFileSync as writeFileSync4
41930
+ writeFileSync as writeFileSync5
41096
41931
  } from "node:fs";
41097
- import { join as join20 } from "node:path";
41098
- import { getCleoHome as getCleoHome4, getCleoPlatformPaths as getCleoPlatformPaths2 } from "@cleocode/paths";
41932
+ import { join as join22 } from "node:path";
41933
+ import { getCleoHome as getCleoHome5, getCleoPlatformPaths as getCleoPlatformPaths2 } from "@cleocode/paths";
41099
41934
  function configDirGlobalConfigPath() {
41100
- return join20(getCleoPlatformPaths2().config, GLOBAL_CONFIG_FILENAME);
41935
+ return join22(getCleoPlatformPaths2().config, GLOBAL_CONFIG_FILENAME);
41101
41936
  }
41102
41937
  function legacyGlobalConfigPath() {
41103
- return join20(getCleoHome4(), GLOBAL_CONFIG_FILENAME);
41938
+ return join22(getCleoHome5(), GLOBAL_CONFIG_FILENAME);
41104
41939
  }
41105
41940
  function migrationMarkerPath() {
41106
- return join20(getCleoHome4(), MIGRATIONS_SUBDIR, MIGRATION_MARKER);
41941
+ return join22(getCleoHome5(), MIGRATIONS_SUBDIR, MIGRATION_MARKER);
41107
41942
  }
41108
41943
  function tempTargetPath() {
41109
41944
  return `${configDirGlobalConfigPath()}.tmp`;
@@ -41113,12 +41948,12 @@ function migrateGlobalConfigToConfigDir() {
41113
41948
  const source = legacyGlobalConfigPath();
41114
41949
  const target = configDirGlobalConfigPath();
41115
41950
  const marker16 = migrationMarkerPath();
41116
- if (existsSync19(marker16)) return false;
41117
- if (!existsSync19(source)) {
41951
+ if (existsSync20(marker16)) return false;
41952
+ if (!existsSync20(source)) {
41118
41953
  stampMarker(marker16);
41119
41954
  return false;
41120
41955
  }
41121
- if (existsSync19(target)) {
41956
+ if (existsSync20(target)) {
41122
41957
  backupSourceQuiet(source);
41123
41958
  stampMarker(marker16);
41124
41959
  return false;
@@ -41132,9 +41967,9 @@ function migrateGlobalConfigToConfigDir() {
41132
41967
  );
41133
41968
  return false;
41134
41969
  }
41135
- mkdirSync5(getCleoPlatformPaths2().config, { recursive: true });
41970
+ mkdirSync6(getCleoPlatformPaths2().config, { recursive: true });
41136
41971
  const temp = tempTargetPath();
41137
- writeFileSync4(temp, raw, { mode: 420 });
41972
+ writeFileSync5(temp, raw, { mode: 420 });
41138
41973
  renameSync4(temp, target);
41139
41974
  stampMarker(marker16);
41140
41975
  try {
@@ -41151,7 +41986,7 @@ function migrateGlobalConfigToConfigDir() {
41151
41986
  } catch (err) {
41152
41987
  try {
41153
41988
  const temp = tempTargetPath();
41154
- if (existsSync19(temp)) unlinkSync5(temp);
41989
+ if (existsSync20(temp)) unlinkSync5(temp);
41155
41990
  } catch {
41156
41991
  }
41157
41992
  console.error(
@@ -41162,8 +41997,8 @@ function migrateGlobalConfigToConfigDir() {
41162
41997
  }
41163
41998
  function stampMarker(markerPath) {
41164
41999
  try {
41165
- mkdirSync5(join20(getCleoHome4(), MIGRATIONS_SUBDIR), { recursive: true });
41166
- writeFileSync4(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
42000
+ mkdirSync6(join22(getCleoHome5(), MIGRATIONS_SUBDIR), { recursive: true });
42001
+ writeFileSync5(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
41167
42002
  `, { mode: 420 });
41168
42003
  } catch {
41169
42004
  }
@@ -41171,7 +42006,7 @@ function stampMarker(markerPath) {
41171
42006
  function backupSourceQuiet(source) {
41172
42007
  try {
41173
42008
  const backup = `${source}${BACKUP_SUFFIX}`;
41174
- if (existsSync19(backup)) return;
42009
+ if (existsSync20(backup)) return;
41175
42010
  renameSync4(source, backup);
41176
42011
  } catch {
41177
42012
  }
@@ -41194,20 +42029,20 @@ var init_global_config_migration = __esm({
41194
42029
  });
41195
42030
 
41196
42031
  // packages/core/src/llm/legacy-flat-key-import.ts
41197
- import { existsSync as existsSync20, readFileSync as readFileSync11, renameSync as renameSync5, writeFileSync as writeFileSync5 } from "node:fs";
41198
- import { join as join21 } from "node:path";
41199
- import { getCleoHome as getCleoHome5 } from "@cleocode/paths";
42032
+ import { existsSync as existsSync21, readFileSync as readFileSync11, renameSync as renameSync5, writeFileSync as writeFileSync6 } from "node:fs";
42033
+ import { join as join23 } from "node:path";
42034
+ import { getCleoHome as getCleoHome6 } from "@cleocode/paths";
41200
42035
  function migrationPaths() {
41201
- const home = getCleoHome5();
42036
+ const home = getCleoHome6();
41202
42037
  return {
41203
- flatPath: join21(home, "anthropic-key"),
41204
- bakPath: join21(home, `anthropic-key${LEGACY_FLAT_KEY_BAK_SUFFIX}`),
41205
- markerPath: join21(home, LEGACY_FLAT_KEY_MARKER)
42038
+ flatPath: join23(home, "anthropic-key"),
42039
+ bakPath: join23(home, `anthropic-key${LEGACY_FLAT_KEY_BAK_SUFFIX}`),
42040
+ markerPath: join23(home, LEGACY_FLAT_KEY_MARKER)
41206
42041
  };
41207
42042
  }
41208
42043
  function writeMarker(markerPath) {
41209
42044
  try {
41210
- writeFileSync5(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
42045
+ writeFileSync6(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
41211
42046
  `, {
41212
42047
  encoding: "utf-8",
41213
42048
  flag: "wx",
@@ -41223,7 +42058,7 @@ function writeMarker(markerPath) {
41223
42058
  }
41224
42059
  function readFlatKey(flatPath) {
41225
42060
  try {
41226
- if (!existsSync20(flatPath)) return null;
42061
+ if (!existsSync21(flatPath)) return null;
41227
42062
  const raw = readFileSync11(flatPath, "utf-8").trim();
41228
42063
  return raw || null;
41229
42064
  } catch (err) {
@@ -41236,7 +42071,7 @@ function readFlatKey(flatPath) {
41236
42071
  }
41237
42072
  async function importLegacyFlatAnthropicKey() {
41238
42073
  const { flatPath, bakPath, markerPath } = migrationPaths();
41239
- if (existsSync20(markerPath)) {
42074
+ if (existsSync21(markerPath)) {
41240
42075
  return { status: "marker-present", flatPath, bakPath: null, markerPath };
41241
42076
  }
41242
42077
  let existing = null;
@@ -41253,7 +42088,7 @@ async function importLegacyFlatAnthropicKey() {
41253
42088
  writeMarker(markerPath);
41254
42089
  return { status: "already-imported", flatPath, bakPath: null, markerPath };
41255
42090
  }
41256
- if (!existsSync20(flatPath)) {
42091
+ if (!existsSync21(flatPath)) {
41257
42092
  writeMarker(markerPath);
41258
42093
  return { status: "no-flat-file", flatPath, bakPath: null, markerPath };
41259
42094
  }
@@ -41330,15 +42165,15 @@ __export(credentials_exports, {
41330
42165
  resolveProviderStatus: () => resolveProviderStatus,
41331
42166
  storeAnthropicApiKey: () => storeAnthropicApiKey
41332
42167
  });
41333
- import { existsSync as existsSync21, mkdirSync as mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "node:fs";
41334
- import { join as join22 } from "node:path";
41335
- import { getCleoHome as getCleoHome6 } from "@cleocode/paths";
42168
+ import { existsSync as existsSync22, mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
42169
+ import { join as join24 } from "node:path";
42170
+ import { getCleoHome as getCleoHome7 } from "@cleocode/paths";
41336
42171
  function globalConfigPath() {
41337
42172
  return configDirGlobalConfigPath();
41338
42173
  }
41339
42174
  function projectConfigPath(projectRoot) {
41340
42175
  const cleoDir = process.env["CLEO_DIR"] ?? ".cleo";
41341
- return join22(projectRoot, cleoDir, "config.json");
42176
+ return join24(projectRoot, cleoDir, "config.json");
41342
42177
  }
41343
42178
  function readGlobalProviderKey(provider) {
41344
42179
  ensureGlobalConfigMigrated();
@@ -41348,8 +42183,8 @@ function readGlobalProviderKey(provider) {
41348
42183
  }
41349
42184
  function readFlatAnthropicKey() {
41350
42185
  try {
41351
- const keyFile = join22(getCleoHome6(), "anthropic-key");
41352
- if (!existsSync21(keyFile)) return null;
42186
+ const keyFile = join24(getCleoHome7(), "anthropic-key");
42187
+ if (!existsSync22(keyFile)) return null;
41353
42188
  const stored = readFileSync12(keyFile, "utf-8").trim();
41354
42189
  return stored || null;
41355
42190
  } catch {
@@ -41358,7 +42193,7 @@ function readFlatAnthropicKey() {
41358
42193
  }
41359
42194
  function readProviderKeyFromConfig(configFile, provider) {
41360
42195
  try {
41361
- if (!existsSync21(configFile)) return null;
42196
+ if (!existsSync22(configFile)) return null;
41362
42197
  const raw = readFileSync12(configFile, "utf-8");
41363
42198
  const config2 = JSON.parse(raw);
41364
42199
  const llm = config2["llm"];
@@ -41530,12 +42365,12 @@ function resolveProviderStatus(provider) {
41530
42365
  return { provider, resolvedSource, hasCredential: true };
41531
42366
  }
41532
42367
  function storeAnthropicApiKey(apiKey) {
41533
- const dir = getCleoHome6();
41534
- if (!existsSync21(dir)) {
41535
- mkdirSync6(dir, { recursive: true });
42368
+ const dir = getCleoHome7();
42369
+ if (!existsSync22(dir)) {
42370
+ mkdirSync7(dir, { recursive: true });
41536
42371
  }
41537
- const keyFile = join22(dir, "anthropic-key");
41538
- writeFileSync6(keyFile, apiKey.trim(), { mode: 384 });
42372
+ const keyFile = join24(dir, "anthropic-key");
42373
+ writeFileSync7(keyFile, apiKey.trim(), { mode: 384 });
41539
42374
  }
41540
42375
  function clearAnthropicKeyCache() {
41541
42376
  }
@@ -41598,17 +42433,17 @@ __export(credentials_store_exports, {
41598
42433
  pickCredentialForProviderSync: () => pickCredentialForProviderSync,
41599
42434
  removeCredential: () => removeCredential
41600
42435
  });
41601
- import { chmodSync, existsSync as existsSync22, mkdirSync as mkdirSync7, readFileSync as readFileSync13, statSync as statSync6, writeFileSync as writeFileSync7 } from "node:fs";
41602
- import { dirname as dirname8, join as join23 } from "node:path";
41603
- import { getCleoHome as getCleoHome7 } from "@cleocode/paths";
42436
+ import { chmodSync, existsSync as existsSync23, mkdirSync as mkdirSync8, readFileSync as readFileSync13, statSync as statSync6, writeFileSync as writeFileSync8 } from "node:fs";
42437
+ import { dirname as dirname8, join as join25 } from "node:path";
42438
+ import { getCleoHome as getCleoHome8 } from "@cleocode/paths";
41604
42439
  function credentialsStorePath() {
41605
- return join23(getCleoHome7(), "llm-credentials.json");
42440
+ return join25(getCleoHome8(), "llm-credentials.json");
41606
42441
  }
41607
42442
  function ensureFileInitialized(path) {
41608
- if (existsSync22(path)) return;
42443
+ if (existsSync23(path)) return;
41609
42444
  const dir = dirname8(path);
41610
- if (!existsSync22(dir)) {
41611
- mkdirSync7(dir, { recursive: true, mode: 448 });
42445
+ if (!existsSync23(dir)) {
42446
+ mkdirSync8(dir, { recursive: true, mode: 448 });
41612
42447
  } else {
41613
42448
  try {
41614
42449
  chmodSync(dir, 448);
@@ -41616,7 +42451,7 @@ function ensureFileInitialized(path) {
41616
42451
  }
41617
42452
  }
41618
42453
  try {
41619
- writeFileSync7(path, `${JSON.stringify(emptyStore(), null, 2)}
42454
+ writeFileSync8(path, `${JSON.stringify(emptyStore(), null, 2)}
41620
42455
  `, {
41621
42456
  encoding: "utf-8",
41622
42457
  flag: "wx",
@@ -41959,13 +42794,13 @@ var init_gemini = __esm({
41959
42794
 
41960
42795
  // packages/core/src/llm/stable-device-id.ts
41961
42796
  import { randomUUID as randomUUID2 } from "node:crypto";
41962
- import { existsSync as existsSync23, mkdirSync as mkdirSync8, readFileSync as readFileSync14, renameSync as renameSync6, writeFileSync as writeFileSync8 } from "node:fs";
41963
- import { dirname as dirname9, join as join24 } from "node:path";
41964
- import { getCleoHome as getCleoHome8 } from "@cleocode/paths";
42797
+ import { existsSync as existsSync24, mkdirSync as mkdirSync9, readFileSync as readFileSync14, renameSync as renameSync6, writeFileSync as writeFileSync9 } from "node:fs";
42798
+ import { dirname as dirname9, join as join26 } from "node:path";
42799
+ import { getCleoHome as getCleoHome9 } from "@cleocode/paths";
41965
42800
  function getStableDeviceId() {
41966
42801
  if (_cachedDeviceId !== null) return _cachedDeviceId;
41967
- const path = join24(getCleoHome8(), DEVICE_ID_FILE);
41968
- if (existsSync23(path)) {
42802
+ const path = join26(getCleoHome9(), DEVICE_ID_FILE);
42803
+ if (existsSync24(path)) {
41969
42804
  try {
41970
42805
  const raw = readFileSync14(path, "utf-8").trim();
41971
42806
  if (raw.length > 0) {
@@ -41978,11 +42813,11 @@ function getStableDeviceId() {
41978
42813
  const fresh = randomUUID2();
41979
42814
  try {
41980
42815
  const dir = dirname9(path);
41981
- if (!existsSync23(dir)) {
41982
- mkdirSync8(dir, { recursive: true });
42816
+ if (!existsSync24(dir)) {
42817
+ mkdirSync9(dir, { recursive: true });
41983
42818
  }
41984
42819
  const tmpPath = `${path}.tmp.${process.pid}`;
41985
- writeFileSync8(tmpPath, fresh, { mode: 384 });
42820
+ writeFileSync9(tmpPath, fresh, { mode: 384 });
41986
42821
  renameSync6(tmpPath, path);
41987
42822
  } catch {
41988
42823
  }
@@ -42280,14 +43115,14 @@ var init_xai = __esm({
42280
43115
  });
42281
43116
 
42282
43117
  // packages/core/src/llm/provider-registry/loader.ts
42283
- import { readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
42284
- import { join as join25 } from "node:path";
43118
+ import { readdirSync as readdirSync6, statSync as statSync7 } from "node:fs";
43119
+ import { join as join27 } from "node:path";
42285
43120
  import { pathToFileURL } from "node:url";
42286
43121
  function isPluginFile(filename) {
42287
43122
  return PLUGIN_EXTENSIONS.some((ext) => filename.endsWith(ext));
42288
43123
  }
42289
43124
  function getPluginDir() {
42290
- return join25(getCleoHome(), "plugins", "model-providers");
43125
+ return join27(getCleoHome(), "plugins", "model-providers");
42291
43126
  }
42292
43127
  async function loadOnePlugin(absPath, api) {
42293
43128
  let mod;
@@ -42329,19 +43164,19 @@ async function loadOnePlugin(absPath, api) {
42329
43164
  async function scanAndLoadPlugins(pluginDir, api) {
42330
43165
  let entries;
42331
43166
  try {
42332
- entries = readdirSync5(pluginDir);
43167
+ entries = readdirSync6(pluginDir);
42333
43168
  } catch {
42334
43169
  return;
42335
43170
  }
42336
43171
  const pluginFiles = entries.filter((name15) => !name15.startsWith(".") && isPluginFile(name15)).filter((name15) => {
42337
43172
  try {
42338
- return statSync7(join25(pluginDir, name15)).isFile();
43173
+ return statSync7(join27(pluginDir, name15)).isFile();
42339
43174
  } catch {
42340
43175
  return false;
42341
43176
  }
42342
43177
  }).sort();
42343
43178
  for (const filename of pluginFiles) {
42344
- await loadOnePlugin(join25(pluginDir, filename), api);
43179
+ await loadOnePlugin(join27(pluginDir, filename), api);
42345
43180
  }
42346
43181
  }
42347
43182
  async function runDiscovery(registerProvider2, builtins) {
@@ -42444,15 +43279,15 @@ var init_provider_registry = __esm({
42444
43279
  });
42445
43280
 
42446
43281
  // packages/core/src/llm/rate-limit-guard.ts
42447
- import { existsSync as existsSync24, mkdirSync as mkdirSync9, unlinkSync as unlinkSync6 } from "node:fs";
42448
- import { join as join26 } from "node:path";
42449
- import { getCleoHome as getCleoHome9 } from "@cleocode/paths";
43282
+ import { existsSync as existsSync25, mkdirSync as mkdirSync10, unlinkSync as unlinkSync6 } from "node:fs";
43283
+ import { join as join28 } from "node:path";
43284
+ import { getCleoHome as getCleoHome10 } from "@cleocode/paths";
42450
43285
  function sanitize(value) {
42451
43286
  return value.replace(/[^a-zA-Z0-9_-]/g, "_");
42452
43287
  }
42453
43288
  function rateLimitStatePath(provider, label) {
42454
- const dir = join26(getCleoHome9(), "rate-limit-state");
42455
- return join26(dir, `${sanitize(provider)}-${sanitize(label)}.json`);
43289
+ const dir = join28(getCleoHome10(), "rate-limit-state");
43290
+ return join28(dir, `${sanitize(provider)}-${sanitize(label)}.json`);
42456
43291
  }
42457
43292
  function parseResetFromHeaders(headers) {
42458
43293
  const get = (k) => {
@@ -42499,9 +43334,9 @@ async function recordRateLimit(provider, label, opts) {
42499
43334
  source = "default";
42500
43335
  }
42501
43336
  const filePath = rateLimitStatePath(provider, label);
42502
- const dir = join26(getCleoHome9(), "rate-limit-state");
42503
- if (!existsSync24(dir)) {
42504
- mkdirSync9(dir, { recursive: true });
43337
+ const dir = join28(getCleoHome10(), "rate-limit-state");
43338
+ if (!existsSync25(dir)) {
43339
+ mkdirSync10(dir, { recursive: true });
42505
43340
  }
42506
43341
  const state = { resetAt, recordedAt: now, source };
42507
43342
  await withFileLock(filePath, () => {
@@ -43401,28 +44236,28 @@ var init_error_classifier = __esm({
43401
44236
 
43402
44237
  // packages/core/src/llm/catalog-cache.ts
43403
44238
  import {
43404
- existsSync as existsSync25,
43405
- mkdirSync as mkdirSync10,
43406
- readdirSync as readdirSync6,
44239
+ existsSync as existsSync26,
44240
+ mkdirSync as mkdirSync11,
44241
+ readdirSync as readdirSync7,
43407
44242
  readFileSync as readFileSync15,
43408
44243
  statSync as statSync8,
43409
44244
  symlinkSync,
43410
44245
  unlinkSync as unlinkSync7,
43411
- writeFileSync as writeFileSync9
44246
+ writeFileSync as writeFileSync10
43412
44247
  } from "node:fs";
43413
44248
  import { homedir as homedir4 } from "node:os";
43414
- import { join as join27 } from "node:path";
44249
+ import { join as join29 } from "node:path";
43415
44250
  function getCatalogDir() {
43416
44251
  if (process.env["CLEO_DATA_DIR"]) {
43417
- return join27(process.env["CLEO_DATA_DIR"], "llm-catalog");
44252
+ return join29(process.env["CLEO_DATA_DIR"], "llm-catalog");
43418
44253
  }
43419
- const xdg = process.env["XDG_DATA_HOME"] ?? join27(homedir4(), ".local", "share");
43420
- return join27(xdg, "cleo", "llm-catalog");
44254
+ const xdg = process.env["XDG_DATA_HOME"] ?? join29(homedir4(), ".local", "share");
44255
+ return join29(xdg, "cleo", "llm-catalog");
43421
44256
  }
43422
44257
  function findLatestCacheFile(dir) {
43423
- if (!existsSync25(dir)) return null;
43424
- const files = readdirSync6(dir).filter((f) => f.endsWith("-models.json")).map((f) => ({ name: f, mtime: statSync8(join27(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
43425
- return files.length > 0 ? join27(dir, files[0].name) : null;
44258
+ if (!existsSync26(dir)) return null;
44259
+ const files = readdirSync7(dir).filter((f) => f.endsWith("-models.json")).map((f) => ({ name: f, mtime: statSync8(join29(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
44260
+ return files.length > 0 ? join29(dir, files[0].name) : null;
43426
44261
  }
43427
44262
  function readCacheFile(filePath) {
43428
44263
  try {
@@ -43440,14 +44275,14 @@ var init_catalog_cache = __esm({
43440
44275
 
43441
44276
  // packages/core/src/llm/model-metadata.ts
43442
44277
  import { readFileSync as readFileSync16 } from "node:fs";
43443
- import { dirname as dirname10, join as join28 } from "node:path";
44278
+ import { dirname as dirname10, join as join30 } from "node:path";
43444
44279
  import { fileURLToPath as fileURLToPath3 } from "node:url";
43445
44280
  function getCuratedTable() {
43446
44281
  if (_curated !== void 0) {
43447
44282
  return _curated;
43448
44283
  }
43449
44284
  const thisDir = dirname10(fileURLToPath3(import.meta.url));
43450
- const jsonPath = join28(thisDir, "curated-models.json");
44285
+ const jsonPath = join30(thisDir, "curated-models.json");
43451
44286
  const raw = JSON.parse(readFileSync16(jsonPath, "utf-8"));
43452
44287
  _curated = raw.models;
43453
44288
  return _curated;
@@ -43532,7 +44367,7 @@ function storedToResolved(stored) {
43532
44367
  awsProfile: stored.metadata?.["awsProfile"] ?? null
43533
44368
  };
43534
44369
  }
43535
- function sleep(ms) {
44370
+ function sleep2(ms) {
43536
44371
  return new Promise((resolve5) => setTimeout(resolve5, ms));
43537
44372
  }
43538
44373
  function backoffMs(policy, attempt) {
@@ -43670,7 +44505,7 @@ var init_concrete_session = __esm({
43670
44505
  throw err;
43671
44506
  }
43672
44507
  lastErr = err;
43673
- await sleep(backoffMs(policy, attempt));
44508
+ await sleep2(backoffMs(policy, attempt));
43674
44509
  }
43675
44510
  }
43676
44511
  throw lastErr;
@@ -47426,7 +48261,7 @@ function normalizeOllamaToolCall(tc) {
47426
48261
  arguments: JSON.stringify(tc.function.arguments ?? {})
47427
48262
  };
47428
48263
  }
47429
- function sleep2(ms) {
48264
+ function sleep3(ms) {
47430
48265
  return new Promise((resolve5) => setTimeout(resolve5, ms));
47431
48266
  }
47432
48267
  var OLLAMA_DEFAULT_BASE_URL, MAX_RETRIES, INITIAL_BACKOFF_MS, RETRYABLE_STATUS_CODES, OllamaTransport;
@@ -47635,7 +48470,7 @@ var init_ollama2 = __esm({
47635
48470
  for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
47636
48471
  if (attempt > 0) {
47637
48472
  const delay = INITIAL_BACKOFF_MS * 2 ** (attempt - 1);
47638
- await sleep2(delay);
48473
+ await sleep3(delay);
47639
48474
  }
47640
48475
  let response;
47641
48476
  try {
@@ -75648,7 +76483,7 @@ var init_catalog_model_resolver = __esm({
75648
76483
  });
75649
76484
 
75650
76485
  // packages/core/src/llm/cross-provider-selector.ts
75651
- import { totalmem } from "node:os";
76486
+ import { totalmem as totalmem2 } from "node:os";
75652
76487
  async function probeOllamaAlive(baseUrl) {
75653
76488
  const cached2 = _ollamaProbeCache.get(baseUrl);
75654
76489
  if (cached2 && Date.now() - cached2.checkedAt < OLLAMA_PROBE_TTL_MS) {
@@ -75671,7 +76506,7 @@ async function probeOllamaAlive(baseUrl) {
75671
76506
  return alive;
75672
76507
  }
75673
76508
  function ollamaDefaultModelForTier(tier, ramBytesOverride) {
75674
- const ramBytes = ramBytesOverride ?? totalmem();
76509
+ const ramBytes = ramBytesOverride ?? totalmem2();
75675
76510
  const gb = ramBytes / 1024 ** 3;
75676
76511
  if (gb >= 8) {
75677
76512
  return tier === "fast" || tier === "local" ? "gemma4:e2b" : "gemma4:e4b";
@@ -75795,7 +76630,7 @@ async function selectBestProvisioned(role, opts) {
75795
76630
  let model;
75796
76631
  if (winner.id === "ollama") {
75797
76632
  const ollamaProfile2 = await getProviderProfile2("ollama");
75798
- const ramBytes = totalmem();
76633
+ const ramBytes = totalmem2();
75799
76634
  const gb = ramBytes / 1024 ** 3;
75800
76635
  if (gb >= 8) {
75801
76636
  model = (winner.tier === "fast" || taskTier === "fast" ? ollamaProfile2?.defaultAuxModel : ollamaProfile2?.defaultModel) ?? ollamaDefaultModelForTier(winner.tier);