@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
@@ -2049,6 +2049,7 @@ var init_tasks = __esm({
2049
2049
  severity: { type: "string", enum: ["P0", "P1", "P2", "P3"] },
2050
2050
  reason: { type: "string" },
2051
2051
  dependsWaiver: { type: "string" },
2052
+ blockedBy: { type: "string" },
2052
2053
  clearBlockedBy: { type: "boolean" },
2053
2054
  relates: {
2054
2055
  type: "array",
@@ -4748,6 +4749,12 @@ var init_operations_registry = __esm({
4748
4749
  required: false,
4749
4750
  description: "Justification to waive the critical-priority --depends requirement"
4750
4751
  },
4752
+ {
4753
+ name: "blockedBy",
4754
+ type: "string",
4755
+ required: false,
4756
+ description: "Set the free-text blockedBy reason (gh#1106)"
4757
+ },
4751
4758
  {
4752
4759
  name: "clearBlockedBy",
4753
4760
  type: "boolean",
@@ -12571,7 +12578,7 @@ var init_lafs = __esm({
12571
12578
 
12572
12579
  // packages/contracts/src/lease-ipc/messages.ts
12573
12580
  import { z as z11 } from "zod";
12574
- 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;
12581
+ 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;
12575
12582
  var init_messages2 = __esm({
12576
12583
  "packages/contracts/src/lease-ipc/messages.ts"() {
12577
12584
  "use strict";
@@ -12656,6 +12663,24 @@ var init_messages2 = __esm({
12656
12663
  /** The worker's own view of whether it is currently inside an LLM call. */
12657
12664
  in_flight_llm: z11.boolean()
12658
12665
  }).strict();
12666
+ ResourceAdmitRequestSchema = z11.object({
12667
+ /** Tag discriminating this request variant. */
12668
+ kind: z11.literal("resource_admit"),
12669
+ /** The resource class (e.g. `"db-heavy"`, `"full-build"`, `"test-run"`). */
12670
+ class: z11.string().min(1),
12671
+ /** The caller holding the slot — process/worktree-unique; the release key. */
12672
+ holder_id: z11.string().min(1),
12673
+ /** The client-computed budget: the max concurrent holders for this class. */
12674
+ budget: z11.number().int().nonnegative()
12675
+ }).strict();
12676
+ ResourceReleaseRequestSchema = z11.object({
12677
+ /** Tag discriminating this request variant. */
12678
+ kind: z11.literal("resource_release"),
12679
+ /** The resource class the slot belongs to. */
12680
+ class: z11.string().min(1),
12681
+ /** The holder that was admitted (matches the admit `holder_id`). */
12682
+ holder_id: z11.string().min(1)
12683
+ }).strict();
12659
12684
  LeaseIpcRequestSchema = z11.discriminatedUnion("kind", [
12660
12685
  LeaseAcquireRequestSchema,
12661
12686
  LeaseReleaseRequestSchema,
@@ -12663,7 +12688,9 @@ var init_messages2 = __esm({
12663
12688
  RateCheckRequestSchema,
12664
12689
  ToolGrantRequestSchema,
12665
12690
  QueueAdmitRequestSchema,
12666
- WorkerHeartbeatRequestSchema
12691
+ WorkerHeartbeatRequestSchema,
12692
+ ResourceAdmitRequestSchema,
12693
+ ResourceReleaseRequestSchema
12667
12694
  ]);
12668
12695
  LeaseGrantedResponseSchema = z11.object({
12669
12696
  /** Tag discriminating this response variant. */
@@ -12764,6 +12791,25 @@ var init_messages2 = __esm({
12764
12791
  /** Tag discriminating this response variant. */
12765
12792
  kind: z11.literal("heartbeat_ack")
12766
12793
  }).strict();
12794
+ ResourceAdmitDispositionSchema = z11.enum(["admitted", "deferred"]);
12795
+ ResourceAdmitResultResponseSchema = z11.object({
12796
+ /** Tag discriminating this response variant. */
12797
+ kind: z11.literal("resource_admit_result"),
12798
+ /** Whether the heavy op was admitted or deferred. */
12799
+ disposition: ResourceAdmitDispositionSchema,
12800
+ /** Back-off in ms before re-requesting (0 when admitted). */
12801
+ retry_after_ms: z11.number().int().nonnegative(),
12802
+ /** Remaining slots for the class after this decision. */
12803
+ slots_remaining: z11.number().int().nonnegative()
12804
+ }).strict();
12805
+ ResourceReleaseResultResponseSchema = z11.object({
12806
+ /** Tag discriminating this response variant. */
12807
+ kind: z11.literal("resource_release_result"),
12808
+ /** Whether a held slot was actually released (false = no such holder). */
12809
+ released: z11.boolean(),
12810
+ /** Remaining in-flight holders for the class after the release. */
12811
+ slots_remaining: z11.number().int().nonnegative()
12812
+ }).strict();
12767
12813
  LeaseErrorResponseSchema = z11.object({
12768
12814
  /** Tag discriminating this response variant. */
12769
12815
  kind: z11.literal("error"),
@@ -12782,6 +12828,8 @@ var init_messages2 = __esm({
12782
12828
  ChildKilledUnresponsiveResponseSchema,
12783
12829
  QueueAdmitResultResponseSchema,
12784
12830
  HeartbeatAckResponseSchema,
12831
+ ResourceAdmitResultResponseSchema,
12832
+ ResourceReleaseResultResponseSchema,
12785
12833
  LeaseErrorResponseSchema
12786
12834
  ]);
12787
12835
  LeaseIpcRequestEnvelopeSchema = z11.object({
@@ -12815,7 +12863,9 @@ var init_messages2 = __esm({
12815
12863
  "rate_check",
12816
12864
  "tool_grant",
12817
12865
  "queue_admit",
12818
- "worker_heartbeat"
12866
+ "worker_heartbeat",
12867
+ "resource_admit",
12868
+ "resource_release"
12819
12869
  ];
12820
12870
  LEASE_IPC_RESPONSE_KINDS = [
12821
12871
  "lease_granted",
@@ -12827,6 +12877,8 @@ var init_messages2 = __esm({
12827
12877
  "child_killed_unresponsive",
12828
12878
  "queue_admit_result",
12829
12879
  "heartbeat_ack",
12880
+ "resource_admit_result",
12881
+ "resource_release_result",
12830
12882
  "error"
12831
12883
  ];
12832
12884
  LEASE_IPC_MESSAGE_KINDS = [
@@ -12837,9 +12889,11 @@ var init_messages2 = __esm({
12837
12889
  });
12838
12890
 
12839
12891
  // packages/contracts/src/lease-ipc/version.ts
12892
+ var LEASE_IPC_PROTOCOL_VERSION;
12840
12893
  var init_version2 = __esm({
12841
12894
  "packages/contracts/src/lease-ipc/version.ts"() {
12842
12895
  "use strict";
12896
+ LEASE_IPC_PROTOCOL_VERSION = "1.2.0";
12843
12897
  }
12844
12898
  });
12845
12899
 
@@ -14038,6 +14092,25 @@ var init_render = __esm({
14038
14092
  }
14039
14093
  });
14040
14094
 
14095
+ // packages/contracts/src/resource-governor.ts
14096
+ var RESOURCE_CLASSES, DEFAULT_RESOURCE_RETRY_AFTER_MS;
14097
+ var init_resource_governor = __esm({
14098
+ "packages/contracts/src/resource-governor.ts"() {
14099
+ "use strict";
14100
+ RESOURCE_CLASSES = Object.freeze([
14101
+ "interactive-cli",
14102
+ "agent-session",
14103
+ "llm-call",
14104
+ "test-run",
14105
+ "scoped-build",
14106
+ "full-build",
14107
+ "db-heavy",
14108
+ "background-autonomous"
14109
+ ]);
14110
+ DEFAULT_RESOURCE_RETRY_AFTER_MS = 2e3;
14111
+ }
14112
+ });
14113
+
14041
14114
  // packages/contracts/src/session.ts
14042
14115
  var init_session2 = __esm({
14043
14116
  "packages/contracts/src/session.ts"() {
@@ -15788,6 +15861,7 @@ var init_src = __esm({
15788
15861
  init_evidence_atoms();
15789
15862
  init_plan();
15790
15863
  init_render();
15864
+ init_resource_governor();
15791
15865
  init_session2();
15792
15866
  init_session_journal();
15793
15867
  init_status_registry();
@@ -17818,7 +17892,7 @@ var init_sql = __esm({
17818
17892
  return new SQL([new StringChunk(str)]);
17819
17893
  }
17820
17894
  _sql.raw = raw;
17821
- function join32(chunks, separator) {
17895
+ function join34(chunks, separator) {
17822
17896
  const result = [];
17823
17897
  for (const [i, chunk] of chunks.entries()) {
17824
17898
  if (i > 0 && separator !== void 0) result.push(separator);
@@ -17826,7 +17900,7 @@ var init_sql = __esm({
17826
17900
  }
17827
17901
  return new SQL(result);
17828
17902
  }
17829
- _sql.join = join32;
17903
+ _sql.join = join34;
17830
17904
  function identifier(value) {
17831
17905
  return new Name(value);
17832
17906
  }
@@ -20213,7 +20287,7 @@ var init_select2 = __esm({
20213
20287
  const baseTableName = this.tableName;
20214
20288
  const tableName = getTableLikeName(table);
20215
20289
  for (const item of extractUsedTable(table)) this.usedTables.add(item);
20216
- if (typeof tableName === "string" && this.config.joins?.some((join32) => join32.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
20290
+ if (typeof tableName === "string" && this.config.joins?.some((join34) => join34.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
20217
20291
  if (!this.isPartialSelect) {
20218
20292
  if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
20219
20293
  if (typeof tableName === "string" && !is(table, SQL)) {
@@ -24023,7 +24097,7 @@ var init_dialect = __esm({
24023
24097
  if (!joins2) return;
24024
24098
  const withEntries = Object.entries(joins2).filter(([_, v]) => v);
24025
24099
  if (!withEntries.length) return;
24026
- return sql.join(withEntries.map(([k, join32]) => {
24100
+ return sql.join(withEntries.map(([k, join34]) => {
24027
24101
  const relation = tableConfig.relations[k];
24028
24102
  const isSingle2 = is(relation, One);
24029
24103
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
@@ -24034,7 +24108,7 @@ var init_dialect = __esm({
24034
24108
  table: targetTable,
24035
24109
  mode: isSingle2 ? "first" : "many",
24036
24110
  schema,
24037
- queryConfig: join32,
24111
+ queryConfig: join34,
24038
24112
  tableConfig: schema[relation.targetTableName],
24039
24113
  relationWhere: filter2,
24040
24114
  isNested: true,
@@ -24048,7 +24122,7 @@ var init_dialect = __esm({
24048
24122
  key: k,
24049
24123
  selection: innerQuery.selection,
24050
24124
  isArray: !isSingle2,
24051
- isOptional: (relation.optional ?? false) || join32 !== true && !!join32.where
24125
+ isOptional: (relation.optional ?? false) || join34 !== true && !!join34.where
24052
24126
  });
24053
24127
  const jsonColumns = sql.join(innerQuery.selection.map((s) => {
24054
24128
  return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`${jsonb3}(${sql.identifier(s.key)})` : sql.identifier(s.key)}`;
@@ -24869,7 +24943,7 @@ var init_update = __esm({
24869
24943
  createJoin(joinType) {
24870
24944
  return ((table, on) => {
24871
24945
  const tableName = getTableLikeName(table);
24872
- if (typeof tableName === "string" && this.config.joins.some((join32) => join32.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
24946
+ if (typeof tableName === "string" && this.config.joins.some((join34) => join34.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
24873
24947
  if (typeof on === "function") {
24874
24948
  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;
24875
24949
  on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
@@ -25944,8 +26018,8 @@ function probeAndMarkApplied(nativeDb, migration, logSubsystem, eliminatedTables
25944
26018
  });
25945
26019
  if (allAltersPresent && allTablesPresent && allIndexesPresent && allTriggersPresent) {
25946
26020
  insertJournalEntry(nativeDb, migration.hash, migration.folderMillis, migration.name ?? "");
25947
- const log8 = getLogger(logSubsystem);
25948
- log8.debug(
26021
+ const log9 = getLogger(logSubsystem);
26022
+ log9.debug(
25949
26023
  {
25950
26024
  migration: migration.name,
25951
26025
  alters: alterTargets.length,
@@ -26014,14 +26088,14 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
26014
26088
  if (hasOrphanedEntries) {
26015
26089
  const dbHashes = new Set(dbEntries.map((e) => e.hash));
26016
26090
  const allLocalHashesPresentInDb = localMigrations.every((m) => dbHashes.has(m.hash));
26017
- const log8 = getLogger(logSubsystem);
26091
+ const log9 = getLogger(logSubsystem);
26018
26092
  if (allLocalHashesPresentInDb) {
26019
- log8.debug(
26093
+ log9.debug(
26020
26094
  { extra: orphanedEntries.length },
26021
26095
  `Migration journal has ${orphanedEntries.length} entries for migrations not known to this install (DB is ahead). Skipping reconciliation.`
26022
26096
  );
26023
26097
  } else {
26024
- log8.warn(
26098
+ log9.warn(
26025
26099
  { orphaned: orphanedEntries.length },
26026
26100
  `Detected ${orphanedEntries.length} true-orphan journal entries from a previous CLEO lineage. Reconciling via DDL probe.`
26027
26101
  );
@@ -26057,8 +26131,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
26057
26131
  if (alterMatches.length === 0) {
26058
26132
  const stripped = stripSqlComments(fullSql).trim();
26059
26133
  if (stripped === "") {
26060
- const log8 = getLogger(logSubsystem);
26061
- log8.debug(
26134
+ const log9 = getLogger(logSubsystem);
26135
+ log9.debug(
26062
26136
  { migration: migration.name },
26063
26137
  `Migration ${migration.name} is a comment-only baseline marker \u2014 marking applied on existing DB.`
26064
26138
  );
@@ -26097,8 +26171,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
26097
26171
  }
26098
26172
  }
26099
26173
  if (missingColumns.length === 0) {
26100
- const log8 = getLogger(logSubsystem);
26101
- log8.warn(
26174
+ const log9 = getLogger(logSubsystem);
26175
+ log9.warn(
26102
26176
  { migration: migration.name, columns: alterMatches },
26103
26177
  `Detected partially-applied migration ${migration.name} \u2014 columns exist but journal entry missing. Auto-reconciling.`
26104
26178
  );
@@ -26106,8 +26180,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
26106
26180
  continue;
26107
26181
  }
26108
26182
  if (existingColumns.length > 0 && missingColumns.length > 0) {
26109
- const log8 = getLogger(logSubsystem);
26110
- log8.warn(
26183
+ const log9 = getLogger(logSubsystem);
26184
+ log9.warn(
26111
26185
  {
26112
26186
  migration: migration.name,
26113
26187
  existingColumns: existingColumns.map((c) => `${c.table}.${c.column}`),
@@ -26119,12 +26193,12 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
26119
26193
  if (!tableExists(nativeDb, table)) continue;
26120
26194
  try {
26121
26195
  nativeDb.exec(`ALTER TABLE ${table} ADD COLUMN ${column}${ddl ? ` ${ddl}` : ""}`);
26122
- log8.warn(
26196
+ log9.warn(
26123
26197
  { migration: migration.name, table, column },
26124
26198
  `T920: Added missing column ${table}.${column} to complete partial migration.`
26125
26199
  );
26126
26200
  } catch {
26127
- log8.warn(
26201
+ log9.warn(
26128
26202
  { migration: migration.name, table, column },
26129
26203
  `T920: Could not add missing column ${table}.${column} \u2014 will let Drizzle migrate() handle it.`
26130
26204
  );
@@ -26144,8 +26218,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable2, logSubsys
26144
26218
  for (const entry of unnamedEntries) {
26145
26219
  const migrationName = hashToName.get(entry.hash);
26146
26220
  if (!migrationName) continue;
26147
- const log8 = getLogger(logSubsystem);
26148
- log8.debug(
26221
+ const log9 = getLogger(logSubsystem);
26222
+ log9.debug(
26149
26223
  { id: entry.id, hash: entry.hash, name: migrationName },
26150
26224
  `Backfilling missing name on journal entry id=${entry.id} (Drizzle v1 beta legacy compat).`
26151
26225
  );
@@ -26229,13 +26303,13 @@ function ensureColumns(nativeDb, tableName, requiredColumns, logSubsystem, conte
26229
26303
  const existingCols = new Set(columns.map((c) => c.name));
26230
26304
  for (const req of requiredColumns) {
26231
26305
  if (!existingCols.has(req.name)) {
26232
- const log8 = getLogger(logSubsystem);
26306
+ const log9 = getLogger(logSubsystem);
26233
26307
  const message = `Adding missing column ${tableName}.${req.name} via ALTER TABLE`;
26234
26308
  const fields = { column: req.name, context };
26235
26309
  if (context === "fresh") {
26236
- log8.error(fields, `${message} \u2014 MIGRATION DEFECT (fresh DB should not need repair)`);
26310
+ log9.error(fields, `${message} \u2014 MIGRATION DEFECT (fresh DB should not need repair)`);
26237
26311
  } else {
26238
- log8.warn(fields, message);
26312
+ log9.warn(fields, message);
26239
26313
  }
26240
26314
  nativeDb.exec(`ALTER TABLE ${tableName} ADD COLUMN ${req.name} ${req.ddl}`);
26241
26315
  }
@@ -35316,11 +35390,750 @@ var init_cleo_global = __esm({
35316
35390
  }
35317
35391
  });
35318
35392
 
35319
- // packages/core/src/store/lock.ts
35393
+ // packages/core/src/resources/linux-backend.ts
35394
+ import { readFile as readFile2, stat } from "node:fs/promises";
35395
+ function parsePressureLine(line2) {
35396
+ const avg10Match = /avg10=([\d.]+)/.exec(line2);
35397
+ const avg60Match = /avg60=([\d.]+)/.exec(line2);
35398
+ const avg300Match = /avg300=([\d.]+)/.exec(line2);
35399
+ const totalMatch = /total=(\d+)/.exec(line2);
35400
+ if (!avg10Match?.[1] || !avg60Match?.[1] || !avg300Match?.[1] || !totalMatch?.[1]) {
35401
+ return null;
35402
+ }
35403
+ return {
35404
+ avg10: parseFloat(avg10Match[1]),
35405
+ avg60: parseFloat(avg60Match[1]),
35406
+ avg300: parseFloat(avg300Match[1]),
35407
+ totalUs: parseInt(totalMatch[1], 10)
35408
+ };
35409
+ }
35410
+ function parsePsiFile(content) {
35411
+ const lines = content.split("\n").map((l) => l.trim()).filter(Boolean);
35412
+ let some = null;
35413
+ let full = null;
35414
+ for (const line2 of lines) {
35415
+ if (line2.startsWith("some ")) {
35416
+ some = parsePressureLine(line2);
35417
+ } else if (line2.startsWith("full ")) {
35418
+ full = parsePressureLine(line2);
35419
+ }
35420
+ }
35421
+ if (!some) {
35422
+ return null;
35423
+ }
35424
+ return { some, full };
35425
+ }
35426
+ function parseMemAvailable(content) {
35427
+ for (const line2 of content.split("\n")) {
35428
+ if (line2.startsWith("MemAvailable:")) {
35429
+ const match = /MemAvailable:\s+(\d+)\s+kB/.exec(line2);
35430
+ if (match?.[1]) {
35431
+ return parseInt(match[1], 10) * 1024;
35432
+ }
35433
+ }
35434
+ }
35435
+ return null;
35436
+ }
35437
+ function parseSmapsRollup(content) {
35438
+ let rssKb = null;
35439
+ let pssKb = null;
35440
+ for (const line2 of content.split("\n")) {
35441
+ if (line2.startsWith("Rss:")) {
35442
+ const m = /Rss:\s+(\d+)\s+kB/.exec(line2);
35443
+ if (m?.[1]) rssKb = parseInt(m[1], 10);
35444
+ } else if (line2.startsWith("Pss:")) {
35445
+ const m = /Pss:\s+(\d+)\s+kB/.exec(line2);
35446
+ if (m?.[1]) pssKb = parseInt(m[1], 10);
35447
+ }
35448
+ }
35449
+ if (rssKb === null || pssKb === null) return null;
35450
+ return { rssBytes: rssKb * 1024, pssBytes: pssKb * 1024 };
35451
+ }
35452
+ var defaultReadFile, defaultStat, LinuxResourceBackend;
35453
+ var init_linux_backend = __esm({
35454
+ "packages/core/src/resources/linux-backend.ts"() {
35455
+ "use strict";
35456
+ defaultReadFile = (path, encoding) => readFile2(path, encoding);
35457
+ defaultStat = async (path) => {
35458
+ try {
35459
+ const s = await stat(path);
35460
+ return { size: s.size };
35461
+ } catch {
35462
+ return null;
35463
+ }
35464
+ };
35465
+ LinuxResourceBackend = class {
35466
+ globalPressurePath;
35467
+ cgroupSlicePressurePath;
35468
+ walPaths;
35469
+ readFileFn;
35470
+ statFileFn;
35471
+ constructor(opts = {}) {
35472
+ this.globalPressurePath = opts.globalPressurePath ?? "/proc/pressure/memory";
35473
+ this.cgroupSlicePressurePath = opts.cgroupSlicePressurePath ?? null;
35474
+ this.walPaths = opts.walPaths ?? [];
35475
+ this.readFileFn = opts.readFileFn ?? defaultReadFile;
35476
+ this.statFileFn = opts.statFileFn ?? defaultStat;
35477
+ }
35478
+ /**
35479
+ * Take a bounded point-in-time resource sample.
35480
+ *
35481
+ * Read-count (bounded by Amendment 1):
35482
+ * - 1 read: `/proc/pressure/memory`
35483
+ * - 0–1 reads: slice `memory.pressure` (if configured)
35484
+ * - 1 read: `/proc/meminfo`
35485
+ * - N stat calls: one per WAL path in `walPaths`
35486
+ *
35487
+ * Never spawns a child process.
35488
+ */
35489
+ async sample() {
35490
+ const sampledAtMs = Date.now();
35491
+ const globalPressure = await this._readPsi(this.globalPressurePath);
35492
+ const pressureAvailable = globalPressure !== null;
35493
+ let slicePressure = null;
35494
+ if (this.cgroupSlicePressurePath) {
35495
+ slicePressure = await this._readPsi(this.cgroupSlicePressurePath);
35496
+ }
35497
+ const memAvailableBytes = await this._readMemAvailable();
35498
+ const walObservations = await this._readWalObservations();
35499
+ return {
35500
+ sampledAtMs,
35501
+ pressureAvailable,
35502
+ memAvailableBytes,
35503
+ globalPressure,
35504
+ slicePressure,
35505
+ walObservations
35506
+ };
35507
+ }
35508
+ /**
35509
+ * Sweep per-child RSS via `/proc/<pid>/smaps_rollup`.
35510
+ *
35511
+ * **STRUCTURALLY SEPARATED from sample()** — smaps_rollup reads are
35512
+ * ms-scale per multi-GB process and must never appear in the hot path.
35513
+ * Call on a separate low-frequency cadence (e.g. every 60s or on
35514
+ * backoff→hold state transition).
35515
+ *
35516
+ * @param pids - PIDs to sweep. Dead/unknown PIDs are silently skipped.
35517
+ */
35518
+ async sweepChildRss(pids) {
35519
+ const sampledAtMs = Date.now();
35520
+ const entries = [];
35521
+ for (const pid of pids) {
35522
+ try {
35523
+ const content = await this.readFileFn(`/proc/${pid}/smaps_rollup`, "utf-8");
35524
+ const parsed = parseSmapsRollup(content);
35525
+ if (parsed) {
35526
+ entries.push({ pid, ...parsed });
35527
+ }
35528
+ } catch {
35529
+ }
35530
+ }
35531
+ return { sampledAtMs, entries };
35532
+ }
35533
+ // -------------------------------------------------------------------------
35534
+ // Private helpers
35535
+ // -------------------------------------------------------------------------
35536
+ async _readPsi(path) {
35537
+ try {
35538
+ const content = await this.readFileFn(path, "utf-8");
35539
+ return parsePsiFile(content);
35540
+ } catch {
35541
+ return null;
35542
+ }
35543
+ }
35544
+ async _readMemAvailable() {
35545
+ try {
35546
+ const content = await this.readFileFn("/proc/meminfo", "utf-8");
35547
+ return parseMemAvailable(content);
35548
+ } catch {
35549
+ return null;
35550
+ }
35551
+ }
35552
+ async _readWalObservations() {
35553
+ const results = [];
35554
+ for (const walPath of this.walPaths) {
35555
+ const info = await this.statFileFn(walPath);
35556
+ results.push({ walPath, sizeBytes: info?.size ?? null });
35557
+ }
35558
+ return results;
35559
+ }
35560
+ };
35561
+ }
35562
+ });
35563
+
35564
+ // packages/core/src/resources/monitor.ts
35565
+ import { EventEmitter as EventEmitter2 } from "node:events";
35566
+ function resolveThresholds(cfg) {
35567
+ return {
35568
+ holdSomeAvg10: cfg.psi?.holdSomeAvg10 ?? DEFAULTS.holdSomeAvg10,
35569
+ backoffSomeAvg10: cfg.psi?.backoffSomeAvg10 ?? DEFAULTS.backoffSomeAvg10,
35570
+ holdFullAvg10: cfg.psi?.holdFullAvg10 ?? DEFAULTS.holdFullAvg10,
35571
+ backoffFullAvg10: cfg.psi?.backoffFullAvg10 ?? DEFAULTS.backoffFullAvg10,
35572
+ hysteresisPoints: cfg.hysteresisPoints ?? DEFAULTS.hysteresisPoints,
35573
+ headroomBytes: cfg.headroomBytes ?? DEFAULTS.headroomBytes,
35574
+ walWarnThresholdBytes: cfg.walWarnThresholdBytes ?? DEFAULTS.walWarnThresholdBytes,
35575
+ pollIntervalMs: cfg.pollIntervalMs ?? DEFAULTS.pollIntervalMs
35576
+ };
35577
+ }
35578
+ function evaluateState(sample, thresholds, currentState) {
35579
+ if (!sample.pressureAvailable) {
35580
+ if (sample.memAvailableBytes !== null && sample.memAvailableBytes < thresholds.headroomBytes) {
35581
+ return { state: "hold", reason: "degraded: memAvailable below headroom" };
35582
+ }
35583
+ return { state: "ok", reason: "degraded: PSI unavailable, memAvailable sufficient" };
35584
+ }
35585
+ const somePressure = sample.globalPressure?.some ?? sample.slicePressure?.some;
35586
+ const fullPressure = sample.globalPressure?.full ?? sample.slicePressure?.full;
35587
+ const someAvg102 = somePressure?.avg10 ?? 0;
35588
+ const fullAvg10 = fullPressure?.avg10 ?? 0;
35589
+ if (someAvg102 > thresholds.backoffSomeAvg10 || fullAvg10 > thresholds.backoffFullAvg10) {
35590
+ return {
35591
+ state: "backoff",
35592
+ reason: `some avg10=${someAvg102.toFixed(2)} full avg10=${fullAvg10.toFixed(2)} \u2014 above backoff threshold`
35593
+ };
35594
+ }
35595
+ if (someAvg102 > thresholds.holdSomeAvg10 || fullAvg10 > thresholds.holdFullAvg10) {
35596
+ return {
35597
+ state: "hold",
35598
+ reason: `some avg10=${someAvg102.toFixed(2)} full avg10=${fullAvg10.toFixed(2)} \u2014 above hold threshold`
35599
+ };
35600
+ }
35601
+ if (currentState !== "ok") {
35602
+ const hysteresisFloor = thresholds.holdSomeAvg10 - thresholds.hysteresisPoints;
35603
+ const fullHysteresisFloor = thresholds.holdFullAvg10 - thresholds.hysteresisPoints;
35604
+ if (someAvg102 > hysteresisFloor || fullAvg10 > fullHysteresisFloor) {
35605
+ const clamped = currentState === "backoff" ? "hold" : currentState;
35606
+ return {
35607
+ state: clamped,
35608
+ reason: `some avg10=${someAvg102.toFixed(2)} full avg10=${fullAvg10.toFixed(2)} \u2014 hysteresis hold (floor: some ${hysteresisFloor}, full ${fullHysteresisFloor})`
35609
+ };
35610
+ }
35611
+ }
35612
+ return {
35613
+ state: "ok",
35614
+ reason: `some avg10=${someAvg102.toFixed(2)} full avg10=${fullAvg10.toFixed(2)} \u2014 below thresholds`
35615
+ };
35616
+ }
35617
+ var DEFAULTS, ResourceMonitor;
35618
+ var init_monitor = __esm({
35619
+ "packages/core/src/resources/monitor.ts"() {
35620
+ "use strict";
35621
+ init_linux_backend();
35622
+ DEFAULTS = {
35623
+ holdSomeAvg10: 10,
35624
+ backoffSomeAvg10: 20,
35625
+ holdFullAvg10: 5,
35626
+ backoffFullAvg10: 10,
35627
+ hysteresisPoints: 3,
35628
+ headroomBytes: 256 * 1024 * 1024,
35629
+ walWarnThresholdBytes: 256 * 1024 * 1024,
35630
+ pollIntervalMs: 1500
35631
+ };
35632
+ ResourceMonitor = class extends EventEmitter2 {
35633
+ thresholds;
35634
+ backend;
35635
+ _state = "ok";
35636
+ _timer = null;
35637
+ _running = false;
35638
+ constructor(cfg = {}) {
35639
+ super();
35640
+ this.thresholds = resolveThresholds(cfg);
35641
+ this.backend = cfg.backend ?? new LinuxResourceBackend();
35642
+ }
35643
+ // -------------------------------------------------------------------------
35644
+ // Public API
35645
+ // -------------------------------------------------------------------------
35646
+ /**
35647
+ * Current pressure state (only meaningful after at least one sample).
35648
+ */
35649
+ get state() {
35650
+ return this._state;
35651
+ }
35652
+ /**
35653
+ * `true` while the continuous loop is running.
35654
+ */
35655
+ get running() {
35656
+ return this._running;
35657
+ }
35658
+ /**
35659
+ * Take a single point-in-time resource sample.
35660
+ *
35661
+ * Safe to call with the daemon off (no child processes, bounded reads).
35662
+ * Does NOT update `this.state` — use {@link startContinuous} for that.
35663
+ */
35664
+ async sample() {
35665
+ return this.backend.sample();
35666
+ }
35667
+ /**
35668
+ * Start the continuous polling loop.
35669
+ *
35670
+ * Returns a `stop()` function. Calling `stop()` is idempotent.
35671
+ *
35672
+ * Emits:
35673
+ * - `'sample'` on every poll (even if state did not change)
35674
+ * - `'transition'` when `PressureState` changes
35675
+ * - `'error'` if the backend throws (loop continues regardless)
35676
+ */
35677
+ startContinuous() {
35678
+ if (this._running) {
35679
+ return () => this._stopLoop();
35680
+ }
35681
+ this._running = true;
35682
+ this._scheduleNext();
35683
+ return () => this._stopLoop();
35684
+ }
35685
+ /**
35686
+ * Stop the continuous polling loop. Idempotent.
35687
+ */
35688
+ stop() {
35689
+ this._stopLoop();
35690
+ }
35691
+ // -------------------------------------------------------------------------
35692
+ // Private loop machinery
35693
+ // -------------------------------------------------------------------------
35694
+ _scheduleNext() {
35695
+ this._timer = setTimeout(() => {
35696
+ void this._tick();
35697
+ }, this.thresholds.pollIntervalMs);
35698
+ if (typeof this._timer.unref === "function") {
35699
+ this._timer.unref();
35700
+ }
35701
+ }
35702
+ async _tick() {
35703
+ if (!this._running) return;
35704
+ try {
35705
+ const sample = await this.backend.sample();
35706
+ this.emit("sample", sample);
35707
+ const { state: newState, reason } = evaluateState(sample, this.thresholds, this._state);
35708
+ if (newState !== this._state) {
35709
+ const transition = {
35710
+ from: this._state,
35711
+ to: newState,
35712
+ sample,
35713
+ reason
35714
+ };
35715
+ this._state = newState;
35716
+ this.emit("transition", transition);
35717
+ }
35718
+ } catch (err) {
35719
+ this.emit("error", err instanceof Error ? err : new Error(String(err)));
35720
+ }
35721
+ if (this._running) {
35722
+ this._scheduleNext();
35723
+ }
35724
+ }
35725
+ _stopLoop() {
35726
+ this._running = false;
35727
+ if (this._timer !== null) {
35728
+ clearTimeout(this._timer);
35729
+ this._timer = null;
35730
+ }
35731
+ }
35732
+ };
35733
+ }
35734
+ });
35735
+
35736
+ // packages/core/src/resources/supervisor-admit.ts
35737
+ import { connect } from "node:net";
35738
+ import { join as join7 } from "node:path";
35739
+ import { getCleoHome as getCleoHome2 } from "@cleocode/paths";
35740
+ function resolveSupervisorSocketPath() {
35741
+ return process.env.CLEO_SUPERVISOR_SOCKET ?? join7(getCleoHome2(), SUPERVISOR_SOCKET_NAME);
35742
+ }
35743
+ async function sendResourceAdmit(socketPath, cls, holderId, budget) {
35744
+ const result = await sendLeaseRequest(
35745
+ socketPath,
35746
+ { kind: "resource_admit", class: cls, holder_id: holderId, budget },
35747
+ "resource_admit_result"
35748
+ );
35749
+ if ("unavailable" in result) return result;
35750
+ if (result.kind === "resource_admit_result") return result;
35751
+ return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
35752
+ }
35753
+ async function sendResourceRelease(socketPath, cls, holderId) {
35754
+ const result = await sendLeaseRequest(
35755
+ socketPath,
35756
+ { kind: "resource_release", class: cls, holder_id: holderId },
35757
+ "resource_release_result"
35758
+ );
35759
+ if ("unavailable" in result) return result;
35760
+ if (result.kind === "resource_release_result") return result;
35761
+ return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
35762
+ }
35763
+ function sendLeaseRequest(socketPath, request, expectedKind) {
35764
+ return new Promise((resolve5) => {
35765
+ const id = `ra-${process.pid}-${request.kind}`;
35766
+ const envelope = LeaseIpcRequestEnvelopeSchema.parse({
35767
+ protocol_version: LEASE_IPC_PROTOCOL_VERSION,
35768
+ id,
35769
+ direction: "request",
35770
+ request
35771
+ });
35772
+ const line2 = `${JSON.stringify(envelope)}
35773
+ `;
35774
+ let settled = false;
35775
+ let buffer = "";
35776
+ const socket = connect(socketPath);
35777
+ const done = (value) => {
35778
+ if (settled) return;
35779
+ settled = true;
35780
+ socket.removeAllListeners();
35781
+ socket.destroy();
35782
+ resolve5(value);
35783
+ };
35784
+ const degrade = (reason) => done({ unavailable: true, reason });
35785
+ socket.setTimeout(REQUEST_TIMEOUT_MS);
35786
+ const connectTimer = setTimeout(
35787
+ () => degrade("supervisor connect timeout"),
35788
+ CONNECT_TIMEOUT_MS
35789
+ );
35790
+ socket.on("connect", () => {
35791
+ clearTimeout(connectTimer);
35792
+ socket.write(line2);
35793
+ });
35794
+ socket.on("timeout", () => degrade("supervisor request timeout"));
35795
+ socket.on("error", (err) => {
35796
+ clearTimeout(connectTimer);
35797
+ degrade(err.message);
35798
+ });
35799
+ socket.on("close", () => {
35800
+ if (!settled) degrade("supervisor closed the connection before responding");
35801
+ });
35802
+ socket.on("data", (chunk) => {
35803
+ buffer += chunk.toString("utf8");
35804
+ const nl = buffer.indexOf("\n");
35805
+ if (nl < 0) return;
35806
+ let json3;
35807
+ try {
35808
+ json3 = JSON.parse(buffer.slice(0, nl));
35809
+ } catch (cause) {
35810
+ degrade(`malformed lease-ipc frame: ${cause instanceof Error ? cause.message : cause}`);
35811
+ return;
35812
+ }
35813
+ const parsed = LeaseIpcResponseEnvelopeSchema.safeParse(json3);
35814
+ if (!parsed.success) {
35815
+ degrade(`off-contract lease-ipc response: ${parsed.error.message}`);
35816
+ return;
35817
+ }
35818
+ const { response } = parsed.data;
35819
+ if (response.kind === expectedKind) {
35820
+ done(response);
35821
+ return;
35822
+ }
35823
+ if (response.kind === "error") {
35824
+ degrade(`${response.code}: ${response.message}`);
35825
+ return;
35826
+ }
35827
+ degrade(`unexpected lease-ipc response kind for ${request.kind}: ${response.kind}`);
35828
+ });
35829
+ });
35830
+ }
35831
+ var SUPERVISOR_SOCKET_NAME, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS;
35832
+ var init_supervisor_admit = __esm({
35833
+ "packages/core/src/resources/supervisor-admit.ts"() {
35834
+ "use strict";
35835
+ init_src();
35836
+ SUPERVISOR_SOCKET_NAME = "cleo-supervisor.sock";
35837
+ CONNECT_TIMEOUT_MS = 250;
35838
+ REQUEST_TIMEOUT_MS = 2e3;
35839
+ }
35840
+ });
35841
+
35842
+ // packages/core/src/resources/governor.ts
35843
+ var governor_exports = {};
35844
+ __export(governor_exports, {
35845
+ ResourceGovernor: () => ResourceGovernor,
35846
+ _resetGovernorStateForTest: () => _resetGovernorStateForTest,
35847
+ computeClassBudget: () => computeClassBudget,
35848
+ governor: () => governor,
35849
+ governorSlotDir: () => governorSlotDir,
35850
+ resolveGovernorMode: () => resolveGovernorMode,
35851
+ slotFileCount: () => slotFileCount
35852
+ });
35853
+ import { existsSync as existsSync4, mkdirSync, readdirSync as readdirSync2, writeFileSync } from "node:fs";
35854
+ import { availableParallelism, totalmem } from "node:os";
35855
+ import { join as join8 } from "node:path";
35320
35856
  import lockfile from "proper-lockfile";
35857
+ function log2() {
35858
+ if (_log2 === null) _log2 = getLogger("resource-governor");
35859
+ return _log2;
35860
+ }
35861
+ function resolveGovernorMode() {
35862
+ if (_cachedMode2 !== null) return _cachedMode2;
35863
+ const raw = process.env.CLEO_RESOURCES_MODE;
35864
+ _cachedMode2 = raw === "supervisor" || raw === "local" || raw === "off" ? raw : "local";
35865
+ return _cachedMode2;
35866
+ }
35867
+ function logSupervisorDegradeOnce(reason) {
35868
+ if (_supervisorDegradeLogged) return;
35869
+ _supervisorDegradeLogged = true;
35870
+ log2().info(
35871
+ `CLEO_RESOURCES_MODE=supervisor but the arbiter is unreachable (${reason}); degrading to local-mode admission for the process lifetime.`
35872
+ );
35873
+ }
35874
+ function _resetGovernorStateForTest() {
35875
+ _cachedMode2 = null;
35876
+ _supervisorDegradeLogged = false;
35877
+ }
35878
+ function someAvg10(sample) {
35879
+ const some = sample.globalPressure?.some ?? sample.slicePressure?.some;
35880
+ return some?.avg10 ?? 0;
35881
+ }
35882
+ function computeClassBudget(cls, sample, opts = {}) {
35883
+ if (cls === "interactive-cli") return Number.POSITIVE_INFINITY;
35884
+ const cpus = Math.max(1, opts.cpuCount ?? availableParallelism());
35885
+ const totalBytes = opts.totalMemBytes ?? totalmem();
35886
+ const headroomBytes = (opts.headroomMb ?? 2048) * MB;
35887
+ const hold = opts.holdSomeAvg10 ?? 10;
35888
+ const floor = opts.floorSomeAvg10 ?? 25;
35889
+ const some = someAvg10(sample);
35890
+ const availBytes = sample.memAvailableBytes ?? totalBytes;
35891
+ const fullStall = sample.globalPressure?.full?.avg10 ?? sample.slicePressure?.full?.avg10 ?? 0;
35892
+ const backoff = some > floor || fullStall > 10;
35893
+ switch (cls) {
35894
+ case "full-build":
35895
+ return 1;
35896
+ case "agent-session": {
35897
+ const estRamBytes = (opts.agentEstRamMb ?? 4096) * MB;
35898
+ const byMem = Math.floor((availBytes - headroomBytes) / estRamBytes);
35899
+ return clamp2(1, byMem, Math.max(1, cpus - 2));
35900
+ }
35901
+ case "llm-call":
35902
+ return Math.max(1, cpus - 2);
35903
+ case "test-run":
35904
+ case "scoped-build": {
35905
+ const base = Math.max(1, Math.floor(cpus / 4));
35906
+ if (some > floor) return 1;
35907
+ if (some > hold) return Math.max(1, Math.floor(base / 2));
35908
+ return base;
35909
+ }
35910
+ case "db-heavy":
35911
+ return backoff ? 0 : 1;
35912
+ case "background-autonomous":
35913
+ return some > hold || fullStall > 5 ? 0 : 1;
35914
+ default:
35915
+ return 1;
35916
+ }
35917
+ }
35918
+ function clamp2(lo, v, hi) {
35919
+ return Math.max(lo, Math.min(v, hi));
35920
+ }
35921
+ function governorSlotDir(cls) {
35922
+ return join8(getCleoHome(), "locks", `resource-${cls}`);
35923
+ }
35924
+ function ensureSlotFiles(dir, count) {
35925
+ if (!existsSync4(dir)) mkdirSync(dir, { recursive: true });
35926
+ const paths = [];
35927
+ for (let i = 0; i < count; i++) {
35928
+ const p = join8(dir, `slot-${i}.lock`);
35929
+ if (!existsSync4(p)) writeFileSync(p, "", { flag: "a" });
35930
+ paths.push(p);
35931
+ }
35932
+ return paths;
35933
+ }
35934
+ function sleep(ms) {
35935
+ return new Promise((r) => setTimeout(r, ms));
35936
+ }
35937
+ function passThroughGrant(cls) {
35938
+ return {
35939
+ deferred: false,
35940
+ class: cls,
35941
+ slot: -1,
35942
+ acquiredAtMs: Date.now(),
35943
+ release: async () => {
35944
+ }
35945
+ };
35946
+ }
35947
+ function deferral(cls, reason, retryAfterMs) {
35948
+ return { deferred: true, class: cls, retryAfterMs, reason };
35949
+ }
35950
+ function supervisorHolderId(cls) {
35951
+ _supervisorHolderSeq += 1;
35952
+ return `${process.pid}:${cls}:${_supervisorHolderSeq}`;
35953
+ }
35954
+ function shuffledIndices(n) {
35955
+ const order = Array.from({ length: n }, (_, i) => i);
35956
+ for (let i = order.length - 1; i > 0; i--) {
35957
+ const j = Math.floor(Math.random() * (i + 1));
35958
+ const a = order[i];
35959
+ const b = order[j];
35960
+ if (a !== void 0 && b !== void 0) {
35961
+ order[i] = b;
35962
+ order[j] = a;
35963
+ }
35964
+ }
35965
+ return order;
35966
+ }
35967
+ async function countHeldSlots(cls, budget) {
35968
+ const dir = governorSlotDir(cls);
35969
+ if (!existsSync4(dir)) return 0;
35970
+ const slots = ensureSlotFiles(dir, budget);
35971
+ let held = 0;
35972
+ for (const path of slots) {
35973
+ try {
35974
+ const release = await lockfile.lock(path, { retries: 0, stale: STALE_MS, realpath: false });
35975
+ await release();
35976
+ } catch {
35977
+ held++;
35978
+ }
35979
+ }
35980
+ return held;
35981
+ }
35982
+ function slotFileCount(cls) {
35983
+ const dir = governorSlotDir(cls);
35984
+ if (!existsSync4(dir)) return 0;
35985
+ return readdirSync2(dir).filter((f) => f.startsWith("slot-") && f.endsWith(".lock")).length;
35986
+ }
35987
+ var _log2, _cachedMode2, _supervisorDegradeLogged, MB, STALE_MS, _supervisorHolderSeq, ResourceGovernor, governor;
35988
+ var init_governor = __esm({
35989
+ "packages/core/src/resources/governor.ts"() {
35990
+ "use strict";
35991
+ init_src();
35992
+ init_logger();
35993
+ init_paths();
35994
+ init_monitor();
35995
+ init_supervisor_admit();
35996
+ _log2 = null;
35997
+ _cachedMode2 = null;
35998
+ _supervisorDegradeLogged = false;
35999
+ MB = 1024 * 1024;
36000
+ STALE_MS = 6e5;
36001
+ _supervisorHolderSeq = 0;
36002
+ ResourceGovernor = class {
36003
+ /**
36004
+ * Acquire one slot of `cls`. Returns a {@link ResourceGrant} on success or a
36005
+ * {@link ResourceDeferral} on denial. Never throws for admission control;
36006
+ * only genuinely unexpected I/O errors propagate.
36007
+ */
36008
+ async acquire(cls, opts = {}) {
36009
+ const mode = resolveGovernorMode();
36010
+ if (mode === "off" || cls === "interactive-cli") {
36011
+ return passThroughGrant(cls);
36012
+ }
36013
+ const sample = opts.sample ?? await (opts.monitor ?? new ResourceMonitor()).sample();
36014
+ const budget = computeClassBudget(cls, sample, opts);
36015
+ if (!Number.isFinite(budget)) return passThroughGrant(cls);
36016
+ if (budget <= 0) {
36017
+ return deferral(
36018
+ cls,
36019
+ `class '${cls}' budget is 0 under current pressure (some avg10=${someAvg10(sample).toFixed(1)})`,
36020
+ DEFAULT_RESOURCE_RETRY_AFTER_MS
36021
+ );
36022
+ }
36023
+ if (mode === "supervisor") {
36024
+ const viaSupervisor = await this.acquireViaSupervisor(cls, Math.floor(budget));
36025
+ if (viaSupervisor !== null) return viaSupervisor;
36026
+ }
36027
+ const dir = governorSlotDir(cls);
36028
+ const slots = ensureSlotFiles(dir, budget);
36029
+ const blocking = opts.blocking ?? true;
36030
+ const timeoutMs = opts.timeoutMs ?? 36e5;
36031
+ const pollMs = opts.pollMs ?? 200;
36032
+ const startedAt = Date.now();
36033
+ do {
36034
+ const order = shuffledIndices(slots.length);
36035
+ for (const idx of order) {
36036
+ const path = slots[idx];
36037
+ if (!path) continue;
36038
+ try {
36039
+ const release = await lockfile.lock(path, {
36040
+ retries: 0,
36041
+ stale: STALE_MS,
36042
+ realpath: false
36043
+ });
36044
+ let released = false;
36045
+ return {
36046
+ deferred: false,
36047
+ class: cls,
36048
+ slot: idx,
36049
+ acquiredAtMs: Date.now(),
36050
+ release: async () => {
36051
+ if (released) return;
36052
+ released = true;
36053
+ try {
36054
+ await release();
36055
+ } catch {
36056
+ }
36057
+ }
36058
+ };
36059
+ } catch {
36060
+ }
36061
+ }
36062
+ if (!blocking) break;
36063
+ await sleep(pollMs);
36064
+ } while (Date.now() - startedAt < timeoutMs);
36065
+ return deferral(
36066
+ cls,
36067
+ `class '${cls}' is at capacity (${budget} slot(s)); ` + (blocking ? `timed out after ${timeoutMs}ms` : "no slot free"),
36068
+ Math.min(pollMs * 4, DEFAULT_RESOURCE_RETRY_AFTER_MS)
36069
+ );
36070
+ }
36071
+ /**
36072
+ * Route an admission through the supervisor's central `resource_admit` verb.
36073
+ * Returns a grant (whose `release` calls `resource_release`) or a deferral, or
36074
+ * `null` when the supervisor is unreachable so the caller degrades to the
36075
+ * local slot engine. Never throws — a dead arbiter never deadlocks work.
36076
+ *
36077
+ * @task T12001
36078
+ */
36079
+ async acquireViaSupervisor(cls, budget) {
36080
+ const socketPath = resolveSupervisorSocketPath();
36081
+ const holderId = supervisorHolderId(cls);
36082
+ const reply = await sendResourceAdmit(socketPath, cls, holderId, budget);
36083
+ if ("unavailable" in reply) {
36084
+ logSupervisorDegradeOnce(reply.reason);
36085
+ return null;
36086
+ }
36087
+ if (reply.disposition === "deferred") {
36088
+ return deferral(
36089
+ cls,
36090
+ `class '${cls}' deferred by supervisor (budget ${budget})`,
36091
+ reply.retry_after_ms || DEFAULT_RESOURCE_RETRY_AFTER_MS
36092
+ );
36093
+ }
36094
+ let released = false;
36095
+ return {
36096
+ deferred: false,
36097
+ class: cls,
36098
+ slot: 0,
36099
+ acquiredAtMs: Date.now(),
36100
+ release: async () => {
36101
+ if (released) return;
36102
+ released = true;
36103
+ await sendResourceRelease(socketPath, cls, holderId).catch(() => {
36104
+ });
36105
+ }
36106
+ };
36107
+ }
36108
+ /** Non-blocking single-pass acquire (admission semantics). */
36109
+ async tryAcquire(cls, opts = {}) {
36110
+ return this.acquire(cls, { ...opts, blocking: false });
36111
+ }
36112
+ /**
36113
+ * Currently-grantable slot count for `cls` = budget − held. Held is the count
36114
+ * of slot files currently locked. `Infinity` for ungated classes.
36115
+ */
36116
+ async available(cls, opts = {}) {
36117
+ if (resolveGovernorMode() === "off" || cls === "interactive-cli") {
36118
+ return Number.POSITIVE_INFINITY;
36119
+ }
36120
+ const sample = opts.sample ?? await (opts.monitor ?? new ResourceMonitor()).sample();
36121
+ const budget = computeClassBudget(cls, sample, opts);
36122
+ if (!Number.isFinite(budget)) return Number.POSITIVE_INFINITY;
36123
+ if (budget <= 0) return 0;
36124
+ const held = await countHeldSlots(cls, budget);
36125
+ return Math.max(0, budget - held);
36126
+ }
36127
+ };
36128
+ governor = new ResourceGovernor();
36129
+ }
36130
+ });
36131
+
36132
+ // packages/core/src/store/lock.ts
36133
+ import lockfile2 from "proper-lockfile";
35321
36134
  async function acquireLock(filePath, options) {
35322
36135
  try {
35323
- const release = await lockfile.lock(filePath, {
36136
+ const release = await lockfile2.lock(filePath, {
35324
36137
  ...DEFAULT_LOCK_OPTIONS,
35325
36138
  ...options?.stale !== void 0 && { stale: options.stale },
35326
36139
  ...options?.retries !== void 0 && {
@@ -35366,7 +36179,7 @@ var init_lock = __esm({
35366
36179
  });
35367
36180
 
35368
36181
  // packages/core/src/store/atomic.ts
35369
- import { mkdir, readFile as readFile2, rename, unlink } from "node:fs/promises";
36182
+ import { mkdir, readFile as readFile3, rename, unlink } from "node:fs/promises";
35370
36183
  import { dirname as dirname4 } from "node:path";
35371
36184
  import writeFileAtomic from "write-file-atomic";
35372
36185
  async function atomicWrite(filePath, data, options) {
@@ -35382,7 +36195,7 @@ async function atomicWrite(filePath, data, options) {
35382
36195
  }
35383
36196
  async function safeReadFile(filePath) {
35384
36197
  try {
35385
- return await readFile2(filePath, "utf8");
36198
+ return await readFile3(filePath, "utf8");
35386
36199
  } catch (err) {
35387
36200
  if (err instanceof Error && "code" in err && err.code === "ENOENT") {
35388
36201
  return null;
@@ -35403,34 +36216,34 @@ var init_atomic = __esm({
35403
36216
  });
35404
36217
 
35405
36218
  // packages/core/src/store/backup.ts
35406
- import { copyFile, rename as fsRename, mkdir as mkdir2, readdir, stat, unlink as unlink2 } from "node:fs/promises";
35407
- import { basename, join as join7 } from "node:path";
36219
+ import { copyFile, rename as fsRename, mkdir as mkdir2, readdir, stat as stat2, unlink as unlink2 } from "node:fs/promises";
36220
+ import { basename, join as join9 } from "node:path";
35408
36221
  async function createBackup(filePath, backupDir, maxBackups = DEFAULT_MAX_BACKUPS) {
35409
36222
  try {
35410
36223
  await mkdir2(backupDir, { recursive: true });
35411
36224
  const fileName = basename(filePath);
35412
36225
  try {
35413
- await stat(filePath);
36226
+ await stat2(filePath);
35414
36227
  } catch {
35415
36228
  throw new CleoError(3 /* FILE_ERROR */, `Cannot backup: source file not found: ${filePath}`);
35416
36229
  }
35417
36230
  for (let i = maxBackups; i >= 1; i--) {
35418
- const current = join7(backupDir, `${fileName}.${i}`);
36231
+ const current = join9(backupDir, `${fileName}.${i}`);
35419
36232
  if (i === maxBackups) {
35420
36233
  try {
35421
36234
  await unlink2(current);
35422
36235
  } catch {
35423
36236
  }
35424
36237
  } else {
35425
- const next = join7(backupDir, `${fileName}.${i + 1}`);
36238
+ const next = join9(backupDir, `${fileName}.${i + 1}`);
35426
36239
  try {
35427
- await stat(current);
36240
+ await stat2(current);
35428
36241
  await fsRename(current, next);
35429
36242
  } catch {
35430
36243
  }
35431
36244
  }
35432
36245
  }
35433
- const backupPath = join7(backupDir, `${fileName}.1`);
36246
+ const backupPath = join9(backupDir, `${fileName}.1`);
35434
36247
  await copyFile(filePath, backupPath);
35435
36248
  return backupPath;
35436
36249
  } catch (err) {
@@ -35709,8 +36522,8 @@ var init_json2 = __esm({
35709
36522
  });
35710
36523
 
35711
36524
  // packages/core/src/scaffold/ensure-config.ts
35712
- import { existsSync as existsSync4, readFileSync as readFileSync2 } from "node:fs";
35713
- import { basename as basename2, dirname as dirname5, join as join8, resolve as resolve2 } from "node:path";
36525
+ import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
36526
+ import { basename as basename2, dirname as dirname5, join as join10, resolve as resolve2 } from "node:path";
35714
36527
  import { fileURLToPath as fileURLToPath2 } from "node:url";
35715
36528
  function getPackageRoot() {
35716
36529
  const thisFile = fileURLToPath2(import.meta.url);
@@ -35718,7 +36531,7 @@ function getPackageRoot() {
35718
36531
  }
35719
36532
  function getCleoVersion() {
35720
36533
  try {
35721
- const pkgPath = join8(getPackageRoot(), "package.json");
36534
+ const pkgPath = join10(getPackageRoot(), "package.json");
35722
36535
  const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
35723
36536
  return pkg.version ?? "0.0.0";
35724
36537
  } catch {
@@ -35737,25 +36550,25 @@ var init_ensure_config = __esm({
35737
36550
  // packages/core/src/store/exodus/archive.ts
35738
36551
  import {
35739
36552
  copyFileSync as copyFileSync2,
35740
- existsSync as existsSync5,
35741
- mkdirSync,
36553
+ existsSync as existsSync6,
36554
+ mkdirSync as mkdirSync2,
35742
36555
  renameSync,
35743
36556
  unlinkSync,
35744
- writeFileSync
36557
+ writeFileSync as writeFileSync2
35745
36558
  } from "node:fs";
35746
- import { basename as basename3, join as join9 } from "node:path";
36559
+ import { basename as basename3, join as join11 } from "node:path";
35747
36560
  function scopeBaseDir(scope, cwd) {
35748
36561
  return scope === "project" ? resolveCleoDir(cwd) : getCleoHome();
35749
36562
  }
35750
36563
  function exodusArchiveDir(scope, cwd) {
35751
- return join9(scopeBaseDir(scope, cwd), ARCHIVE_DIR_NAME);
36564
+ return join11(scopeBaseDir(scope, cwd), ARCHIVE_DIR_NAME);
35752
36565
  }
35753
36566
  function exodusMarkerPath(scope, cwd) {
35754
- return join9(scopeBaseDir(scope, cwd), MARKER_FILENAME_BY_SCOPE[scope]);
36567
+ return join11(scopeBaseDir(scope, cwd), MARKER_FILENAME_BY_SCOPE[scope]);
35755
36568
  }
35756
36569
  function hasExodusCompleteMarker(scope, cwd) {
35757
36570
  try {
35758
- return existsSync5(exodusMarkerPath(scope, cwd));
36571
+ return existsSync6(exodusMarkerPath(scope, cwd));
35759
36572
  } catch {
35760
36573
  return false;
35761
36574
  }
@@ -35763,7 +36576,7 @@ function hasExodusCompleteMarker(scope, cwd) {
35763
36576
  function writeExodusCompleteMarker(scope, archivedSources, cwd) {
35764
36577
  const markerPath = exodusMarkerPath(scope, cwd);
35765
36578
  const baseDir = scopeBaseDir(scope, cwd);
35766
- mkdirSync(baseDir, { recursive: true });
36579
+ mkdirSync2(baseDir, { recursive: true });
35767
36580
  const marker16 = {
35768
36581
  version: 1,
35769
36582
  scope,
@@ -35772,17 +36585,17 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd) {
35772
36585
  archivedSources: [...archivedSources]
35773
36586
  };
35774
36587
  const tmpPath = `${markerPath}.tmp`;
35775
- writeFileSync(tmpPath, JSON.stringify(marker16, null, 2) + "\n", "utf8");
36588
+ writeFileSync2(tmpPath, JSON.stringify(marker16, null, 2) + "\n", "utf8");
35776
36589
  renameSync(tmpPath, markerPath);
35777
- log2.info({ scope, markerPath, archivedSources }, "exodus: wrote completion marker");
36590
+ log3.info({ scope, markerPath, archivedSources }, "exodus: wrote completion marker");
35778
36591
  return markerPath;
35779
36592
  }
35780
36593
  function moveFileInto(srcPath, destDir) {
35781
- mkdirSync(destDir, { recursive: true });
35782
- let dest = join9(destDir, basename3(srcPath));
35783
- if (existsSync5(dest)) {
36594
+ mkdirSync2(destDir, { recursive: true });
36595
+ let dest = join11(destDir, basename3(srcPath));
36596
+ if (existsSync6(dest)) {
35784
36597
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/Z$/, "Z");
35785
- dest = join9(destDir, `${basename3(srcPath)}.${stamp}`);
36598
+ dest = join11(destDir, `${basename3(srcPath)}.${stamp}`);
35786
36599
  }
35787
36600
  try {
35788
36601
  renameSync(srcPath, dest);
@@ -35793,25 +36606,25 @@ function moveFileInto(srcPath, destDir) {
35793
36606
  return dest;
35794
36607
  }
35795
36608
  function archiveSourceDb(source, cwd) {
35796
- if (!existsSync5(source.path)) {
36609
+ if (!existsSync6(source.path)) {
35797
36610
  return { name: source.name, sourcePath: source.path, archivedTo: null, action: "absent" };
35798
36611
  }
35799
36612
  const destDir = exodusArchiveDir(source.targetScope, cwd);
35800
36613
  const archivedTo = moveFileInto(source.path, destDir);
35801
36614
  for (const suffix of SIDECAR_SUFFIXES) {
35802
36615
  const sidecar = `${source.path}${suffix}`;
35803
- if (existsSync5(sidecar)) {
36616
+ if (existsSync6(sidecar)) {
35804
36617
  try {
35805
36618
  moveFileInto(sidecar, destDir);
35806
36619
  } catch (err) {
35807
- log2.warn(
36620
+ log3.warn(
35808
36621
  { err, sidecar, sourceName: source.name },
35809
36622
  "exodus-archive: failed to archive sidecar (non-fatal)"
35810
36623
  );
35811
36624
  }
35812
36625
  }
35813
36626
  }
35814
- log2.info(
36627
+ log3.info(
35815
36628
  { sourceName: source.name, sourcePath: source.path, archivedTo, scope: source.targetScope },
35816
36629
  "exodus-archive: archived legacy source DB"
35817
36630
  );
@@ -35846,7 +36659,7 @@ function detectStrandedResidue(sources, cwd) {
35846
36659
  const stranded = [];
35847
36660
  for (const source of sources) {
35848
36661
  if (!markedScopes.has(source.targetScope)) continue;
35849
- if (existsSync5(source.path)) {
36662
+ if (existsSync6(source.path)) {
35850
36663
  stranded.push({ name: source.name, path: source.path, scope: source.targetScope });
35851
36664
  }
35852
36665
  }
@@ -35862,14 +36675,14 @@ function archiveStrandedResidue(stranded, sources, cwd) {
35862
36675
  }
35863
36676
  return results;
35864
36677
  }
35865
- var log2, ARCHIVE_DIR_NAME, MARKER_FILENAME_BY_SCOPE, SIDECAR_SUFFIXES;
36678
+ var log3, ARCHIVE_DIR_NAME, MARKER_FILENAME_BY_SCOPE, SIDECAR_SUFFIXES;
35866
36679
  var init_archive2 = __esm({
35867
36680
  "packages/core/src/store/exodus/archive.ts"() {
35868
36681
  "use strict";
35869
36682
  init_logger();
35870
36683
  init_paths();
35871
36684
  init_ensure_config();
35872
- log2 = getLogger("exodus-archive");
36685
+ log3 = getLogger("exodus-archive");
35873
36686
  ARCHIVE_DIR_NAME = "_archive";
35874
36687
  MARKER_FILENAME_BY_SCOPE = {
35875
36688
  project: "exodus-complete",
@@ -36263,7 +37076,7 @@ var init_table_name_map = __esm({
36263
37076
  });
36264
37077
 
36265
37078
  // packages/core/src/store/exodus/count-parity.ts
36266
- import { existsSync as existsSync6 } from "node:fs";
37079
+ import { existsSync as existsSync7 } from "node:fs";
36267
37080
  function listTables(db) {
36268
37081
  return db.prepare(
36269
37082
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%' ORDER BY name"
@@ -36284,14 +37097,14 @@ function rowCount(db, tableName) {
36284
37097
  function computeCountParity(sources, projectDbPath, globalDbPath) {
36285
37098
  const entries = [];
36286
37099
  let skipped = 0;
36287
- if (!existsSync6(projectDbPath) || !existsSync6(globalDbPath)) {
37100
+ if (!existsSync7(projectDbPath) || !existsSync7(globalDbPath)) {
36288
37101
  return { ok: false, entries: [], deficits: [], checked: 0, skipped: 0 };
36289
37102
  }
36290
37103
  const projectSnap = openCleoDbSnapshot(projectDbPath, { readOnly: true });
36291
37104
  const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
36292
37105
  try {
36293
37106
  for (const src of sources) {
36294
- if (!existsSync6(src.path)) continue;
37107
+ if (!existsSync7(src.path)) continue;
36295
37108
  const srcSnap = openCleoDbSnapshot(src.path, { readOnly: true });
36296
37109
  try {
36297
37110
  for (const legacyTable of listTables(srcSnap.db)) {
@@ -36330,27 +37143,27 @@ function computeCountParity(sources, projectDbPath, globalDbPath) {
36330
37143
  }
36331
37144
  const deficits = entries.filter((e) => e.deficit > 0);
36332
37145
  if (deficits.length > 0) {
36333
- log3.warn(
37146
+ log4.warn(
36334
37147
  { deficitCount: deficits.length, sample: deficits.slice(0, 5) },
36335
37148
  `exodus count-parity: ${deficits.length} table(s) have FEWER rows in the consolidated target than the legacy source`
36336
37149
  );
36337
37150
  }
36338
37151
  return { ok: deficits.length === 0, entries, deficits, checked: entries.length, skipped };
36339
37152
  }
36340
- var log3;
37153
+ var log4;
36341
37154
  var init_count_parity = __esm({
36342
37155
  "packages/core/src/store/exodus/count-parity.ts"() {
36343
37156
  "use strict";
36344
37157
  init_logger();
36345
37158
  init_open_cleo_db();
36346
37159
  init_table_name_map();
36347
- log3 = getLogger("exodus-count-parity");
37160
+ log4 = getLogger("exodus-count-parity");
36348
37161
  }
36349
37162
  });
36350
37163
 
36351
37164
  // packages/core/src/store/exodus/plan.ts
36352
- import { existsSync as existsSync7, readdirSync as readdirSync2, statfsSync, statSync } from "node:fs";
36353
- import { join as join10 } from "node:path";
37165
+ import { existsSync as existsSync8, readdirSync as readdirSync3, statfsSync, statSync } from "node:fs";
37166
+ import { join as join12 } from "node:path";
36354
37167
  function computeRequiredBytes(totalSourceBytes, largestSourceBytes) {
36355
37168
  return Math.ceil(STAGING_HEADROOM_FACTOR * largestSourceBytes) + totalSourceBytes;
36356
37169
  }
@@ -36361,33 +37174,33 @@ function buildSourceDescriptors(cwd) {
36361
37174
  // Project-tier — go into consolidated project-scope cleo.db
36362
37175
  {
36363
37176
  name: "tasks",
36364
- path: join10(cleoDir, "tasks.db"),
37177
+ path: join12(cleoDir, "tasks.db"),
36365
37178
  targetScope: "project"
36366
37179
  },
36367
37180
  {
36368
37181
  name: "brain (project)",
36369
- path: join10(cleoDir, "brain.db"),
37182
+ path: join12(cleoDir, "brain.db"),
36370
37183
  targetScope: "project"
36371
37184
  },
36372
37185
  {
36373
37186
  name: "conduit",
36374
- path: join10(cleoDir, "conduit.db"),
37187
+ path: join12(cleoDir, "conduit.db"),
36375
37188
  targetScope: "project"
36376
37189
  },
36377
37190
  // Global-tier — go into consolidated global-scope cleo.db
36378
37191
  {
36379
37192
  name: "nexus",
36380
- path: join10(cleoHome, "nexus.db"),
37193
+ path: join12(cleoHome, "nexus.db"),
36381
37194
  targetScope: "global"
36382
37195
  },
36383
37196
  {
36384
37197
  name: "signaldock",
36385
- path: join10(cleoHome, "signaldock.db"),
37198
+ path: join12(cleoHome, "signaldock.db"),
36386
37199
  targetScope: "global"
36387
37200
  },
36388
37201
  {
36389
37202
  name: "skills",
36390
- path: join10(cleoHome, "skills.db"),
37203
+ path: join12(cleoHome, "skills.db"),
36391
37204
  targetScope: "global"
36392
37205
  }
36393
37206
  ];
@@ -36413,10 +37226,10 @@ function deriveStagingDirName() {
36413
37226
  }
36414
37227
  function findExistingStaging(cleoDir) {
36415
37228
  try {
36416
- const entries = readdirSync2(cleoDir, { withFileTypes: true });
37229
+ const entries = readdirSync3(cleoDir, { withFileTypes: true });
36417
37230
  const stagingDirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => e.name).sort().reverse();
36418
37231
  if (stagingDirs.length > 0) {
36419
- return join10(cleoDir, stagingDirs[0]);
37232
+ return join12(cleoDir, stagingDirs[0]);
36420
37233
  }
36421
37234
  } catch {
36422
37235
  }
@@ -36432,7 +37245,7 @@ function buildExodusPlan(cwd) {
36432
37245
  const availableBytes = getAvailableBytes(cleoDir);
36433
37246
  const diskPreflight = totalSourceBytes === 0 || availableBytes >= requiredBytes;
36434
37247
  const existingStaging = findExistingStaging(cleoDir);
36435
- const stagingDir = existingStaging ?? join10(cleoDir, deriveStagingDirName());
37248
+ const stagingDir = existingStaging ?? join12(cleoDir, deriveStagingDirName());
36436
37249
  const resumeFromStaging = existingStaging !== null;
36437
37250
  const projectDbPath = resolveDualScopeDbPath("project", cwd);
36438
37251
  const globalDbPath = resolveDualScopeDbPath("global");
@@ -36451,7 +37264,7 @@ function buildExodusPlan(cwd) {
36451
37264
  };
36452
37265
  }
36453
37266
  function sourcesPresent(sources) {
36454
- return sources.some((s) => existsSync7(s.path));
37267
+ return sources.some((s) => existsSync8(s.path));
36455
37268
  }
36456
37269
  var STAGING_HEADROOM_FACTOR, STAGING_COPY_SKIP_THRESHOLD_BYTES;
36457
37270
  var init_plan2 = __esm({
@@ -36465,18 +37278,18 @@ var init_plan2 = __esm({
36465
37278
  });
36466
37279
 
36467
37280
  // packages/core/src/store/exodus/health.ts
36468
- import { existsSync as existsSync8, statSync as statSync2 } from "node:fs";
37281
+ import { existsSync as existsSync9, statSync as statSync2 } from "node:fs";
36469
37282
  function buildExodusHealth(cwd) {
36470
37283
  const plan = buildExodusPlan(cwd);
36471
- const anyLegacyPresent = plan.sources.some((s) => existsSync8(s.path));
37284
+ const anyLegacyPresent = plan.sources.some((s) => existsSync9(s.path));
36472
37285
  const parity = anyLegacyPresent ? computeCountParity(plan.sources, plan.projectDbPath, plan.globalDbPath) : { ok: true, entries: [], deficits: [], checked: 0, skipped: 0 };
36473
37286
  const consolidatedExistsByScope = {
36474
- project: existsSync8(plan.projectDbPath),
36475
- global: existsSync8(plan.globalDbPath)
37287
+ project: existsSync9(plan.projectDbPath),
37288
+ global: existsSync9(plan.globalDbPath)
36476
37289
  };
36477
37290
  const buildScope = (scope) => {
36478
37291
  const sources = plan.sources.filter((s) => s.targetScope === scope).map((s) => {
36479
- const present = existsSync8(s.path);
37292
+ const present = existsSync9(s.path);
36480
37293
  let bytes = 0;
36481
37294
  if (present) {
36482
37295
  try {
@@ -36743,15 +37556,15 @@ var init_types = __esm({
36743
37556
  // packages/core/src/store/exodus/migrate.ts
36744
37557
  import {
36745
37558
  copyFileSync as copyFileSync3,
36746
- existsSync as existsSync9,
36747
- mkdirSync as mkdirSync2,
37559
+ existsSync as existsSync10,
37560
+ mkdirSync as mkdirSync3,
36748
37561
  readFileSync as readFileSync3,
36749
37562
  renameSync as renameSync2,
36750
37563
  statSync as statSync3,
36751
37564
  unlinkSync as unlinkSync2,
36752
- writeFileSync as writeFileSync2
37565
+ writeFileSync as writeFileSync3
36753
37566
  } from "node:fs";
36754
- import { join as join11 } from "node:path";
37567
+ import { join as join13 } from "node:path";
36755
37568
  function getSqliteVersion(db) {
36756
37569
  try {
36757
37570
  const row = db.prepare("SELECT sqlite_version() AS v").get();
@@ -36767,14 +37580,14 @@ function listTables2(db) {
36767
37580
  return rows.map((r) => r.name);
36768
37581
  }
36769
37582
  function writeJournal(stagingDir, journal) {
36770
- const journalPath = join11(stagingDir, JOURNAL_FILENAME);
37583
+ const journalPath = join13(stagingDir, JOURNAL_FILENAME);
36771
37584
  const tmpPath = `${journalPath}.tmp`;
36772
- writeFileSync2(tmpPath, JSON.stringify(journal, null, 2) + "\n", "utf8");
37585
+ writeFileSync3(tmpPath, JSON.stringify(journal, null, 2) + "\n", "utf8");
36773
37586
  renameSync2(tmpPath, journalPath);
36774
37587
  }
36775
37588
  function readJournal(stagingDir) {
36776
- const journalPath = join11(stagingDir, JOURNAL_FILENAME);
36777
- if (!existsSync9(journalPath)) return null;
37589
+ const journalPath = join13(stagingDir, JOURNAL_FILENAME);
37590
+ if (!existsSync10(journalPath)) return null;
36778
37591
  try {
36779
37592
  return JSON.parse(readFileSync3(journalPath, "utf8"));
36780
37593
  } catch {
@@ -36782,17 +37595,17 @@ function readJournal(stagingDir) {
36782
37595
  }
36783
37596
  }
36784
37597
  function clearExodusJournal(stagingDir) {
36785
- const journalPath = join11(stagingDir, JOURNAL_FILENAME);
37598
+ const journalPath = join13(stagingDir, JOURNAL_FILENAME);
36786
37599
  try {
36787
- if (!existsSync9(journalPath)) return false;
37600
+ if (!existsSync10(journalPath)) return false;
36788
37601
  unlinkSync2(journalPath);
36789
- log4.info(
37602
+ log5.info(
36790
37603
  { stagingDir },
36791
37604
  "exodus: cleared migrate journal after abort/rollback \u2014 a retry will RE-COPY all tables"
36792
37605
  );
36793
37606
  return true;
36794
37607
  } catch (err) {
36795
- log4.warn(
37608
+ log5.warn(
36796
37609
  { err, stagingDir },
36797
37610
  'exodus: failed to clear migrate journal after rollback (a retry may skip already-"done" tables)'
36798
37611
  );
@@ -36817,7 +37630,7 @@ function lockPath(dbPath) {
36817
37630
  }
36818
37631
  function acquireAdvisoryLock(dbPath) {
36819
37632
  const lp = lockPath(dbPath);
36820
- writeFileSync2(lp, JSON.stringify({ pid: process.pid, ts: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
37633
+ writeFileSync3(lp, JSON.stringify({ pid: process.pid, ts: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
36821
37634
  }
36822
37635
  function releaseAdvisoryLock(dbPath) {
36823
37636
  try {
@@ -36880,7 +37693,7 @@ function buildSelectExpr(attachAlias, legacyTable, targetTableName, col, srcType
36880
37693
  function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyTableName, sourceName, targetSchema = "main") {
36881
37694
  const resolution = resolveConsolidatedTableName(sourceName, legacyTableName);
36882
37695
  if (resolution.kind === "skip") {
36883
- log4.warn(
37696
+ log5.warn(
36884
37697
  { legacyTableName, sourceName, reason: resolution.reason },
36885
37698
  `Exodus: explicitly skipping table \u2014 ${resolution.reason}`
36886
37699
  );
@@ -36899,7 +37712,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36899
37712
  ).get();
36900
37713
  if (!existsRow) {
36901
37714
  const reason = `consolidated target '${targetTableName}' not found (mapped from legacy '${legacyTableName}')`;
36902
- log4.warn(
37715
+ log5.warn(
36903
37716
  { legacyTableName, targetTableName, sourceName, attachAlias, targetSchema },
36904
37717
  `Exodus: ${reason}`
36905
37718
  );
@@ -36910,13 +37723,13 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36910
37723
  const sharedColumns = srcPragma.map((r) => r.name).filter((col) => tgtColMap.has(col));
36911
37724
  if (sharedColumns.length === 0) {
36912
37725
  const reason = `no overlapping columns between source '${legacyTableName}' and target '${targetTableName}'`;
36913
- log4.warn({ legacyTableName, targetTableName, sourceName }, `Exodus: ${reason}`);
37726
+ log5.warn({ legacyTableName, targetTableName, sourceName }, `Exodus: ${reason}`);
36914
37727
  return { rowsCopied: 0, skipped: true, reason };
36915
37728
  }
36916
37729
  const srcOnlyColumns = srcPragma.map((r) => r.name).filter((c) => !tgtColMap.has(c));
36917
37730
  const tgtOnlyColumns = tgtPragma.map((r) => r.name).filter((c) => !srcColumns.has(c));
36918
37731
  if (srcOnlyColumns.length > 0 || tgtOnlyColumns.length > 0) {
36919
- log4.info(
37732
+ log5.info(
36920
37733
  { legacyTableName, targetTableName, sourceName, srcOnlyColumns, tgtOnlyColumns },
36921
37734
  "Exodus: column drift detected \u2014 copying intersection, dropping src-only cols, using defaults for tgt-only cols"
36922
37735
  );
@@ -36931,7 +37744,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36931
37744
  return isoGlobCols.has(col) && (upper.includes("INT") || upper === "" || upper === "NUMERIC");
36932
37745
  });
36933
37746
  if (coercedCols.length > 0) {
36934
- log4.info(
37747
+ log5.info(
36935
37748
  {
36936
37749
  legacyTableName,
36937
37750
  targetTableName,
@@ -36947,7 +37760,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36947
37760
  (col) => ENUM_NORMALIZATIONS.has(`${targetTableName}.${col}`)
36948
37761
  );
36949
37762
  if (normalizedCols.length > 0) {
36950
- log4.info(
37763
+ log5.info(
36951
37764
  { legacyTableName, targetTableName, sourceName, normalizedCols },
36952
37765
  `Exodus: applying enum-value normalization for ${normalizedCols.length} column(s) (T11547)`
36953
37766
  );
@@ -36956,7 +37769,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36956
37769
  (col) => NUMERIC_CLAMPS.has(`${targetTableName}.${col}`)
36957
37770
  );
36958
37771
  if (clampedCols.length > 0) {
36959
- log4.info(
37772
+ log5.info(
36960
37773
  { legacyTableName, targetTableName, sourceName, clampedCols },
36961
37774
  `Exodus: applying non-finite numeric clamp for ${clampedCols.length} column(s) (T11782)`
36962
37775
  );
@@ -36998,7 +37811,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
36998
37811
  if (rowsCopied < sourceCount) {
36999
37812
  const presentAccountedFor = existingBefore + rowsCopied;
37000
37813
  if (presentAccountedFor >= sourceCount) {
37001
- log4.info(
37814
+ log5.info(
37002
37815
  { legacyTableName, targetTableName, sourceName, sourceCount, rowsCopied, existingBefore },
37003
37816
  `Exodus: '${legacyTableName}'\u2192'${targetTableName}' \u2014 ${sourceCount - rowsCopied} of ${sourceCount} row(s) already present in target (idempotent PK dedup), ${rowsCopied} newly copied; no loss`
37004
37817
  );
@@ -37006,7 +37819,7 @@ function copyTableFromAttached(targetNativeDb, srcNativeDb, attachAlias, legacyT
37006
37819
  }
37007
37820
  const missing = sourceCount - presentAccountedFor;
37008
37821
  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.`;
37009
- log4.error(
37822
+ log5.error(
37010
37823
  {
37011
37824
  legacyTableName,
37012
37825
  targetTableName,
@@ -37026,10 +37839,10 @@ function checkSchemaVersion(journal, forceCrossVersion) {
37026
37839
  if (journal.targetSchemaVersion !== EXODUS_TARGET_SCHEMA_VERSION) {
37027
37840
  const msg = `Schema version mismatch: journal=${journal.targetSchemaVersion}, expected=${EXODUS_TARGET_SCHEMA_VERSION}`;
37028
37841
  if (forceCrossVersion) {
37029
- log4.warn(msg + " (--force-cross-version: continuing anyway)");
37842
+ log5.warn(msg + " (--force-cross-version: continuing anyway)");
37030
37843
  return true;
37031
37844
  }
37032
- log4.error(msg + " \u2014 pass --force-cross-version to override");
37845
+ log5.error(msg + " \u2014 pass --force-cross-version to override");
37033
37846
  return false;
37034
37847
  }
37035
37848
  return true;
@@ -37046,10 +37859,10 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress) {
37046
37859
  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.`
37047
37860
  };
37048
37861
  }
37049
- mkdirSync2(stagingDir, { recursive: true });
37862
+ mkdirSync3(stagingDir, { recursive: true });
37050
37863
  let sqliteVersion = "unknown";
37051
37864
  for (const src of sources) {
37052
- if (existsSync9(src.path)) {
37865
+ if (existsSync10(src.path)) {
37053
37866
  const snap = openCleoDbSnapshot(src.path, { readOnly: true });
37054
37867
  sqliteVersion = getSqliteVersion(snap.db);
37055
37868
  snap.close();
@@ -37090,15 +37903,15 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress) {
37090
37903
  };
37091
37904
  var extractNativeDb = extractNativeDb2;
37092
37905
  for (const src of sources) {
37093
- if (!existsSync9(src.path)) continue;
37094
- const backupDest = join11(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
37906
+ if (!existsSync10(src.path)) continue;
37907
+ const backupDest = join13(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
37095
37908
  const srcBytes = safeStatBytes(src.path);
37096
37909
  const skipStagingCopy = srcBytes > plan.stagingCopyThresholdBytes;
37097
37910
  if (skipStagingCopy) {
37098
37911
  onProgress?.(
37099
37912
  `Skipping full staging copy of ${src.name} (${srcBytes} bytes > ${plan.stagingCopyThresholdBytes} threshold) \u2014 source is archived, not deleted, on success.`
37100
37913
  );
37101
- } else if (!existsSync9(backupDest)) {
37914
+ } else if (!existsSync10(backupDest)) {
37102
37915
  onProgress?.(`Backing up ${src.name} \u2192 staging dir\u2026`);
37103
37916
  copyFileSync3(src.path, backupDest);
37104
37917
  backupPaths.push(backupDest);
@@ -37116,8 +37929,8 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress) {
37116
37929
  });
37117
37930
  const projectNative = extractNativeDb2(projectHandle);
37118
37931
  const globalNative = extractNativeDb2(globalHandle);
37119
- const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync9(s.path));
37120
- const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync9(s.path));
37932
+ const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync10(s.path));
37933
+ const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync10(s.path));
37121
37934
  await migrateScope(
37122
37935
  "project",
37123
37936
  projectSources,
@@ -37142,7 +37955,7 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress) {
37142
37955
  return { ok: true, tables: allTableResults, stagingDir, backupPaths };
37143
37956
  } catch (err) {
37144
37957
  const error48 = err instanceof Error ? err.message : String(err);
37145
- log4.error({ err }, "Exodus migration failed");
37958
+ log5.error({ err }, "Exodus migration failed");
37146
37959
  return { ok: false, tables: allTableResults, stagingDir, backupPaths, error: error48 };
37147
37960
  } finally {
37148
37961
  try {
@@ -37162,7 +37975,7 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37162
37975
  if (sources.length === 0) return;
37163
37976
  onProgress?.(`Migrating ${scope}-scope sources\u2026`);
37164
37977
  targetNativeDb.exec("PRAGMA foreign_keys = OFF");
37165
- log4.info({ scope }, "Exodus: foreign_keys=OFF for bulk copy (T11533 FK-defer)");
37978
+ log5.info({ scope }, "Exodus: foreign_keys=OFF for bulk copy (T11533 FK-defer)");
37166
37979
  try {
37167
37980
  for (let i = 0; i < sources.length; i++) {
37168
37981
  const src = sources[i];
@@ -37229,7 +38042,7 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37229
38042
  }
37230
38043
  } catch (err) {
37231
38044
  const msg = err instanceof Error ? err.message : String(err);
37232
- log4.warn({ tableName, sourceDb: src.name, err }, "Table copy failed \u2014 skipping");
38045
+ log5.warn({ tableName, sourceDb: src.name, err }, "Table copy failed \u2014 skipping");
37233
38046
  status = "skipped";
37234
38047
  errorMsg = msg;
37235
38048
  skipped = true;
@@ -37277,7 +38090,7 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37277
38090
  targetNativeDb.exec(`DETACH DATABASE "${attachAlias}"`);
37278
38091
  onProgress?.(` [${src.name}] Detached "${attachAlias}"`);
37279
38092
  } catch (detachErr) {
37280
- log4.warn(
38093
+ log5.warn(
37281
38094
  { attachAlias, sourceDb: src.name, err: detachErr },
37282
38095
  "DETACH failed \u2014 alias will be released on DB close"
37283
38096
  );
@@ -37287,7 +38100,7 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37287
38100
  targetNativeDb.exec(`DETACH DATABASE "${crossAlias}"`);
37288
38101
  onProgress?.(` [${src.name}] Cross-scope target detached "${crossAlias}"`);
37289
38102
  } catch (detachErr) {
37290
- log4.warn(
38103
+ log5.warn(
37291
38104
  { crossAlias, sourceDb: src.name, err: detachErr },
37292
38105
  "Cross-scope DETACH failed \u2014 alias will be released on DB close"
37293
38106
  );
@@ -37299,28 +38112,28 @@ async function migrateScope(scope, sources, targetNativeDb, journal, stagingDir,
37299
38112
  try {
37300
38113
  const orphans = targetNativeDb.prepare("PRAGMA foreign_key_check").all();
37301
38114
  if (orphans.length > 0) {
37302
- log4.warn(
38115
+ log5.warn(
37303
38116
  { scope, orphanCount: orphans.length, sample: orphans.slice(0, 5) },
37304
38117
  `Exodus: PRAGMA foreign_key_check found ${orphans.length} orphan row(s) after bulk copy \u2014 these are genuine data orphans (not ordering artifacts)`
37305
38118
  );
37306
38119
  } else {
37307
- log4.info({ scope }, "Exodus: PRAGMA foreign_key_check PASSED \u2014 no orphan rows");
38120
+ log5.info({ scope }, "Exodus: PRAGMA foreign_key_check PASSED \u2014 no orphan rows");
37308
38121
  }
37309
38122
  } catch (checkErr) {
37310
- log4.warn(
38123
+ log5.warn(
37311
38124
  { scope, err: checkErr },
37312
38125
  "Exodus: PRAGMA foreign_key_check failed (non-fatal) \u2014 target schema may not have FK constraints enabled"
37313
38126
  );
37314
38127
  }
37315
38128
  try {
37316
38129
  targetNativeDb.exec("PRAGMA foreign_keys = ON");
37317
- log4.info({ scope }, "Exodus: foreign_keys=ON restored after bulk copy");
38130
+ log5.info({ scope }, "Exodus: foreign_keys=ON restored after bulk copy");
37318
38131
  } catch (fkErr) {
37319
- log4.warn({ scope, err: fkErr }, "Exodus: could not restore foreign_keys=ON (non-fatal)");
38132
+ log5.warn({ scope, err: fkErr }, "Exodus: could not restore foreign_keys=ON (non-fatal)");
37320
38133
  }
37321
38134
  }
37322
38135
  }
37323
- var log4, LOCK_SENTINEL_SUFFIX, JOURNAL_FILENAME, SOURCE_EPOCH_UNITS;
38136
+ var log5, LOCK_SENTINEL_SUFFIX, JOURNAL_FILENAME, SOURCE_EPOCH_UNITS;
37324
38137
  var init_migrate = __esm({
37325
38138
  "packages/core/src/store/exodus/migrate.ts"() {
37326
38139
  "use strict";
@@ -37332,7 +38145,7 @@ var init_migrate = __esm({
37332
38145
  init_plan2();
37333
38146
  init_table_name_map();
37334
38147
  init_types();
37335
- log4 = getLogger("exodus-migrate");
38148
+ log5 = getLogger("exodus-migrate");
37336
38149
  LOCK_SENTINEL_SUFFIX = ".exodus-lock";
37337
38150
  JOURNAL_FILENAME = "exodus-journal.json";
37338
38151
  SOURCE_EPOCH_UNITS = /* @__PURE__ */ new Map([
@@ -37356,7 +38169,7 @@ function sealExodus(plan, scopeArg, cwd) {
37356
38169
  const parity = computeCountParity(plan.sources, plan.projectDbPath, plan.globalDbPath);
37357
38170
  if (!parity.ok) {
37358
38171
  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(", ")}`;
37359
- log5.error({ deficits: parity.deficits.length }, `exodus seal refused \u2014 ${refusedReason}`);
38172
+ log6.error({ deficits: parity.deficits.length }, `exodus seal refused \u2014 ${refusedReason}`);
37360
38173
  return { ok: false, refusedReason, parity, scopes: [] };
37361
38174
  }
37362
38175
  const outcomes = [];
@@ -37372,7 +38185,7 @@ function sealExodus(plan, scopeArg, cwd) {
37372
38185
  scopeSources.map((s) => s.name),
37373
38186
  cwd
37374
38187
  );
37375
- log5.info(
38188
+ log6.info(
37376
38189
  { scope, alreadySealed, archived: archived.filter((a) => a.action === "archived").length },
37377
38190
  `exodus seal: scope '${scope}' certified (count-parity verified, ${parity.checked} tables)`
37378
38191
  );
@@ -37380,23 +38193,23 @@ function sealExodus(plan, scopeArg, cwd) {
37380
38193
  }
37381
38194
  return { ok: true, parity, scopes: outcomes };
37382
38195
  }
37383
- var log5;
38196
+ var log6;
37384
38197
  var init_seal = __esm({
37385
38198
  "packages/core/src/store/exodus/seal.ts"() {
37386
38199
  "use strict";
37387
38200
  init_logger();
37388
38201
  init_archive2();
37389
38202
  init_count_parity();
37390
- log5 = getLogger("exodus-seal");
38203
+ log6 = getLogger("exodus-seal");
37391
38204
  }
37392
38205
  });
37393
38206
 
37394
38207
  // packages/core/src/store/exodus/status.ts
37395
- import { existsSync as existsSync10, readdirSync as readdirSync3, readFileSync as readFileSync4, statSync as statSync4 } from "node:fs";
37396
- import { join as join12 } from "node:path";
38208
+ import { existsSync as existsSync11, readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync4 } from "node:fs";
38209
+ import { join as join14 } from "node:path";
37397
38210
  function readJournal2(stagingDir) {
37398
- const p = join12(stagingDir, JOURNAL_FILENAME2);
37399
- if (!existsSync10(p)) return null;
38211
+ const p = join14(stagingDir, JOURNAL_FILENAME2);
38212
+ if (!existsSync11(p)) return null;
37400
38213
  try {
37401
38214
  return JSON.parse(readFileSync4(p, "utf8"));
37402
38215
  } catch {
@@ -37405,7 +38218,7 @@ function readJournal2(stagingDir) {
37405
38218
  }
37406
38219
  function findStagingDirs(cleoDir) {
37407
38220
  try {
37408
- return readdirSync3(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join12(cleoDir, e.name)).sort().reverse();
38221
+ return readdirSync4(cleoDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("exodus-staging-")).map((e) => join14(cleoDir, e.name)).sort().reverse();
37409
38222
  } catch {
37410
38223
  return [];
37411
38224
  }
@@ -37428,15 +38241,15 @@ function runExodusStatus(cwd) {
37428
38241
  const sourcesInfo = plan.sources.map((s) => ({
37429
38242
  name: s.name,
37430
38243
  path: s.path,
37431
- exists: existsSync10(s.path),
38244
+ exists: existsSync11(s.path),
37432
38245
  bytes: safeBytes(s.path)
37433
38246
  }));
37434
38247
  return {
37435
38248
  hasStaging: latestStaging !== null,
37436
38249
  stagingDir: latestStaging,
37437
38250
  journal,
37438
- projectDbExists: existsSync10(projectDbPath),
37439
- globalDbExists: existsSync10(globalDbPath),
38251
+ projectDbExists: existsSync11(projectDbPath),
38252
+ globalDbExists: existsSync11(globalDbPath),
37440
38253
  sourcesPresent: sourcesInfo.some((s) => s.exists),
37441
38254
  sources: sourcesInfo
37442
38255
  };
@@ -37453,7 +38266,7 @@ var init_status = __esm({
37453
38266
  });
37454
38267
 
37455
38268
  // packages/core/src/store/exodus/verify-migration.ts
37456
- import { existsSync as existsSync11 } from "node:fs";
38269
+ import { existsSync as existsSync12 } from "node:fs";
37457
38270
  import { createRequire as createRequire3 } from "node:module";
37458
38271
  function orderByClause(db, tableName) {
37459
38272
  try {
@@ -37473,7 +38286,7 @@ function computeTableDigest(db, tableName, columns, transform2) {
37473
38286
  count = Number(row?.c ?? 0);
37474
38287
  } catch (err) {
37475
38288
  const msg = err instanceof Error ? err.message : String(err);
37476
- log6.warn(
38289
+ log7.warn(
37477
38290
  { tableName, err: msg },
37478
38291
  "computeTableDigest: COUNT(*) failed (possibly a virtual/FTS table) \u2014 treating as 0 rows"
37479
38292
  );
@@ -37508,7 +38321,7 @@ function computeTableDigest(db, tableName, columns, transform2) {
37508
38321
  }
37509
38322
  } catch (err) {
37510
38323
  const msg = err instanceof Error ? err.message : String(err);
37511
- log6.warn(
38324
+ log7.warn(
37512
38325
  { tableName, err: msg },
37513
38326
  "computeTableDigest: streamed SELECT failed (possibly a virtual/FTS table) \u2014 digest skipped (COUNT(*) parity still enforced)"
37514
38327
  );
@@ -37634,7 +38447,7 @@ function foreignKeyCheck(db, scope) {
37634
38447
  try {
37635
38448
  const rows = db.prepare("PRAGMA foreign_key_check").all();
37636
38449
  if (rows.length > 0) {
37637
- log6.warn(
38450
+ log7.warn(
37638
38451
  { scope, count: rows.length, sample: rows.slice(0, 5) },
37639
38452
  `verifyMigration: PRAGMA foreign_key_check found ${rows.length} orphan row(s)`
37640
38453
  );
@@ -37646,7 +38459,7 @@ function foreignKeyCheck(db, scope) {
37646
38459
  fkid: r.fkid
37647
38460
  }));
37648
38461
  } catch (err) {
37649
- log6.warn({ scope, err }, "verifyMigration: PRAGMA foreign_key_check failed (non-fatal)");
38462
+ log7.warn({ scope, err }, "verifyMigration: PRAGMA foreign_key_check failed (non-fatal)");
37650
38463
  return [];
37651
38464
  }
37652
38465
  }
@@ -37683,13 +38496,13 @@ function sourceOrphanSignatures(db, sourceName, scope) {
37683
38496
  const rows = db.prepare("PRAGMA foreign_key_check").all();
37684
38497
  for (const r of rows) sigs.add(orphanSignature(db, r, sourceName));
37685
38498
  if (rows.length > 0) {
37686
- log6.warn(
38499
+ log7.warn(
37687
38500
  { scope, count: rows.length, sample: rows.slice(0, 5) },
37688
38501
  `verifyMigration: source already has ${rows.length} pre-existing FK orphan(s) \u2014 these are tolerated (carried forward losslessly, flagged for data-hygiene)`
37689
38502
  );
37690
38503
  }
37691
38504
  } catch (err) {
37692
- log6.warn({ scope, err }, "verifyMigration: source PRAGMA foreign_key_check failed (non-fatal)");
38505
+ log7.warn({ scope, err }, "verifyMigration: source PRAGMA foreign_key_check failed (non-fatal)");
37693
38506
  }
37694
38507
  return sigs;
37695
38508
  }
@@ -37701,7 +38514,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37701
38514
  const preExistingForeignKeyViolations = [];
37702
38515
  const failureLines = [];
37703
38516
  const sourceOrphanSigs = /* @__PURE__ */ new Set();
37704
- if (!existsSync11(projectDbPath)) {
38517
+ if (!existsSync12(projectDbPath)) {
37705
38518
  return {
37706
38519
  ok: false,
37707
38520
  tables: [],
@@ -37712,7 +38525,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37712
38525
  error: `Consolidated project cleo.db not found at ${projectDbPath}. Run 'cleo exodus migrate' first.`
37713
38526
  };
37714
38527
  }
37715
- if (!existsSync11(globalDbPath)) {
38528
+ if (!existsSync12(globalDbPath)) {
37716
38529
  return {
37717
38530
  ok: false,
37718
38531
  tables: [],
@@ -37727,7 +38540,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37727
38540
  const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
37728
38541
  try {
37729
38542
  for (const src of sources) {
37730
- if (!existsSync11(src.path)) {
38543
+ if (!existsSync12(src.path)) {
37731
38544
  onProgress?.(`Skipping ${src.name} (not present)`);
37732
38545
  continue;
37733
38546
  }
@@ -37812,7 +38625,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37812
38625
  `[${scope}] ${src.name}.${legacyTableName} \u2192 ${targetTableName}: DEFICIT \u2014 source=${srcDigest.count} rows, target=${tgtDigest.count} rows (${srcDigest.count - tgtDigest.count} missing), hashMatch=${hashMatch}`
37813
38626
  );
37814
38627
  } else if (tgtDigest.count > srcDigest.count) {
37815
- log6.warn(
38628
+ log7.warn(
37816
38629
  {
37817
38630
  scope,
37818
38631
  source: src.name,
@@ -37862,7 +38675,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37862
38675
  }
37863
38676
  }
37864
38677
  if (preExistingForeignKeyViolations.length > 0) {
37865
- log6.warn(
38678
+ log7.warn(
37866
38679
  {
37867
38680
  count: preExistingForeignKeyViolations.length,
37868
38681
  sample: preExistingForeignKeyViolations.slice(0, 5)
@@ -37872,7 +38685,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37872
38685
  }
37873
38686
  } catch (err) {
37874
38687
  const error48 = err instanceof Error ? err.message : String(err);
37875
- log6.error({ err }, "verifyMigration failed");
38688
+ log7.error({ err }, "verifyMigration failed");
37876
38689
  return {
37877
38690
  ok: false,
37878
38691
  tables,
@@ -37889,7 +38702,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress) {
37889
38702
  if (failureLines.length > 0) {
37890
38703
  const error48 = `verifyMigration FAILED: ${failureLines.length} issue(s):
37891
38704
  ${failureLines.map((l) => ` \u2022 ${l}`).join("\n")}`;
37892
- log6.error({ failureCount: failureLines.length }, error48);
38705
+ log7.error({ failureCount: failureLines.length }, error48);
37893
38706
  return {
37894
38707
  ok: false,
37895
38708
  tables,
@@ -37909,7 +38722,7 @@ ${failureLines.map((l) => ` \u2022 ${l}`).join("\n")}`;
37909
38722
  enumDrift
37910
38723
  };
37911
38724
  }
37912
- var log6, _require, CHECK_ENUM_REGEX;
38725
+ var log7, _require, CHECK_ENUM_REGEX;
37913
38726
  var init_verify_migration = __esm({
37914
38727
  "packages/core/src/store/exodus/verify-migration.ts"() {
37915
38728
  "use strict";
@@ -37918,7 +38731,7 @@ var init_verify_migration = __esm({
37918
38731
  init_open_cleo_db();
37919
38732
  init_column_transforms();
37920
38733
  init_table_name_map();
37921
- log6 = getLogger("verify-migration");
38734
+ log7 = getLogger("verify-migration");
37922
38735
  _require = createRequire3(import.meta.url);
37923
38736
  CHECK_ENUM_REGEX = /CHECK\s*\(\s*"([^"]+)"\s+(?:IS\s+NULL\s+OR\s+"[^"]+"\s+)?IN\s*\(([^)]*)\)\s*\)/gi;
37924
38737
  }
@@ -38010,7 +38823,7 @@ __export(on_open_exports, {
38010
38823
  isDataContinuityOk: () => isDataContinuityOk,
38011
38824
  maybeRunExodusOnOpen: () => maybeRunExodusOnOpen
38012
38825
  });
38013
- import { existsSync as existsSync12 } from "node:fs";
38826
+ import { existsSync as existsSync13 } from "node:fs";
38014
38827
  function isDisabledByEnv() {
38015
38828
  const v = process.env.CLEO_DISABLE_EXODUS_ON_OPEN;
38016
38829
  return v === "1" || v === "true";
@@ -38036,7 +38849,7 @@ function rollbackConsolidatedToEmpty(nativeDb, scope) {
38036
38849
  "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%'"
38037
38850
  ).all().map((r) => r.name);
38038
38851
  } catch (err) {
38039
- log7.error({ err, scope }, "exodus-on-open: failed to enumerate tables for rollback");
38852
+ log8.error({ err, scope }, "exodus-on-open: failed to enumerate tables for rollback");
38040
38853
  return;
38041
38854
  }
38042
38855
  try {
@@ -38046,7 +38859,7 @@ function rollbackConsolidatedToEmpty(nativeDb, scope) {
38046
38859
  try {
38047
38860
  nativeDb.exec(`DELETE FROM "${table}"`);
38048
38861
  } catch (err) {
38049
- log7.warn({ err, table, scope }, "exodus-on-open: failed to clear table during rollback");
38862
+ log8.warn({ err, table, scope }, "exodus-on-open: failed to clear table during rollback");
38050
38863
  }
38051
38864
  }
38052
38865
  nativeDb.exec("COMMIT");
@@ -38055,7 +38868,7 @@ function rollbackConsolidatedToEmpty(nativeDb, scope) {
38055
38868
  nativeDb.exec("ROLLBACK");
38056
38869
  } catch {
38057
38870
  }
38058
- log7.error({ err, scope }, "exodus-on-open: rollback transaction failed");
38871
+ log8.error({ err, scope }, "exodus-on-open: rollback transaction failed");
38059
38872
  } finally {
38060
38873
  try {
38061
38874
  nativeDb.exec("PRAGMA foreign_keys = ON");
@@ -38075,7 +38888,7 @@ async function rollbackBothScopes(scope, projectDbPath, globalDbPath) {
38075
38888
  rollbackConsolidatedToEmpty(native, s);
38076
38889
  }
38077
38890
  } catch (err) {
38078
- log7.warn(
38891
+ log8.warn(
38079
38892
  { err, scope: s, openingScope: scope },
38080
38893
  "exodus-on-open: could not roll back scope (best-effort)"
38081
38894
  );
@@ -38091,7 +38904,7 @@ function isDataContinuityOk(result) {
38091
38904
  const deficits = result.tables.filter((t) => t.targetCount < t.sourceCount);
38092
38905
  const surpluses = result.tables.filter((t) => t.targetCount > t.sourceCount);
38093
38906
  if (surpluses.length > 0) {
38094
- log7.warn(
38907
+ log8.warn(
38095
38908
  {
38096
38909
  surpluses: surpluses.map((t) => ({
38097
38910
  table: t.targetTable,
@@ -38125,7 +38938,7 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38125
38938
  const { buildExodusPlan: buildExodusPlan2, runExodusMigrate: runExodusMigrate2, verifyMigration: verifyMigration2, clearExodusJournal: clearExodusJournal2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
38126
38939
  const plan = buildExodusPlan2(cwd);
38127
38940
  const scopeSources = plan.sources.filter((s) => s.targetScope === scope);
38128
- if (!scopeSources.some((s) => existsSync12(s.path))) {
38941
+ if (!scopeSources.some((s) => existsSync13(s.path))) {
38129
38942
  return {
38130
38943
  outcome: "skipped",
38131
38944
  reason: `no legacy ${scope}-scope source DBs present (fresh install or cross-scope-only)`
@@ -38138,11 +38951,11 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38138
38951
  if (!consolidatedIsEmpty(nativeDb, scope)) {
38139
38952
  return { outcome: "skipped", reason: "migrated by a concurrent process (lock winner)" };
38140
38953
  }
38141
- log7.info(
38954
+ log8.info(
38142
38955
  {
38143
38956
  scope,
38144
38957
  dbPath,
38145
- sources: plan.sources.filter((s) => existsSync12(s.path)).map((s) => s.name)
38958
+ sources: plan.sources.filter((s) => existsSync13(s.path)).map((s) => s.name)
38146
38959
  },
38147
38960
  "exodus-on-open: consolidated cleo.db is empty and legacy data present \u2014 auto-migrating"
38148
38961
  );
@@ -38151,23 +38964,23 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38151
38964
  const migrateResult = await runExodusMigrate2(
38152
38965
  plan,
38153
38966
  false,
38154
- (msg) => log7.debug({ scope }, `exodus-on-open: ${msg}`)
38967
+ (msg) => log8.debug({ scope }, `exodus-on-open: ${msg}`)
38155
38968
  );
38156
38969
  if (!migrateResult.ok) {
38157
38970
  await rollbackBothScopes(scope, plan.projectDbPath, plan.globalDbPath);
38158
38971
  clearExodusJournal2(migrateResult.stagingDir);
38159
38972
  const reason = `migration failed: ${migrateResult.error ?? "unknown error"} \u2014 legacy DBs kept as source`;
38160
- log7.error({ scope, error: migrateResult.error }, `exodus-on-open: ${reason}`);
38973
+ log8.error({ scope, error: migrateResult.error }, `exodus-on-open: ${reason}`);
38161
38974
  return { outcome: "aborted", reason };
38162
38975
  }
38163
38976
  const verifyResult = verifyMigration2(
38164
38977
  plan.sources,
38165
38978
  plan.projectDbPath,
38166
38979
  plan.globalDbPath,
38167
- (msg) => log7.debug({ scope }, `exodus-on-open verify: ${msg}`)
38980
+ (msg) => log8.debug({ scope }, `exodus-on-open verify: ${msg}`)
38168
38981
  );
38169
38982
  if (!verifyResult.ok) {
38170
- log7.warn(
38983
+ log8.warn(
38171
38984
  {
38172
38985
  scope,
38173
38986
  enumDrift: verifyResult.enumDrift.length,
@@ -38181,7 +38994,7 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38181
38994
  clearExodusJournal2(plan.stagingDir);
38182
38995
  const deficits = verifyResult.tables.filter((t) => t.targetCount < t.sourceCount).map((t) => `${t.targetTable}(${t.sourceCount}\u2192${t.targetCount})`);
38183
38996
  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();
38184
- log7.error(
38997
+ log8.error(
38185
38998
  {
38186
38999
  scope,
38187
39000
  countDeficits: deficits,
@@ -38193,14 +39006,14 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38193
39006
  return { outcome: "aborted", reason };
38194
39007
  }
38195
39008
  const rowsCopied = migrateResult.tables.filter((t) => !t.skipped).reduce((n, t) => n + t.rowsCopied, 0);
38196
- log7.info(
39009
+ log8.info(
38197
39010
  { scope, rowsCopied, tables: migrateResult.tables.length },
38198
39011
  "exodus-on-open: parity verified \u2014 legacy data migrated into consolidated cleo.db"
38199
39012
  );
38200
39013
  try {
38201
- const consumed = plan.sources.filter((s) => existsSync12(s.path));
39014
+ const consumed = plan.sources.filter((s) => existsSync13(s.path));
38202
39015
  const archiveResult = archiveMigratedSources(consumed, cwd);
38203
- log7.info(
39016
+ log8.info(
38204
39017
  {
38205
39018
  scope,
38206
39019
  archived: archiveResult.sources.filter((s) => s.action === "archived").length,
@@ -38209,7 +39022,7 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38209
39022
  "exodus-on-open: archived legacy sources + sealed completion marker(s)"
38210
39023
  );
38211
39024
  } catch (err) {
38212
- log7.error(
39025
+ log8.error(
38213
39026
  { err, scope },
38214
39027
  "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`)"
38215
39028
  );
@@ -38231,14 +39044,14 @@ async function maybeRunExodusOnOpen(scope, dbPath, nativeDb, cwd) {
38231
39044
  function _isExodusInProgress() {
38232
39045
  return _exodusInProgress;
38233
39046
  }
38234
- var log7, _exodusInProgress;
39047
+ var log8, _exodusInProgress;
38235
39048
  var init_on_open = __esm({
38236
39049
  "packages/core/src/store/exodus/on-open.ts"() {
38237
39050
  "use strict";
38238
39051
  init_logger();
38239
39052
  init_lock();
38240
39053
  init_archive2();
38241
- log7 = getLogger("exodus-on-open");
39054
+ log8 = getLogger("exodus-on-open");
38242
39055
  _exodusInProgress = false;
38243
39056
  }
38244
39057
  });
@@ -38255,9 +39068,9 @@ __export(dual_scope_db_exports, {
38255
39068
  resolveDualScopeDbPath: () => resolveDualScopeDbPath,
38256
39069
  upsertIdempotent: () => upsertIdempotent
38257
39070
  });
38258
- import { existsSync as existsSync13, mkdirSync as mkdirSync3 } from "node:fs";
39071
+ import { existsSync as existsSync14, mkdirSync as mkdirSync4 } from "node:fs";
38259
39072
  import { createRequire as createRequire4 } from "node:module";
38260
- import { dirname as dirname6, join as join13 } from "node:path";
39073
+ import { dirname as dirname6, join as join15 } from "node:path";
38261
39074
  function assertWriteDurable(handle) {
38262
39075
  if (handle.exodusAbort) {
38263
39076
  throw new ExodusAbortWriteUnsafeError(handle.exodusAbort);
@@ -38274,9 +39087,9 @@ function cacheKey(scope, dbPath) {
38274
39087
  }
38275
39088
  function resolveDualScopeDbPath(scope, cwd) {
38276
39089
  if (scope === "project") {
38277
- return join13(resolveCleoDir(cwd), "cleo.db");
39090
+ return join15(resolveCleoDir(cwd), "cleo.db");
38278
39091
  }
38279
- return join13(getCleoHome(), "cleo.db");
39092
+ return join15(getCleoHome(), "cleo.db");
38280
39093
  }
38281
39094
  function migrationsSetName(scope) {
38282
39095
  return scope === "project" ? "drizzle-cleo-project" : "drizzle-cleo-global";
@@ -38319,11 +39132,11 @@ async function openDualScopeDb(scope, cwd) {
38319
39132
  const dbPath = resolveDualScopeDbPath(scope, cwd);
38320
39133
  return scope === "project" ? openDualScopeDbAtPath("project", dbPath, cwd) : openDualScopeDbAtPath("global", dbPath, cwd);
38321
39134
  }
38322
- async function openDedicatedDualScopeDb(scope, dbPath, log8) {
38323
- log8.debug({ scope, dbPath }, "opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)");
39135
+ async function openDedicatedDualScopeDb(scope, dbPath, log9) {
39136
+ log9.debug({ scope, dbPath }, "opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)");
38324
39137
  const dir = dirname6(dbPath);
38325
- if (!existsSync13(dir)) {
38326
- mkdirSync3(dir, { recursive: true });
39138
+ if (!existsSync14(dir)) {
39139
+ mkdirSync4(dir, { recursive: true });
38327
39140
  }
38328
39141
  const DatabaseSyncCtor = getDatabaseSyncCtor();
38329
39142
  const nativeDb = new DatabaseSyncCtor(dbPath, { allowExtension: true });
@@ -38346,7 +39159,7 @@ async function openDedicatedDualScopeDb(scope, dbPath, log8) {
38346
39159
  existenceTable(scope),
38347
39160
  `dual-scope-db[${scope}]`
38348
39161
  );
38349
- log8.debug({ scope, dbPath }, "DEDICATED dual-scope cleo.db ready (T11782 FIX D)");
39162
+ log9.debug({ scope, dbPath }, "DEDICATED dual-scope cleo.db ready (T11782 FIX D)");
38350
39163
  return {
38351
39164
  db,
38352
39165
  scope,
@@ -38371,15 +39184,15 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38371
39184
  return existing.handle;
38372
39185
  }
38373
39186
  }
38374
- const log8 = getLogger("dual-scope-db");
39187
+ const log9 = getLogger("dual-scope-db");
38375
39188
  if (dedicated) {
38376
- return openDedicatedDualScopeDb(scope, dbPath, log8);
39189
+ return openDedicatedDualScopeDb(scope, dbPath, log9);
38377
39190
  }
38378
39191
  const initPromise = (async () => {
38379
- log8.debug({ scope, dbPath }, "opening dual-scope cleo.db");
39192
+ log9.debug({ scope, dbPath }, "opening dual-scope cleo.db");
38380
39193
  const dir = dirname6(dbPath);
38381
- if (!existsSync13(dir)) {
38382
- mkdirSync3(dir, { recursive: true });
39194
+ if (!existsSync14(dir)) {
39195
+ mkdirSync4(dir, { recursive: true });
38383
39196
  }
38384
39197
  const DatabaseSyncCtor = getDatabaseSyncCtor();
38385
39198
  const nativeDb = new DatabaseSyncCtor(dbPath, { allowExtension: true });
@@ -38406,7 +39219,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38406
39219
  existenceTable(scope),
38407
39220
  `dual-scope-db[${scope}]`
38408
39221
  );
38409
- log8.debug({ scope, dbPath }, "dual-scope cleo.db ready");
39222
+ log9.debug({ scope, dbPath }, "dual-scope cleo.db ready");
38410
39223
  const built = {
38411
39224
  db,
38412
39225
  scope,
@@ -38432,6 +39245,25 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38432
39245
  { dbPath }
38433
39246
  );
38434
39247
  if (exodusCwd !== void 0 && dbPath === resolveDualScopeDbPath(scope, exodusCwd)) {
39248
+ let releaseDbHeavy = null;
39249
+ let dbHeavyDeferred = false;
39250
+ try {
39251
+ const { governor: governor2 } = await Promise.resolve().then(() => (init_governor(), governor_exports));
39252
+ const admit = await governor2.tryAcquire("db-heavy");
39253
+ if (admit.deferred) {
39254
+ dbHeavyDeferred = true;
39255
+ } else {
39256
+ releaseDbHeavy = admit.release;
39257
+ }
39258
+ } catch {
39259
+ }
39260
+ if (dbHeavyDeferred) {
39261
+ log9.debug(
39262
+ { scope, dbPath },
39263
+ "exodus-on-open skipped this open \u2014 db-heavy deferred under memory pressure (re-runs idempotently on a calmer open)"
39264
+ );
39265
+ return handle;
39266
+ }
38435
39267
  try {
38436
39268
  const { maybeRunExodusOnOpen: maybeRunExodusOnOpen2 } = await Promise.resolve().then(() => (init_on_open(), on_open_exports));
38437
39269
  const result = await maybeRunExodusOnOpen2(scope, dbPath, nativeDb, exodusCwd);
@@ -38444,7 +39276,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38444
39276
  reason: result.reason,
38445
39277
  at: Date.now()
38446
39278
  };
38447
- log8.warn(
39279
+ log9.warn(
38448
39280
  { scope, reason: result.reason },
38449
39281
  "exodus-on-open aborted; consolidated cleo.db left empty, legacy kept as source \u2014 mutating callers must check handle.exodusAbort / call assertWriteDurable (T11828)"
38450
39282
  );
@@ -38457,11 +39289,14 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
38457
39289
  return reopened;
38458
39290
  }
38459
39291
  } catch (err) {
38460
- log8.warn(
39292
+ log9.warn(
38461
39293
  { err, scope },
38462
39294
  "exodus-on-open hook failed (non-fatal); re-opening consolidated handle"
38463
39295
  );
38464
39296
  return scope === "project" ? openDualScopeDbAtPath("project", dbPath) : openDualScopeDbAtPath("global", dbPath);
39297
+ } finally {
39298
+ if (releaseDbHeavy) await releaseDbHeavy().catch(() => {
39299
+ });
38465
39300
  }
38466
39301
  }
38467
39302
  return handle;
@@ -39084,8 +39919,8 @@ __export(nexus_sqlite_exports, {
39084
39919
  resetNexusDbState: () => resetNexusDbState,
39085
39920
  resolveNexusMigrationsFolder: () => resolveNexusMigrationsFolder
39086
39921
  });
39087
- import { copyFileSync as copyFileSync4, existsSync as existsSync14 } from "node:fs";
39088
- import { join as join14 } from "node:path";
39922
+ import { copyFileSync as copyFileSync4, existsSync as existsSync15 } from "node:fs";
39923
+ import { join as join16 } from "node:path";
39089
39924
  function getNexusDbPath(cwd) {
39090
39925
  return resolveDualScopeDbPath("project", cwd);
39091
39926
  }
@@ -39117,7 +39952,7 @@ function resolveNexusMigrationsFolder() {
39117
39952
  return resolveCorePackageMigrationsFolder("drizzle-nexus");
39118
39953
  }
39119
39954
  function getNestedNexusSentinelPath() {
39120
- return join14(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
39955
+ return join16(getCleoHome(), "nexus", NESTED_NEXUS_SENTINEL);
39121
39956
  }
39122
39957
  function detectAndWarnOnNestedNexus() {
39123
39958
  let nestedPath;
@@ -39126,12 +39961,12 @@ function detectAndWarnOnNestedNexus() {
39126
39961
  } catch {
39127
39962
  return false;
39128
39963
  }
39129
- if (!existsSync14(nestedPath)) return false;
39964
+ if (!existsSync15(nestedPath)) return false;
39130
39965
  if (_warnedNestedPaths.has(nestedPath)) return false;
39131
39966
  _warnedNestedPaths.add(nestedPath);
39132
39967
  const canonicalPath = getNexusDbPath();
39133
- const log8 = getLogger("nexus-sqlite");
39134
- log8.warn(
39968
+ const log9 = getLogger("nexus-sqlite");
39969
+ log9.warn(
39135
39970
  {
39136
39971
  nestedPath,
39137
39972
  canonicalPath,
@@ -39285,7 +40120,7 @@ function runNexusMigrations(nativeDb, db) {
39285
40120
  const migrationsFolder = resolveNexusMigrationsFolder();
39286
40121
  if (tableExists4(nativeDb, "nexus_nodes") && _nexusDbPath) {
39287
40122
  const backupPath = _nexusDbPath.replace(/\.db$/, "-pre-cleo.db.bak");
39288
- if (!existsSync14(backupPath)) {
40123
+ if (!existsSync15(backupPath)) {
39289
40124
  try {
39290
40125
  copyFileSync4(_nexusDbPath, backupPath);
39291
40126
  } catch {
@@ -39423,10 +40258,10 @@ var init_nexus_sqlite = __esm({
39423
40258
 
39424
40259
  // packages/core/src/paths.ts
39425
40260
  import { AsyncLocalStorage } from "node:async_hooks";
39426
- import { existsSync as existsSync15, readFileSync as readFileSync5, statSync as statSync5 } from "node:fs";
40261
+ import { existsSync as existsSync16, readFileSync as readFileSync5, statSync as statSync5 } from "node:fs";
39427
40262
  import { createRequire as createRequire5 } from "node:module";
39428
40263
  import { homedir } from "node:os";
39429
- import { basename as basename4, dirname as dirname7, join as join15, resolve as resolve3 } from "node:path";
40264
+ import { basename as basename4, dirname as dirname7, join as join17, resolve as resolve3 } from "node:path";
39430
40265
  import {
39431
40266
  computeCanonicalProjectId as _computeCanonicalProjectId,
39432
40267
  getCanonicalTemplatesTildePath as _getCanonicalTemplatesTildePath,
@@ -39516,8 +40351,8 @@ function getCleoDirAbsolute(cwd, opts) {
39516
40351
  function _resolveProjectByCwdFromNexus(cwd) {
39517
40352
  try {
39518
40353
  const cleoHome = getCleoHome();
39519
- const globalDbPath = join15(cleoHome, "cleo.db");
39520
- if (!existsSync15(globalDbPath)) return null;
40354
+ const globalDbPath = join17(cleoHome, "cleo.db");
40355
+ if (!existsSync16(globalDbPath)) return null;
39521
40356
  const start = resolve3(cwd ?? process.cwd());
39522
40357
  let current = start;
39523
40358
  const DatabaseSync2 = _getDatabaseSyncCtor();
@@ -39556,7 +40391,7 @@ function _findCleoDirRoot(cwd) {
39556
40391
  const isDangerousRoot = current === homeRoot || current === "/" || current === "";
39557
40392
  if (!isDangerousRoot) {
39558
40393
  try {
39559
- if (statSync5(join15(current, ".cleo")).isDirectory()) {
40394
+ if (statSync5(join17(current, ".cleo")).isDirectory()) {
39560
40395
  return current;
39561
40396
  }
39562
40397
  } catch {
@@ -39571,7 +40406,7 @@ function _findCleoDirRoot(cwd) {
39571
40406
  function resolveCleoDir(cwd) {
39572
40407
  const scope = worktreeScope.getStore();
39573
40408
  if (scope !== void 0) {
39574
- return join15(scope.worktreeRoot, ".cleo");
40409
+ return join17(scope.worktreeRoot, ".cleo");
39575
40410
  }
39576
40411
  const override = _cleoDirEnvOverride();
39577
40412
  if (override !== null) {
@@ -39579,14 +40414,14 @@ function resolveCleoDir(cwd) {
39579
40414
  }
39580
40415
  const root = _findCleoDirRoot(cwd);
39581
40416
  if (root !== null) {
39582
- return join15(root, ".cleo");
40417
+ return join17(root, ".cleo");
39583
40418
  }
39584
40419
  const start = resolve3(cwd ?? process.cwd());
39585
40420
  let current = start;
39586
40421
  while (true) {
39587
40422
  const mainRepo = _resolveMainRepoFromGitlink(current);
39588
40423
  if (mainRepo !== null) {
39589
- return join15(mainRepo, ".cleo");
40424
+ return join17(mainRepo, ".cleo");
39590
40425
  }
39591
40426
  const parent = dirname7(current);
39592
40427
  if (parent === current) {
@@ -39628,9 +40463,9 @@ function _cwdHasGitAncestor(cwd) {
39628
40463
  const start = resolve3(cwd ?? process.cwd());
39629
40464
  let current = start;
39630
40465
  while (true) {
39631
- const gitMarker = join15(current, ".git");
40466
+ const gitMarker = join17(current, ".git");
39632
40467
  try {
39633
- if (existsSync15(gitMarker)) {
40468
+ if (existsSync16(gitMarker)) {
39634
40469
  return true;
39635
40470
  }
39636
40471
  } catch {
@@ -39642,16 +40477,16 @@ function _cwdHasGitAncestor(cwd) {
39642
40477
  }
39643
40478
  function _resolveMainRepoFromGitlink(gitlinkDir) {
39644
40479
  try {
39645
- const gitLinkPath = join15(gitlinkDir, ".git");
39646
- if (!existsSync15(gitLinkPath)) return null;
39647
- const stat2 = statSync5(gitLinkPath);
39648
- if (!stat2.isFile()) return null;
40480
+ const gitLinkPath = join17(gitlinkDir, ".git");
40481
+ if (!existsSync16(gitLinkPath)) return null;
40482
+ const stat3 = statSync5(gitLinkPath);
40483
+ if (!stat3.isFile()) return null;
39649
40484
  const gitLinkContent = readFileSync5(gitLinkPath, "utf-8").trim();
39650
40485
  const match = gitLinkContent.match(/^gitdir:\s*(.+)$/m);
39651
40486
  if (!match) return null;
39652
40487
  const gitdir = match[1].trim();
39653
40488
  const mainRepo = dirname7(dirname7(dirname7(gitdir)));
39654
- if (existsSync15(join15(mainRepo, ".cleo")) && validateProjectRoot(mainRepo)) {
40489
+ if (existsSync16(join17(mainRepo, ".cleo")) && validateProjectRoot(mainRepo)) {
39655
40490
  return mainRepo;
39656
40491
  }
39657
40492
  } catch {
@@ -39659,18 +40494,18 @@ function _resolveMainRepoFromGitlink(gitlinkDir) {
39659
40494
  return null;
39660
40495
  }
39661
40496
  function validateProjectRoot(candidate) {
39662
- const cleoDir = join15(candidate, ".cleo");
39663
- if (!existsSync15(cleoDir)) {
40497
+ const cleoDir = join17(candidate, ".cleo");
40498
+ if (!existsSync16(cleoDir)) {
39664
40499
  return false;
39665
40500
  }
39666
- const projectInfoPath = join15(cleoDir, "project-info.json");
39667
- if (existsSync15(projectInfoPath)) {
40501
+ const projectInfoPath = join17(cleoDir, "project-info.json");
40502
+ if (existsSync16(projectInfoPath)) {
39668
40503
  try {
39669
40504
  const raw = readFileSync5(projectInfoPath, "utf-8");
39670
40505
  const parsed = JSON.parse(raw);
39671
40506
  if (typeof parsed === "object" && parsed !== null && "projectId" in parsed && typeof parsed["projectId"] === "string" && parsed["projectId"] !== "") {
39672
- const gitMarker = join15(candidate, ".git");
39673
- if (existsSync15(gitMarker)) {
40507
+ const gitMarker = join17(candidate, ".git");
40508
+ if (existsSync16(gitMarker)) {
39674
40509
  try {
39675
40510
  if (!statSync5(gitMarker).isDirectory()) {
39676
40511
  return false;
@@ -39684,12 +40519,12 @@ function validateProjectRoot(candidate) {
39684
40519
  } catch {
39685
40520
  }
39686
40521
  }
39687
- const gitDir = join15(candidate, ".git");
39688
- if (existsSync15(gitDir)) {
40522
+ const gitDir = join17(candidate, ".git");
40523
+ if (existsSync16(gitDir)) {
39689
40524
  let isRealGitDir = false;
39690
40525
  try {
39691
- const stat2 = statSync5(gitDir);
39692
- isRealGitDir = stat2.isDirectory();
40526
+ const stat3 = statSync5(gitDir);
40527
+ isRealGitDir = stat3.isDirectory();
39693
40528
  } catch {
39694
40529
  isRealGitDir = false;
39695
40530
  }
@@ -39732,16 +40567,16 @@ function getProjectRoot(cwd) {
39732
40567
  const homeRoot = homedir();
39733
40568
  const skippedCleoDirs = [];
39734
40569
  while (true) {
39735
- const cleoDir = join15(current, ".cleo");
39736
- const gitDir = join15(current, ".git");
40570
+ const cleoDir = join17(current, ".cleo");
40571
+ const gitDir = join17(current, ".git");
39737
40572
  const isDangerousRoot = current === homeRoot || current === "/" || current === "";
39738
- if (existsSync15(cleoDir) && !isDangerousRoot) {
40573
+ if (existsSync16(cleoDir) && !isDangerousRoot) {
39739
40574
  if (validateProjectRoot(current)) {
39740
40575
  return current;
39741
40576
  }
39742
40577
  skippedCleoDirs.push(current);
39743
40578
  }
39744
- if (existsSync15(gitDir) && !isDangerousRoot) {
40579
+ if (existsSync16(gitDir) && !isDangerousRoot) {
39745
40580
  let isRealGitDir = false;
39746
40581
  try {
39747
40582
  isRealGitDir = statSync5(gitDir).isDirectory();
@@ -39786,18 +40621,18 @@ function resolveOrCwd(maybeRoot) {
39786
40621
  return getProjectRoot();
39787
40622
  }
39788
40623
  function getConfigPath(cwd) {
39789
- return join15(_resolveCleoDir(cwd), "config.json");
40624
+ return join17(_resolveCleoDir(cwd), "config.json");
39790
40625
  }
39791
40626
  function getGlobalConfigPath() {
39792
- return join15(getCleoHome(), "config.json");
40627
+ return join17(getCleoHome(), "config.json");
39793
40628
  }
39794
40629
  function isAbsolutePath(path) {
39795
40630
  return _isAbsolutePath(path);
39796
40631
  }
39797
40632
  function _readProjectNameFromInfo(projectRoot) {
39798
40633
  try {
39799
- const infoPath = join15(projectRoot, ".cleo", "project-info.json");
39800
- if (!existsSync15(infoPath)) return void 0;
40634
+ const infoPath = join17(projectRoot, ".cleo", "project-info.json");
40635
+ if (!existsSync16(infoPath)) return void 0;
39801
40636
  const raw = readFileSync5(infoPath, "utf-8");
39802
40637
  const data = JSON.parse(raw);
39803
40638
  return typeof data.name === "string" && data.name.length > 0 ? data.name : void 0;
@@ -39823,8 +40658,8 @@ async function registerProjectOnEncounter(projectRoot, infoProjectId) {
39823
40658
  if (existingRows.length > 0) {
39824
40659
  const existingPath = existingRows[0].projectPath;
39825
40660
  if (existingPath !== resolvedPath) {
39826
- const newBrainDbPath = join15(resolvedPath, ".cleo", "brain.db");
39827
- const newTasksDbPath = join15(resolvedPath, ".cleo", "tasks.db");
40661
+ const newBrainDbPath = join17(resolvedPath, ".cleo", "brain.db");
40662
+ const newTasksDbPath = join17(resolvedPath, ".cleo", "tasks.db");
39828
40663
  await db.update(projectRegistry2).set({
39829
40664
  projectPath: resolvedPath,
39830
40665
  projectHash: generateProjectHash2(resolvedPath),
@@ -39855,8 +40690,8 @@ async function registerProjectOnEncounter(projectRoot, infoProjectId) {
39855
40690
  lastSync: now,
39856
40691
  taskCount: 0,
39857
40692
  labelsJson: "[]",
39858
- brainDbPath: join15(resolvedPath, ".cleo", "brain.db"),
39859
- tasksDbPath: join15(resolvedPath, ".cleo", "tasks.db"),
40693
+ brainDbPath: join17(resolvedPath, ".cleo", "brain.db"),
40694
+ tasksDbPath: join17(resolvedPath, ".cleo", "tasks.db"),
39860
40695
  statsJson: "{}"
39861
40696
  }).onConflictDoNothing();
39862
40697
  const aliases = canonicalResult.legacyAliases ?? [];
@@ -39957,46 +40792,46 @@ var init_api_mode = __esm({
39957
40792
  // packages/core/src/store/file-utils.ts
39958
40793
  import { randomBytes } from "node:crypto";
39959
40794
  import {
39960
- existsSync as existsSync16,
39961
- mkdirSync as mkdirSync4,
39962
- readdirSync as readdirSync4,
40795
+ existsSync as existsSync17,
40796
+ mkdirSync as mkdirSync5,
40797
+ readdirSync as readdirSync5,
39963
40798
  readFileSync as readFileSync6,
39964
40799
  renameSync as renameSync3,
39965
40800
  unlinkSync as unlinkSync3,
39966
- writeFileSync as writeFileSync3
40801
+ writeFileSync as writeFileSync4
39967
40802
  } from "node:fs";
39968
- import { basename as basename5, dirname as dirname8, join as join16 } from "node:path";
39969
- import * as lockfile2 from "proper-lockfile";
40803
+ import { basename as basename5, dirname as dirname8, join as join18 } from "node:path";
40804
+ import * as lockfile3 from "proper-lockfile";
39970
40805
  function rotateBackup(filePath, mode) {
39971
40806
  const dir = dirname8(filePath);
39972
40807
  const name15 = basename5(filePath);
39973
- const backupDir = join16(dir, ".backups");
40808
+ const backupDir = join18(dir, ".backups");
39974
40809
  const dirMode = typeof mode === "number" ? modeToDirMode(mode) : void 0;
39975
- if (!existsSync16(backupDir)) {
39976
- mkdirSync4(backupDir, { recursive: true, mode: dirMode });
40810
+ if (!existsSync17(backupDir)) {
40811
+ mkdirSync5(backupDir, { recursive: true, mode: dirMode });
39977
40812
  }
39978
40813
  for (let i = MAX_BACKUPS; i >= 1; i--) {
39979
- const current = join16(backupDir, `${name15}.${i}`);
40814
+ const current = join18(backupDir, `${name15}.${i}`);
39980
40815
  if (i === MAX_BACKUPS) {
39981
40816
  try {
39982
40817
  unlinkSync3(current);
39983
40818
  } catch {
39984
40819
  }
39985
40820
  } else {
39986
- const next = join16(backupDir, `${name15}.${i + 1}`);
40821
+ const next = join18(backupDir, `${name15}.${i + 1}`);
39987
40822
  try {
39988
- if (existsSync16(current)) renameSync3(current, next);
40823
+ if (existsSync17(current)) renameSync3(current, next);
39989
40824
  } catch {
39990
40825
  }
39991
40826
  }
39992
40827
  }
39993
40828
  try {
39994
40829
  const content = readFileSync6(filePath, "utf-8");
39995
- const backupPath = join16(backupDir, `${name15}.1`);
40830
+ const backupPath = join18(backupDir, `${name15}.1`);
39996
40831
  if (typeof mode === "number") {
39997
- writeFileSync3(backupPath, content, { encoding: "utf-8", mode });
40832
+ writeFileSync4(backupPath, content, { encoding: "utf-8", mode });
39998
40833
  } else {
39999
- writeFileSync3(backupPath, content, "utf-8");
40834
+ writeFileSync4(backupPath, content, "utf-8");
40000
40835
  }
40001
40836
  } catch {
40002
40837
  }
@@ -40013,15 +40848,15 @@ function writeJsonFileAtomic(filePath, data, optsOrIndent = 2) {
40013
40848
  const indent = opts.indent ?? 2;
40014
40849
  const mode = opts.mode;
40015
40850
  const dir = dirname8(filePath);
40016
- const tempPath = join16(dir, `.${basename5(filePath)}.${randomBytes(6).toString("hex")}.tmp`);
40851
+ const tempPath = join18(dir, `.${basename5(filePath)}.${randomBytes(6).toString("hex")}.tmp`);
40017
40852
  const content = JSON.stringify(data, null, indent) + "\n";
40018
40853
  if (typeof mode === "number") {
40019
- writeFileSync3(tempPath, content, { encoding: "utf-8", mode });
40854
+ writeFileSync4(tempPath, content, { encoding: "utf-8", mode });
40020
40855
  } else {
40021
- writeFileSync3(tempPath, content, "utf-8");
40856
+ writeFileSync4(tempPath, content, "utf-8");
40022
40857
  }
40023
40858
  try {
40024
- if (existsSync16(filePath)) {
40859
+ if (existsSync17(filePath)) {
40025
40860
  rotateBackup(filePath, mode);
40026
40861
  }
40027
40862
  renameSync3(tempPath, filePath);
@@ -40047,19 +40882,19 @@ function readJsonFile(filePath) {
40047
40882
  async function withLock2(filePath, transform2, opts = {}) {
40048
40883
  const dir = dirname8(filePath);
40049
40884
  const dirMode = typeof opts.mode === "number" ? modeToDirMode(opts.mode) : void 0;
40050
- if (!existsSync16(dir)) {
40051
- mkdirSync4(dir, { recursive: true, mode: dirMode });
40885
+ if (!existsSync17(dir)) {
40886
+ mkdirSync5(dir, { recursive: true, mode: dirMode });
40052
40887
  }
40053
- if (!existsSync16(filePath)) {
40888
+ if (!existsSync17(filePath)) {
40054
40889
  if (typeof opts.mode === "number") {
40055
- writeFileSync3(filePath, "", { encoding: "utf-8", mode: opts.mode });
40890
+ writeFileSync4(filePath, "", { encoding: "utf-8", mode: opts.mode });
40056
40891
  } else {
40057
- writeFileSync3(filePath, "", "utf-8");
40892
+ writeFileSync4(filePath, "", "utf-8");
40058
40893
  }
40059
40894
  }
40060
40895
  let release;
40061
40896
  try {
40062
- release = await lockfile2.lock(filePath, LOCK_OPTIONS);
40897
+ release = await lockfile3.lock(filePath, LOCK_OPTIONS);
40063
40898
  const current = readJsonFile(filePath);
40064
40899
  const updated = transform2(current);
40065
40900
  writeJsonFileAtomic(filePath, updated, { mode: opts.mode });
@@ -40072,15 +40907,15 @@ async function withLock2(filePath, transform2, opts = {}) {
40072
40907
  }
40073
40908
  async function withFileLock(filePath, operation) {
40074
40909
  const dir = dirname8(filePath);
40075
- if (!existsSync16(dir)) {
40076
- mkdirSync4(dir, { recursive: true });
40910
+ if (!existsSync17(dir)) {
40911
+ mkdirSync5(dir, { recursive: true });
40077
40912
  }
40078
- if (!existsSync16(filePath)) {
40079
- writeFileSync3(filePath, "", "utf-8");
40913
+ if (!existsSync17(filePath)) {
40914
+ writeFileSync4(filePath, "", "utf-8");
40080
40915
  }
40081
40916
  let release;
40082
40917
  try {
40083
- release = await lockfile2.lock(filePath, LOCK_OPTIONS);
40918
+ release = await lockfile3.lock(filePath, LOCK_OPTIONS);
40084
40919
  return await operation();
40085
40920
  } finally {
40086
40921
  if (release) {
@@ -40109,8 +40944,8 @@ var init_file_utils = __esm({
40109
40944
 
40110
40945
  // packages/core/src/llm/credential-removal.ts
40111
40946
  import { unlinkSync as unlinkSync4 } from "node:fs";
40112
- import { join as join17 } from "node:path";
40113
- import { getCleoHome as getCleoHome2 } from "@cleocode/paths";
40947
+ import { join as join19 } from "node:path";
40948
+ import { getCleoHome as getCleoHome3 } from "@cleocode/paths";
40114
40949
  function buildBuiltinRemovalRegistry() {
40115
40950
  const registry2 = new RemovalRegistry();
40116
40951
  registry2.register(MANUAL_REMOVAL_STEP);
@@ -40201,7 +41036,7 @@ var init_credential_removal = __esm({
40201
41036
  sourceId: "cleo-pkce",
40202
41037
  description: "Delete CLEO-issued PKCE token at <CLEO_HOME>/anthropic-oauth.json",
40203
41038
  async remove() {
40204
- const path = join17(getCleoHome2(), "anthropic-oauth.json");
41039
+ const path = join19(getCleoHome3(), "anthropic-oauth.json");
40205
41040
  const cleaned = [];
40206
41041
  try {
40207
41042
  unlinkSync4(path);
@@ -40280,7 +41115,7 @@ __export(config_exports, {
40280
41115
  parseConfigValue: () => parseConfigValue,
40281
41116
  setConfigValue: () => setConfigValue
40282
41117
  });
40283
- import { existsSync as existsSync17 } from "node:fs";
41118
+ import { existsSync as existsSync18 } from "node:fs";
40284
41119
  function getNestedValue(obj, path) {
40285
41120
  const parts = path.split(".");
40286
41121
  let current = obj;
@@ -40328,7 +41163,7 @@ function parseEnvValue(value) {
40328
41163
  return value;
40329
41164
  }
40330
41165
  async function loadConfig(cwd) {
40331
- let merged = JSON.parse(JSON.stringify(DEFAULTS));
41166
+ let merged = JSON.parse(JSON.stringify(DEFAULTS2));
40332
41167
  const globalConfig2 = await readJson(getGlobalConfigPath());
40333
41168
  if (globalConfig2) {
40334
41169
  merged = deepMerge(merged, globalConfig2);
@@ -40374,7 +41209,7 @@ async function getConfigValue(path, cwd) {
40374
41209
  return { value: val, source: "global" };
40375
41210
  }
40376
41211
  }
40377
- const defaultVal = getNestedValue({ ...DEFAULTS }, path);
41212
+ const defaultVal = getNestedValue({ ...DEFAULTS2 }, path);
40378
41213
  return { value: defaultVal, source: "default" };
40379
41214
  }
40380
41215
  async function getRawConfigValue(key, cwd) {
@@ -40402,7 +41237,7 @@ function parseConfigValue(value) {
40402
41237
  }
40403
41238
  async function setConfigValue(key, value, cwd, opts) {
40404
41239
  const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
40405
- if (!existsSync17(configPath)) {
41240
+ if (!existsSync18(configPath)) {
40406
41241
  await atomicWriteJson(configPath, {});
40407
41242
  }
40408
41243
  const config2 = await readJson(configPath) ?? {};
@@ -40414,7 +41249,7 @@ async function setConfigValue(key, value, cwd, opts) {
40414
41249
  async function applyStrictnessPreset(preset, cwd, opts) {
40415
41250
  const definition = STRICTNESS_PRESETS[preset];
40416
41251
  const configPath = opts?.global ? getGlobalConfigPath() : getConfigPath(cwd);
40417
- if (!existsSync17(configPath)) {
41252
+ if (!existsSync18(configPath)) {
40418
41253
  await atomicWriteJson(configPath, {});
40419
41254
  }
40420
41255
  const config2 = await readJson(configPath) ?? {};
@@ -40438,7 +41273,7 @@ function listStrictnessPresets() {
40438
41273
  })
40439
41274
  );
40440
41275
  }
40441
- var DEFAULTS, ENV_MAP, STRICTNESS_PRESETS;
41276
+ var DEFAULTS2, ENV_MAP, STRICTNESS_PRESETS;
40442
41277
  var init_config = __esm({
40443
41278
  "packages/core/src/config.ts"() {
40444
41279
  "use strict";
@@ -40446,7 +41281,7 @@ var init_config = __esm({
40446
41281
  init_paths();
40447
41282
  init_atomic();
40448
41283
  init_json2();
40449
- DEFAULTS = {
41284
+ DEFAULTS2 = {
40450
41285
  version: "2.10.0",
40451
41286
  output: {
40452
41287
  defaultFormat: "json",
@@ -40621,10 +41456,10 @@ var init_config = __esm({
40621
41456
  // packages/core/src/llm/credential-seeders/claude-code-seeder.ts
40622
41457
  import { readFileSync as readFileSync7 } from "node:fs";
40623
41458
  import { homedir as homedir2 } from "node:os";
40624
- import { join as join18 } from "node:path";
41459
+ import { join as join20 } from "node:path";
40625
41460
  function defaultReadCredentialFile() {
40626
41461
  try {
40627
- return readFileSync7(join18(homedir2(), ".claude", ".credentials.json"), "utf-8");
41462
+ return readFileSync7(join20(homedir2(), ".claude", ".credentials.json"), "utf-8");
40628
41463
  } catch {
40629
41464
  return null;
40630
41465
  }
@@ -40719,9 +41554,9 @@ var init_claude_code_seeder = __esm({
40719
41554
 
40720
41555
  // packages/core/src/llm/credential-seeders/cleo-pkce-seeder.ts
40721
41556
  import { readFileSync as readFileSync8 } from "node:fs";
40722
- import { join as join19 } from "node:path";
41557
+ import { join as join21 } from "node:path";
40723
41558
  function defaultCleoPkcePath() {
40724
- return join19(getCleoHome(), "anthropic-oauth.json");
41559
+ return join21(getCleoHome(), "anthropic-oauth.json");
40725
41560
  }
40726
41561
  function defaultReadCredentialFile2() {
40727
41562
  try {
@@ -40792,13 +41627,13 @@ var init_cleo_pkce_seeder = __esm({
40792
41627
  });
40793
41628
 
40794
41629
  // packages/core/src/llm/credential-seeders/codex-cli-seeder.ts
40795
- import { existsSync as existsSync18, readFileSync as readFileSync9 } from "node:fs";
41630
+ import { existsSync as existsSync19, readFileSync as readFileSync9 } from "node:fs";
40796
41631
  import { homedir as homedir3 } from "node:os";
40797
- import { join as join20 } from "node:path";
41632
+ import { join as join22 } from "node:path";
40798
41633
  function getCodexAuthPath() {
40799
41634
  const codexHome = (process.env["CODEX_HOME"] ?? "").trim();
40800
- const root = codexHome || join20(homedir3(), ".codex");
40801
- return join20(root, "auth.json");
41635
+ const root = codexHome || join22(homedir3(), ".codex");
41636
+ return join22(root, "auth.json");
40802
41637
  }
40803
41638
  var CodexCliSeeder, codexCliSeeder;
40804
41639
  var init_codex_cli_seeder = __esm({
@@ -40817,7 +41652,7 @@ var init_codex_cli_seeder = __esm({
40817
41652
  */
40818
41653
  async seed() {
40819
41654
  const authPath = getCodexAuthPath();
40820
- if (!existsSync18(authPath)) {
41655
+ if (!existsSync19(authPath)) {
40821
41656
  return { entries: [] };
40822
41657
  }
40823
41658
  let raw;
@@ -41012,11 +41847,11 @@ var init_google_pkce = __esm({
41012
41847
  });
41013
41848
 
41014
41849
  // packages/core/src/llm/credential-seeders/gemini-cli-seeder.ts
41015
- import { existsSync as existsSync19, readFileSync as readFileSync10 } from "node:fs";
41016
- import { join as join21 } from "node:path";
41017
- import { getCleoHome as getCleoHome3 } from "@cleocode/paths";
41850
+ import { existsSync as existsSync20, readFileSync as readFileSync10 } from "node:fs";
41851
+ import { join as join23 } from "node:path";
41852
+ import { getCleoHome as getCleoHome4 } from "@cleocode/paths";
41018
41853
  function getGoogleOauthPath() {
41019
- return join21(getCleoHome3(), "google_oauth.json");
41854
+ return join23(getCleoHome4(), "google_oauth.json");
41020
41855
  }
41021
41856
  function parseGoogleOauthFile(raw) {
41022
41857
  let json3;
@@ -41061,7 +41896,7 @@ var init_gemini_cli_seeder = __esm({
41061
41896
  */
41062
41897
  async seed() {
41063
41898
  const path = getGoogleOauthPath();
41064
- if (!existsSync19(path)) {
41899
+ if (!existsSync20(path)) {
41065
41900
  return { entries: [] };
41066
41901
  }
41067
41902
  let raw;
@@ -41286,23 +42121,23 @@ var init_credential_seeders = __esm({
41286
42121
 
41287
42122
  // packages/core/src/llm/global-config-migration.ts
41288
42123
  import {
41289
- existsSync as existsSync20,
41290
- mkdirSync as mkdirSync5,
42124
+ existsSync as existsSync21,
42125
+ mkdirSync as mkdirSync6,
41291
42126
  readFileSync as readFileSync11,
41292
42127
  renameSync as renameSync4,
41293
42128
  unlinkSync as unlinkSync5,
41294
- writeFileSync as writeFileSync4
42129
+ writeFileSync as writeFileSync5
41295
42130
  } from "node:fs";
41296
- import { join as join22 } from "node:path";
41297
- import { getCleoHome as getCleoHome4, getCleoPlatformPaths as getCleoPlatformPaths2 } from "@cleocode/paths";
42131
+ import { join as join24 } from "node:path";
42132
+ import { getCleoHome as getCleoHome5, getCleoPlatformPaths as getCleoPlatformPaths2 } from "@cleocode/paths";
41298
42133
  function configDirGlobalConfigPath() {
41299
- return join22(getCleoPlatformPaths2().config, GLOBAL_CONFIG_FILENAME);
42134
+ return join24(getCleoPlatformPaths2().config, GLOBAL_CONFIG_FILENAME);
41300
42135
  }
41301
42136
  function legacyGlobalConfigPath() {
41302
- return join22(getCleoHome4(), GLOBAL_CONFIG_FILENAME);
42137
+ return join24(getCleoHome5(), GLOBAL_CONFIG_FILENAME);
41303
42138
  }
41304
42139
  function migrationMarkerPath() {
41305
- return join22(getCleoHome4(), MIGRATIONS_SUBDIR, MIGRATION_MARKER);
42140
+ return join24(getCleoHome5(), MIGRATIONS_SUBDIR, MIGRATION_MARKER);
41306
42141
  }
41307
42142
  function tempTargetPath() {
41308
42143
  return `${configDirGlobalConfigPath()}.tmp`;
@@ -41312,12 +42147,12 @@ function migrateGlobalConfigToConfigDir() {
41312
42147
  const source = legacyGlobalConfigPath();
41313
42148
  const target = configDirGlobalConfigPath();
41314
42149
  const marker16 = migrationMarkerPath();
41315
- if (existsSync20(marker16)) return false;
41316
- if (!existsSync20(source)) {
42150
+ if (existsSync21(marker16)) return false;
42151
+ if (!existsSync21(source)) {
41317
42152
  stampMarker(marker16);
41318
42153
  return false;
41319
42154
  }
41320
- if (existsSync20(target)) {
42155
+ if (existsSync21(target)) {
41321
42156
  backupSourceQuiet(source);
41322
42157
  stampMarker(marker16);
41323
42158
  return false;
@@ -41331,9 +42166,9 @@ function migrateGlobalConfigToConfigDir() {
41331
42166
  );
41332
42167
  return false;
41333
42168
  }
41334
- mkdirSync5(getCleoPlatformPaths2().config, { recursive: true });
42169
+ mkdirSync6(getCleoPlatformPaths2().config, { recursive: true });
41335
42170
  const temp = tempTargetPath();
41336
- writeFileSync4(temp, raw, { mode: 420 });
42171
+ writeFileSync5(temp, raw, { mode: 420 });
41337
42172
  renameSync4(temp, target);
41338
42173
  stampMarker(marker16);
41339
42174
  try {
@@ -41350,7 +42185,7 @@ function migrateGlobalConfigToConfigDir() {
41350
42185
  } catch (err) {
41351
42186
  try {
41352
42187
  const temp = tempTargetPath();
41353
- if (existsSync20(temp)) unlinkSync5(temp);
42188
+ if (existsSync21(temp)) unlinkSync5(temp);
41354
42189
  } catch {
41355
42190
  }
41356
42191
  console.error(
@@ -41361,8 +42196,8 @@ function migrateGlobalConfigToConfigDir() {
41361
42196
  }
41362
42197
  function stampMarker(markerPath) {
41363
42198
  try {
41364
- mkdirSync5(join22(getCleoHome4(), MIGRATIONS_SUBDIR), { recursive: true });
41365
- writeFileSync4(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
42199
+ mkdirSync6(join24(getCleoHome5(), MIGRATIONS_SUBDIR), { recursive: true });
42200
+ writeFileSync5(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
41366
42201
  `, { mode: 420 });
41367
42202
  } catch {
41368
42203
  }
@@ -41370,7 +42205,7 @@ function stampMarker(markerPath) {
41370
42205
  function backupSourceQuiet(source) {
41371
42206
  try {
41372
42207
  const backup = `${source}${BACKUP_SUFFIX}`;
41373
- if (existsSync20(backup)) return;
42208
+ if (existsSync21(backup)) return;
41374
42209
  renameSync4(source, backup);
41375
42210
  } catch {
41376
42211
  }
@@ -41393,20 +42228,20 @@ var init_global_config_migration = __esm({
41393
42228
  });
41394
42229
 
41395
42230
  // packages/core/src/llm/legacy-flat-key-import.ts
41396
- import { existsSync as existsSync21, readFileSync as readFileSync12, renameSync as renameSync5, writeFileSync as writeFileSync5 } from "node:fs";
41397
- import { join as join23 } from "node:path";
41398
- import { getCleoHome as getCleoHome5 } from "@cleocode/paths";
42231
+ import { existsSync as existsSync22, readFileSync as readFileSync12, renameSync as renameSync5, writeFileSync as writeFileSync6 } from "node:fs";
42232
+ import { join as join25 } from "node:path";
42233
+ import { getCleoHome as getCleoHome6 } from "@cleocode/paths";
41399
42234
  function migrationPaths() {
41400
- const home = getCleoHome5();
42235
+ const home = getCleoHome6();
41401
42236
  return {
41402
- flatPath: join23(home, "anthropic-key"),
41403
- bakPath: join23(home, `anthropic-key${LEGACY_FLAT_KEY_BAK_SUFFIX}`),
41404
- markerPath: join23(home, LEGACY_FLAT_KEY_MARKER)
42237
+ flatPath: join25(home, "anthropic-key"),
42238
+ bakPath: join25(home, `anthropic-key${LEGACY_FLAT_KEY_BAK_SUFFIX}`),
42239
+ markerPath: join25(home, LEGACY_FLAT_KEY_MARKER)
41405
42240
  };
41406
42241
  }
41407
42242
  function writeMarker(markerPath) {
41408
42243
  try {
41409
- writeFileSync5(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
42244
+ writeFileSync6(markerPath, `${(/* @__PURE__ */ new Date()).toISOString()}
41410
42245
  `, {
41411
42246
  encoding: "utf-8",
41412
42247
  flag: "wx",
@@ -41422,7 +42257,7 @@ function writeMarker(markerPath) {
41422
42257
  }
41423
42258
  function readFlatKey(flatPath) {
41424
42259
  try {
41425
- if (!existsSync21(flatPath)) return null;
42260
+ if (!existsSync22(flatPath)) return null;
41426
42261
  const raw = readFileSync12(flatPath, "utf-8").trim();
41427
42262
  return raw || null;
41428
42263
  } catch (err) {
@@ -41435,7 +42270,7 @@ function readFlatKey(flatPath) {
41435
42270
  }
41436
42271
  async function importLegacyFlatAnthropicKey() {
41437
42272
  const { flatPath, bakPath, markerPath } = migrationPaths();
41438
- if (existsSync21(markerPath)) {
42273
+ if (existsSync22(markerPath)) {
41439
42274
  return { status: "marker-present", flatPath, bakPath: null, markerPath };
41440
42275
  }
41441
42276
  let existing = null;
@@ -41452,7 +42287,7 @@ async function importLegacyFlatAnthropicKey() {
41452
42287
  writeMarker(markerPath);
41453
42288
  return { status: "already-imported", flatPath, bakPath: null, markerPath };
41454
42289
  }
41455
- if (!existsSync21(flatPath)) {
42290
+ if (!existsSync22(flatPath)) {
41456
42291
  writeMarker(markerPath);
41457
42292
  return { status: "no-flat-file", flatPath, bakPath: null, markerPath };
41458
42293
  }
@@ -41514,15 +42349,15 @@ var init_legacy_flat_key_import = __esm({
41514
42349
  });
41515
42350
 
41516
42351
  // packages/core/src/llm/credentials.ts
41517
- import { existsSync as existsSync22, mkdirSync as mkdirSync6, readFileSync as readFileSync13, writeFileSync as writeFileSync6 } from "node:fs";
41518
- import { join as join24 } from "node:path";
41519
- import { getCleoHome as getCleoHome6 } from "@cleocode/paths";
42352
+ import { existsSync as existsSync23, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "node:fs";
42353
+ import { join as join26 } from "node:path";
42354
+ import { getCleoHome as getCleoHome7 } from "@cleocode/paths";
41520
42355
  function globalConfigPath() {
41521
42356
  return configDirGlobalConfigPath();
41522
42357
  }
41523
42358
  function projectConfigPath(projectRoot) {
41524
42359
  const cleoDir = process.env["CLEO_DIR"] ?? ".cleo";
41525
- return join24(projectRoot, cleoDir, "config.json");
42360
+ return join26(projectRoot, cleoDir, "config.json");
41526
42361
  }
41527
42362
  function readGlobalProviderKey(provider) {
41528
42363
  ensureGlobalConfigMigrated();
@@ -41532,8 +42367,8 @@ function readGlobalProviderKey(provider) {
41532
42367
  }
41533
42368
  function readFlatAnthropicKey() {
41534
42369
  try {
41535
- const keyFile = join24(getCleoHome6(), "anthropic-key");
41536
- if (!existsSync22(keyFile)) return null;
42370
+ const keyFile = join26(getCleoHome7(), "anthropic-key");
42371
+ if (!existsSync23(keyFile)) return null;
41537
42372
  const stored = readFileSync13(keyFile, "utf-8").trim();
41538
42373
  return stored || null;
41539
42374
  } catch {
@@ -41542,7 +42377,7 @@ function readFlatAnthropicKey() {
41542
42377
  }
41543
42378
  function readProviderKeyFromConfig(configFile, provider) {
41544
42379
  try {
41545
- if (!existsSync22(configFile)) return null;
42380
+ if (!existsSync23(configFile)) return null;
41546
42381
  const raw = readFileSync13(configFile, "utf-8");
41547
42382
  const config2 = JSON.parse(raw);
41548
42383
  const llm = config2["llm"];
@@ -41681,17 +42516,17 @@ __export(credentials_store_exports, {
41681
42516
  pickCredentialForProviderSync: () => pickCredentialForProviderSync,
41682
42517
  removeCredential: () => removeCredential
41683
42518
  });
41684
- import { chmodSync, existsSync as existsSync23, mkdirSync as mkdirSync7, readFileSync as readFileSync14, statSync as statSync6, writeFileSync as writeFileSync7 } from "node:fs";
41685
- import { dirname as dirname9, join as join25 } from "node:path";
41686
- import { getCleoHome as getCleoHome7 } from "@cleocode/paths";
42519
+ import { chmodSync, existsSync as existsSync24, mkdirSync as mkdirSync8, readFileSync as readFileSync14, statSync as statSync6, writeFileSync as writeFileSync8 } from "node:fs";
42520
+ import { dirname as dirname9, join as join27 } from "node:path";
42521
+ import { getCleoHome as getCleoHome8 } from "@cleocode/paths";
41687
42522
  function credentialsStorePath() {
41688
- return join25(getCleoHome7(), "llm-credentials.json");
42523
+ return join27(getCleoHome8(), "llm-credentials.json");
41689
42524
  }
41690
42525
  function ensureFileInitialized(path) {
41691
- if (existsSync23(path)) return;
42526
+ if (existsSync24(path)) return;
41692
42527
  const dir = dirname9(path);
41693
- if (!existsSync23(dir)) {
41694
- mkdirSync7(dir, { recursive: true, mode: 448 });
42528
+ if (!existsSync24(dir)) {
42529
+ mkdirSync8(dir, { recursive: true, mode: 448 });
41695
42530
  } else {
41696
42531
  try {
41697
42532
  chmodSync(dir, 448);
@@ -41699,7 +42534,7 @@ function ensureFileInitialized(path) {
41699
42534
  }
41700
42535
  }
41701
42536
  try {
41702
- writeFileSync7(path, `${JSON.stringify(emptyStore(), null, 2)}
42537
+ writeFileSync8(path, `${JSON.stringify(emptyStore(), null, 2)}
41703
42538
  `, {
41704
42539
  encoding: "utf-8",
41705
42540
  flag: "wx",
@@ -42042,13 +42877,13 @@ var init_gemini = __esm({
42042
42877
 
42043
42878
  // packages/core/src/llm/stable-device-id.ts
42044
42879
  import { randomUUID as randomUUID2 } from "node:crypto";
42045
- import { existsSync as existsSync24, mkdirSync as mkdirSync8, readFileSync as readFileSync15, renameSync as renameSync6, writeFileSync as writeFileSync8 } from "node:fs";
42046
- import { dirname as dirname10, join as join26 } from "node:path";
42047
- import { getCleoHome as getCleoHome8 } from "@cleocode/paths";
42880
+ import { existsSync as existsSync25, mkdirSync as mkdirSync9, readFileSync as readFileSync15, renameSync as renameSync6, writeFileSync as writeFileSync9 } from "node:fs";
42881
+ import { dirname as dirname10, join as join28 } from "node:path";
42882
+ import { getCleoHome as getCleoHome9 } from "@cleocode/paths";
42048
42883
  function getStableDeviceId() {
42049
42884
  if (_cachedDeviceId !== null) return _cachedDeviceId;
42050
- const path = join26(getCleoHome8(), DEVICE_ID_FILE);
42051
- if (existsSync24(path)) {
42885
+ const path = join28(getCleoHome9(), DEVICE_ID_FILE);
42886
+ if (existsSync25(path)) {
42052
42887
  try {
42053
42888
  const raw = readFileSync15(path, "utf-8").trim();
42054
42889
  if (raw.length > 0) {
@@ -42061,11 +42896,11 @@ function getStableDeviceId() {
42061
42896
  const fresh = randomUUID2();
42062
42897
  try {
42063
42898
  const dir = dirname10(path);
42064
- if (!existsSync24(dir)) {
42065
- mkdirSync8(dir, { recursive: true });
42899
+ if (!existsSync25(dir)) {
42900
+ mkdirSync9(dir, { recursive: true });
42066
42901
  }
42067
42902
  const tmpPath = `${path}.tmp.${process.pid}`;
42068
- writeFileSync8(tmpPath, fresh, { mode: 384 });
42903
+ writeFileSync9(tmpPath, fresh, { mode: 384 });
42069
42904
  renameSync6(tmpPath, path);
42070
42905
  } catch {
42071
42906
  }
@@ -42363,14 +43198,14 @@ var init_xai = __esm({
42363
43198
  });
42364
43199
 
42365
43200
  // packages/core/src/llm/provider-registry/loader.ts
42366
- import { readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
42367
- import { join as join27 } from "node:path";
43201
+ import { readdirSync as readdirSync6, statSync as statSync7 } from "node:fs";
43202
+ import { join as join29 } from "node:path";
42368
43203
  import { pathToFileURL } from "node:url";
42369
43204
  function isPluginFile(filename) {
42370
43205
  return PLUGIN_EXTENSIONS.some((ext) => filename.endsWith(ext));
42371
43206
  }
42372
43207
  function getPluginDir() {
42373
- return join27(getCleoHome(), "plugins", "model-providers");
43208
+ return join29(getCleoHome(), "plugins", "model-providers");
42374
43209
  }
42375
43210
  async function loadOnePlugin(absPath, api) {
42376
43211
  let mod;
@@ -42412,19 +43247,19 @@ async function loadOnePlugin(absPath, api) {
42412
43247
  async function scanAndLoadPlugins(pluginDir, api) {
42413
43248
  let entries;
42414
43249
  try {
42415
- entries = readdirSync5(pluginDir);
43250
+ entries = readdirSync6(pluginDir);
42416
43251
  } catch {
42417
43252
  return;
42418
43253
  }
42419
43254
  const pluginFiles = entries.filter((name15) => !name15.startsWith(".") && isPluginFile(name15)).filter((name15) => {
42420
43255
  try {
42421
- return statSync7(join27(pluginDir, name15)).isFile();
43256
+ return statSync7(join29(pluginDir, name15)).isFile();
42422
43257
  } catch {
42423
43258
  return false;
42424
43259
  }
42425
43260
  }).sort();
42426
43261
  for (const filename of pluginFiles) {
42427
- await loadOnePlugin(join27(pluginDir, filename), api);
43262
+ await loadOnePlugin(join29(pluginDir, filename), api);
42428
43263
  }
42429
43264
  }
42430
43265
  async function runDiscovery(registerProvider2, builtins) {
@@ -42527,15 +43362,15 @@ var init_provider_registry = __esm({
42527
43362
  });
42528
43363
 
42529
43364
  // packages/core/src/llm/rate-limit-guard.ts
42530
- import { existsSync as existsSync25, mkdirSync as mkdirSync9, unlinkSync as unlinkSync6 } from "node:fs";
42531
- import { join as join28 } from "node:path";
42532
- import { getCleoHome as getCleoHome9 } from "@cleocode/paths";
43365
+ import { existsSync as existsSync26, mkdirSync as mkdirSync10, unlinkSync as unlinkSync6 } from "node:fs";
43366
+ import { join as join30 } from "node:path";
43367
+ import { getCleoHome as getCleoHome10 } from "@cleocode/paths";
42533
43368
  function sanitize(value) {
42534
43369
  return value.replace(/[^a-zA-Z0-9_-]/g, "_");
42535
43370
  }
42536
43371
  function rateLimitStatePath(provider, label) {
42537
- const dir = join28(getCleoHome9(), "rate-limit-state");
42538
- return join28(dir, `${sanitize(provider)}-${sanitize(label)}.json`);
43372
+ const dir = join30(getCleoHome10(), "rate-limit-state");
43373
+ return join30(dir, `${sanitize(provider)}-${sanitize(label)}.json`);
42539
43374
  }
42540
43375
  function parseResetFromHeaders(headers) {
42541
43376
  const get = (k) => {
@@ -42582,9 +43417,9 @@ async function recordRateLimit(provider, label, opts) {
42582
43417
  source = "default";
42583
43418
  }
42584
43419
  const filePath = rateLimitStatePath(provider, label);
42585
- const dir = join28(getCleoHome9(), "rate-limit-state");
42586
- if (!existsSync25(dir)) {
42587
- mkdirSync9(dir, { recursive: true });
43420
+ const dir = join30(getCleoHome10(), "rate-limit-state");
43421
+ if (!existsSync26(dir)) {
43422
+ mkdirSync10(dir, { recursive: true });
42588
43423
  }
42589
43424
  const state = { resetAt, recordedAt: now, source };
42590
43425
  await withFileLock(filePath, () => {
@@ -43098,28 +43933,28 @@ var init_credential_pool = __esm({
43098
43933
 
43099
43934
  // packages/core/src/llm/catalog-cache.ts
43100
43935
  import {
43101
- existsSync as existsSync26,
43102
- mkdirSync as mkdirSync10,
43103
- readdirSync as readdirSync6,
43936
+ existsSync as existsSync27,
43937
+ mkdirSync as mkdirSync11,
43938
+ readdirSync as readdirSync7,
43104
43939
  readFileSync as readFileSync16,
43105
43940
  statSync as statSync8,
43106
43941
  symlinkSync,
43107
43942
  unlinkSync as unlinkSync7,
43108
- writeFileSync as writeFileSync9
43943
+ writeFileSync as writeFileSync10
43109
43944
  } from "node:fs";
43110
43945
  import { homedir as homedir4 } from "node:os";
43111
- import { join as join29 } from "node:path";
43946
+ import { join as join31 } from "node:path";
43112
43947
  function getCatalogDir() {
43113
43948
  if (process.env["CLEO_DATA_DIR"]) {
43114
- return join29(process.env["CLEO_DATA_DIR"], "llm-catalog");
43949
+ return join31(process.env["CLEO_DATA_DIR"], "llm-catalog");
43115
43950
  }
43116
- const xdg = process.env["XDG_DATA_HOME"] ?? join29(homedir4(), ".local", "share");
43117
- return join29(xdg, "cleo", "llm-catalog");
43951
+ const xdg = process.env["XDG_DATA_HOME"] ?? join31(homedir4(), ".local", "share");
43952
+ return join31(xdg, "cleo", "llm-catalog");
43118
43953
  }
43119
43954
  function findLatestCacheFile(dir) {
43120
- if (!existsSync26(dir)) return null;
43121
- const files = readdirSync6(dir).filter((f) => f.endsWith("-models.json")).map((f) => ({ name: f, mtime: statSync8(join29(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
43122
- return files.length > 0 ? join29(dir, files[0].name) : null;
43955
+ if (!existsSync27(dir)) return null;
43956
+ const files = readdirSync7(dir).filter((f) => f.endsWith("-models.json")).map((f) => ({ name: f, mtime: statSync8(join31(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
43957
+ return files.length > 0 ? join31(dir, files[0].name) : null;
43123
43958
  }
43124
43959
  function readCacheFile(filePath) {
43125
43960
  try {
@@ -43217,7 +44052,7 @@ var init_catalog_model_resolver = __esm({
43217
44052
  });
43218
44053
 
43219
44054
  // packages/core/src/llm/cross-provider-selector.ts
43220
- import { totalmem } from "node:os";
44055
+ import { totalmem as totalmem2 } from "node:os";
43221
44056
  async function probeOllamaAlive(baseUrl) {
43222
44057
  const cached2 = _ollamaProbeCache.get(baseUrl);
43223
44058
  if (cached2 && Date.now() - cached2.checkedAt < OLLAMA_PROBE_TTL_MS) {
@@ -43240,7 +44075,7 @@ async function probeOllamaAlive(baseUrl) {
43240
44075
  return alive;
43241
44076
  }
43242
44077
  function ollamaDefaultModelForTier(tier, ramBytesOverride) {
43243
- const ramBytes = ramBytesOverride ?? totalmem();
44078
+ const ramBytes = ramBytesOverride ?? totalmem2();
43244
44079
  const gb = ramBytes / 1024 ** 3;
43245
44080
  if (gb >= 8) {
43246
44081
  return tier === "fast" || tier === "local" ? "gemma4:e2b" : "gemma4:e4b";
@@ -43364,7 +44199,7 @@ async function selectBestProvisioned(role, opts) {
43364
44199
  let model;
43365
44200
  if (winner.id === "ollama") {
43366
44201
  const ollamaProfile2 = await getProviderProfile2("ollama");
43367
- const ramBytes = totalmem();
44202
+ const ramBytes = totalmem2();
43368
44203
  const gb = ramBytes / 1024 ** 3;
43369
44204
  if (gb >= 8) {
43370
44205
  model = (winner.tier === "fast" || taskTier === "fast" ? ollamaProfile2?.defaultAuxModel : ollamaProfile2?.defaultModel) ?? ollamaDefaultModelForTier(winner.tier);
@@ -43766,7 +44601,7 @@ __export(catalog_resolver_exports, {
43766
44601
  resolveCatalogEntry: () => resolveCatalogEntry
43767
44602
  });
43768
44603
  import { readFileSync as readFileSync17 } from "node:fs";
43769
- import { dirname as dirname11, join as join30 } from "node:path";
44604
+ import { dirname as dirname11, join as join32 } from "node:path";
43770
44605
  import { fileURLToPath as fileURLToPath3 } from "node:url";
43771
44606
  async function openCatalogAtPath(dbPath) {
43772
44607
  const handle = await openDualScopeDbAtPath("global", dbPath);
@@ -43776,7 +44611,7 @@ function loadShippedSeed() {
43776
44611
  if (_seed !== void 0) return _seed;
43777
44612
  try {
43778
44613
  const thisDir = dirname11(fileURLToPath3(import.meta.url));
43779
- const jsonPath = join30(thisDir, "curated-catalog.json");
44614
+ const jsonPath = join32(thisDir, "curated-catalog.json");
43780
44615
  _seed = JSON.parse(readFileSync17(jsonPath, "utf-8"));
43781
44616
  } catch (err) {
43782
44617
  logger5.warn(
@@ -44166,14 +45001,14 @@ var init_message_utils = __esm({
44166
45001
 
44167
45002
  // packages/core/src/llm/model-metadata.ts
44168
45003
  import { readFileSync as readFileSync18 } from "node:fs";
44169
- import { dirname as dirname12, join as join31 } from "node:path";
45004
+ import { dirname as dirname12, join as join33 } from "node:path";
44170
45005
  import { fileURLToPath as fileURLToPath4 } from "node:url";
44171
45006
  function getCuratedTable() {
44172
45007
  if (_curated !== void 0) {
44173
45008
  return _curated;
44174
45009
  }
44175
45010
  const thisDir = dirname12(fileURLToPath4(import.meta.url));
44176
- const jsonPath = join31(thisDir, "curated-models.json");
45011
+ const jsonPath = join33(thisDir, "curated-models.json");
44177
45012
  const raw = JSON.parse(readFileSync18(jsonPath, "utf-8"));
44178
45013
  _curated = raw.models;
44179
45014
  return _curated;
@@ -44252,7 +45087,7 @@ function storedToResolved(stored) {
44252
45087
  awsProfile: stored.metadata?.["awsProfile"] ?? null
44253
45088
  };
44254
45089
  }
44255
- function sleep(ms) {
45090
+ function sleep2(ms) {
44256
45091
  return new Promise((resolve5) => setTimeout(resolve5, ms));
44257
45092
  }
44258
45093
  function backoffMs(policy, attempt) {
@@ -44390,7 +45225,7 @@ var init_concrete_session = __esm({
44390
45225
  throw err;
44391
45226
  }
44392
45227
  lastErr = err;
44393
- await sleep(backoffMs(policy, attempt));
45228
+ await sleep2(backoffMs(policy, attempt));
44394
45229
  }
44395
45230
  }
44396
45231
  throw lastErr;
@@ -48074,7 +48909,7 @@ function normalizeOllamaToolCall(tc) {
48074
48909
  arguments: JSON.stringify(tc.function.arguments ?? {})
48075
48910
  };
48076
48911
  }
48077
- function sleep2(ms) {
48912
+ function sleep3(ms) {
48078
48913
  return new Promise((resolve5) => setTimeout(resolve5, ms));
48079
48914
  }
48080
48915
  var OLLAMA_DEFAULT_BASE_URL, MAX_RETRIES, INITIAL_BACKOFF_MS, RETRYABLE_STATUS_CODES, OllamaTransport;
@@ -48283,7 +49118,7 @@ var init_ollama2 = __esm({
48283
49118
  for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
48284
49119
  if (attempt > 0) {
48285
49120
  const delay = INITIAL_BACKOFF_MS * 2 ** (attempt - 1);
48286
- await sleep2(delay);
49121
+ await sleep3(delay);
48287
49122
  }
48288
49123
  let response;
48289
49124
  try {
@@ -76215,7 +77050,7 @@ var init_model_runner = __esm({
76215
77050
  });
76216
77051
 
76217
77052
  // packages/core/src/selfimprove/fix-gen.ts
76218
- import { writeFileSync as writeFileSync10 } from "node:fs";
77053
+ import { writeFileSync as writeFileSync11 } from "node:fs";
76219
77054
  import { resolve as resolvePath } from "node:path";
76220
77055
  import { cwd as processCwd } from "node:process";
76221
77056
 
@@ -76563,7 +77398,7 @@ async function generateFixPatch(opts) {
76563
77398
  }
76564
77399
  const diff = output.diff.endsWith("\n") ? output.diff : `${output.diff}
76565
77400
  `;
76566
- writeFileSync10(patchPath, diff, "utf8");
77401
+ writeFileSync11(patchPath, diff, "utf8");
76567
77402
  const bytes = Buffer.byteLength(diff, "utf8");
76568
77403
  logger8.info(
76569
77404
  { dhqId: request.dhqId, scenario: request.scenario, patchPath, bytes, model: output.model },