@cleocode/core 2026.8.1 → 2026.8.3

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 (323) hide show
  1. package/dist/bootstrap.d.ts.map +1 -1
  2. package/dist/bootstrap.js +57 -27
  3. package/dist/bootstrap.js.map +1 -1
  4. package/dist/check/pr-gate.d.ts.map +1 -1
  5. package/dist/check/pr-gate.js +9 -0
  6. package/dist/check/pr-gate.js.map +1 -1
  7. package/dist/db/index.d.ts +13 -0
  8. package/dist/db/index.d.ts.map +1 -1
  9. package/dist/db/index.js +13 -0
  10. package/dist/db/index.js.map +1 -1
  11. package/dist/docs/display-alias.js +1 -1
  12. package/dist/docs/display-alias.js.map +1 -1
  13. package/dist/docs/export-document.js +499 -380
  14. package/dist/docs/export-document.js.map +3 -3
  15. package/dist/docs/numbering.js +1 -1
  16. package/dist/docs/numbering.js.map +1 -1
  17. package/dist/docs/supersede.js +1 -1
  18. package/dist/docs/supersede.js.map +1 -1
  19. package/dist/hooks/registry.d.ts +2 -2
  20. package/dist/hooks/registry.d.ts.map +1 -1
  21. package/dist/hooks/registry.js +5 -0
  22. package/dist/hooks/registry.js.map +1 -1
  23. package/dist/hooks/types.d.ts +59 -0
  24. package/dist/hooks/types.d.ts.map +1 -1
  25. package/dist/init/scaffold-workflows.d.ts +12 -0
  26. package/dist/init/scaffold-workflows.d.ts.map +1 -1
  27. package/dist/init/scaffold-workflows.js +16 -0
  28. package/dist/init/scaffold-workflows.js.map +1 -1
  29. package/dist/init/upgrade-workflows.d.ts.map +1 -1
  30. package/dist/init/upgrade-workflows.js +16 -0
  31. package/dist/init/upgrade-workflows.js.map +1 -1
  32. package/dist/init.d.ts.map +1 -1
  33. package/dist/init.js +16 -1
  34. package/dist/init.js.map +1 -1
  35. package/dist/injection.d.ts.map +1 -1
  36. package/dist/injection.js +44 -3
  37. package/dist/injection.js.map +1 -1
  38. package/dist/internal.d.ts +1 -0
  39. package/dist/internal.d.ts.map +1 -1
  40. package/dist/internal.js +2 -0
  41. package/dist/internal.js.map +1 -1
  42. package/dist/lifecycle/index.js +1 -1
  43. package/dist/lifecycle/index.js.map +1 -1
  44. package/dist/llm/credentials.d.ts +16 -1
  45. package/dist/llm/credentials.d.ts.map +1 -1
  46. package/dist/llm/credentials.js.map +1 -1
  47. package/dist/llm/cross-provider-selector.d.ts +25 -0
  48. package/dist/llm/cross-provider-selector.d.ts.map +1 -1
  49. package/dist/llm/cross-provider-selector.js +76 -3
  50. package/dist/llm/cross-provider-selector.js.map +1 -1
  51. package/dist/llm/local-inference-probe.d.ts +101 -0
  52. package/dist/llm/local-inference-probe.d.ts.map +1 -0
  53. package/dist/llm/local-inference-probe.js +174 -0
  54. package/dist/llm/local-inference-probe.js.map +1 -0
  55. package/dist/llm/plugin-facade.js +429 -115
  56. package/dist/llm/plugin-facade.js.map +3 -3
  57. package/dist/llm/role-executor.d.ts.map +1 -1
  58. package/dist/llm/role-executor.js +95 -9
  59. package/dist/llm/role-executor.js.map +1 -1
  60. package/dist/llm/role-resolver.d.ts +10 -0
  61. package/dist/llm/role-resolver.d.ts.map +1 -1
  62. package/dist/llm/role-resolver.js +92 -1
  63. package/dist/llm/role-resolver.js.map +1 -1
  64. package/dist/llm/system-resolver.d.ts.map +1 -1
  65. package/dist/llm/system-resolver.js +2 -0
  66. package/dist/llm/system-resolver.js.map +1 -1
  67. package/dist/memory/brain-backfill.js +3 -3
  68. package/dist/memory/brain-backfill.js.map +1 -1
  69. package/dist/memory/brain-consolidator.js +2 -2
  70. package/dist/memory/brain-consolidator.js.map +1 -1
  71. package/dist/memory/brain-doctor.js +1 -1
  72. package/dist/memory/brain-doctor.js.map +1 -1
  73. package/dist/memory/brain-health-dashboard.js +1 -1
  74. package/dist/memory/brain-health-dashboard.js.map +1 -1
  75. package/dist/memory/brain-lifecycle.js +10 -10
  76. package/dist/memory/brain-lifecycle.js.map +1 -1
  77. package/dist/memory/brain-maintenance.js +1 -1
  78. package/dist/memory/brain-maintenance.js.map +1 -1
  79. package/dist/memory/brain-page-nodes.js +4 -4
  80. package/dist/memory/brain-page-nodes.js.map +1 -1
  81. package/dist/memory/brain-reasoning.js +1 -1
  82. package/dist/memory/brain-reasoning.js.map +1 -1
  83. package/dist/memory/brain-search.d.ts +109 -0
  84. package/dist/memory/brain-search.d.ts.map +1 -1
  85. package/dist/memory/brain-search.js +150 -38
  86. package/dist/memory/brain-search.js.map +1 -1
  87. package/dist/memory/brain-similarity.js +1 -1
  88. package/dist/memory/brain-similarity.js.map +1 -1
  89. package/dist/memory/brain-stdp.js +6 -6
  90. package/dist/memory/brain-stdp.js.map +1 -1
  91. package/dist/memory/brain-stub-prune.d.ts +109 -0
  92. package/dist/memory/brain-stub-prune.d.ts.map +1 -0
  93. package/dist/memory/brain-stub-prune.js +155 -0
  94. package/dist/memory/brain-stub-prune.js.map +1 -0
  95. package/dist/memory/brain-sweep-executor.js +1 -1
  96. package/dist/memory/brain-sweep-executor.js.map +1 -1
  97. package/dist/memory/brain-writer-handlers.js +2 -2
  98. package/dist/memory/brain-writer-handlers.js.map +1 -1
  99. package/dist/memory/claude-mem-migration.d.ts.map +1 -1
  100. package/dist/memory/claude-mem-migration.js +2 -2
  101. package/dist/memory/claude-mem-migration.js.map +1 -1
  102. package/dist/memory/engine-compat.d.ts.map +1 -1
  103. package/dist/memory/engine-compat.js +65 -7
  104. package/dist/memory/engine-compat.js.map +1 -1
  105. package/dist/memory/extraction-gate.js +3 -3
  106. package/dist/memory/extraction-gate.js.map +1 -1
  107. package/dist/memory/graph-memory-bridge.js +9 -9
  108. package/dist/memory/graph-memory-bridge.js.map +1 -1
  109. package/dist/memory/graph-queries.js +4 -4
  110. package/dist/memory/graph-queries.js.map +1 -1
  111. package/dist/memory/llm-extraction.js +1 -1
  112. package/dist/memory/llm-extraction.js.map +1 -1
  113. package/dist/memory/memory-bridge.js +1 -1
  114. package/dist/memory/memory-bridge.js.map +1 -1
  115. package/dist/memory/nexus-plasticity.js +1 -1
  116. package/dist/memory/nexus-plasticity.js.map +1 -1
  117. package/dist/memory/observer-reflector.js +1 -1
  118. package/dist/memory/observer-reflector.js.map +1 -1
  119. package/dist/memory/pipeline-manifest-sqlite.d.ts.map +1 -1
  120. package/dist/memory/pipeline-manifest-sqlite.js +13 -3
  121. package/dist/memory/pipeline-manifest-sqlite.js.map +1 -1
  122. package/dist/memory/quality-feedback.js +4 -4
  123. package/dist/memory/quality-feedback.js.map +1 -1
  124. package/dist/memory/retrieval/increment-citation-counts.js +1 -1
  125. package/dist/memory/retrieval/increment-citation-counts.js.map +1 -1
  126. package/dist/memory/retrieval/log-retrieval.js +1 -1
  127. package/dist/memory/retrieval/log-retrieval.js.map +1 -1
  128. package/dist/memory/retrieval/observe.js +1 -1
  129. package/dist/memory/retrieval/observe.js.map +1 -1
  130. package/dist/memory/retrieval/search.js +1 -1
  131. package/dist/memory/retrieval/search.js.map +1 -1
  132. package/dist/memory/retrieval/timeline.js +1 -1
  133. package/dist/memory/retrieval/timeline.js.map +1 -1
  134. package/dist/memory/sleep-consolidation.js +4 -4
  135. package/dist/memory/sleep-consolidation.js.map +1 -1
  136. package/dist/memory/temporal-supersession.js +5 -5
  137. package/dist/memory/temporal-supersession.js.map +1 -1
  138. package/dist/memory/transcript-extractor.js +1 -1
  139. package/dist/memory/transcript-extractor.js.map +1 -1
  140. package/dist/memory/transcript-ingestor.js +1 -1
  141. package/dist/memory/transcript-ingestor.js.map +1 -1
  142. package/dist/memory/transcript-scanner.js +1 -1
  143. package/dist/memory/transcript-scanner.js.map +1 -1
  144. package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
  145. package/dist/nexus/analyze-orchestrator.js +28 -0
  146. package/dist/nexus/analyze-orchestrator.js.map +1 -1
  147. package/dist/nexus/context.d.ts.map +1 -1
  148. package/dist/nexus/context.js +3 -3
  149. package/dist/nexus/context.js.map +1 -1
  150. package/dist/nexus/impact.d.ts.map +1 -1
  151. package/dist/nexus/impact.js +3 -3
  152. package/dist/nexus/impact.js.map +1 -1
  153. package/dist/nexus/living-brain.js +7 -7
  154. package/dist/nexus/living-brain.js.map +1 -1
  155. package/dist/nexus/symbol-miss.d.ts +132 -0
  156. package/dist/nexus/symbol-miss.d.ts.map +1 -0
  157. package/dist/nexus/symbol-miss.js +168 -0
  158. package/dist/nexus/symbol-miss.js.map +1 -0
  159. package/dist/nexus/tasks-bridge.js +4 -4
  160. package/dist/nexus/tasks-bridge.js.map +1 -1
  161. package/dist/orchestrate/spawn-ops.d.ts +21 -1
  162. package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
  163. package/dist/orchestrate/spawn-ops.js +39 -2
  164. package/dist/orchestrate/spawn-ops.js.map +1 -1
  165. package/dist/orchestrate/worker-verify.d.ts.map +1 -1
  166. package/dist/orchestrate/worker-verify.js +22 -0
  167. package/dist/orchestrate/worker-verify.js.map +1 -1
  168. package/dist/release/changesets-aggregator.d.ts.map +1 -1
  169. package/dist/release/changesets-aggregator.js +15 -1
  170. package/dist/release/changesets-aggregator.js.map +1 -1
  171. package/dist/release/open.d.ts +29 -2
  172. package/dist/release/open.d.ts.map +1 -1
  173. package/dist/release/open.js +48 -11
  174. package/dist/release/open.js.map +1 -1
  175. package/dist/release/reconcile.d.ts.map +1 -1
  176. package/dist/release/reconcile.js +5 -1
  177. package/dist/release/reconcile.js.map +1 -1
  178. package/dist/resources/governor.d.ts +12 -2
  179. package/dist/resources/governor.d.ts.map +1 -1
  180. package/dist/resources/governor.js +12 -3
  181. package/dist/resources/governor.js.map +1 -1
  182. package/dist/sagas/migrate-containment.d.ts.map +1 -1
  183. package/dist/sagas/migrate-containment.js +4 -2
  184. package/dist/sagas/migrate-containment.js.map +1 -1
  185. package/dist/scaffold/ensure-dirs.d.ts.map +1 -1
  186. package/dist/scaffold/ensure-dirs.js +15 -3
  187. package/dist/scaffold/ensure-dirs.js.map +1 -1
  188. package/dist/scaffold/project-detection.d.ts.map +1 -1
  189. package/dist/scaffold/project-detection.js +2 -1
  190. package/dist/scaffold/project-detection.js.map +1 -1
  191. package/dist/selfimprove/draft-pr.d.ts +14 -1
  192. package/dist/selfimprove/draft-pr.d.ts.map +1 -1
  193. package/dist/selfimprove/draft-pr.js.map +1 -1
  194. package/dist/selfimprove/fix-gen.d.ts +0 -21
  195. package/dist/selfimprove/fix-gen.d.ts.map +1 -1
  196. package/dist/selfimprove/fix-gen.js +509 -173
  197. package/dist/selfimprove/fix-gen.js.map +3 -3
  198. package/dist/selfimprove/run-loop.d.ts.map +1 -1
  199. package/dist/selfimprove/run-loop.js +50 -19
  200. package/dist/selfimprove/run-loop.js.map +1 -1
  201. package/dist/selfimprove/scenarios/dhq-replay-find/golden.json +114 -4
  202. package/dist/selfimprove/scenarios/dhq-replay-find/scenario.json +3 -3
  203. package/dist/sentient/dream-cycle.d.ts +20 -19
  204. package/dist/sentient/dream-cycle.d.ts.map +1 -1
  205. package/dist/sentient/dream-cycle.js +323 -12
  206. package/dist/sentient/dream-cycle.js.map +1 -1
  207. package/dist/sentient/dream-watermark.d.ts +134 -0
  208. package/dist/sentient/dream-watermark.d.ts.map +1 -0
  209. package/dist/sentient/dream-watermark.js +156 -0
  210. package/dist/sentient/dream-watermark.js.map +1 -0
  211. package/dist/sentient/hygiene-scan.js +1 -1
  212. package/dist/sentient/hygiene-scan.js.map +1 -1
  213. package/dist/sentient/propose-tick.js +3 -3
  214. package/dist/sentient/propose-tick.js.map +1 -1
  215. package/dist/sentient/stage-drift-tick.js +1 -1
  216. package/dist/sentient/stage-drift-tick.js.map +1 -1
  217. package/dist/sentient/state.d.ts +17 -0
  218. package/dist/sentient/state.d.ts.map +1 -1
  219. package/dist/sentient/state.js +22 -3
  220. package/dist/sentient/state.js.map +1 -1
  221. package/dist/sentient/tick.d.ts.map +1 -1
  222. package/dist/sentient/tick.js +79 -2
  223. package/dist/sentient/tick.js.map +1 -1
  224. package/dist/sequence/index.js +1 -1
  225. package/dist/sequence/index.js.map +1 -1
  226. package/dist/sessions/index.d.ts.map +1 -1
  227. package/dist/sessions/index.js +5 -1
  228. package/dist/sessions/index.js.map +1 -1
  229. package/dist/sessions/snapshot.d.ts.map +1 -1
  230. package/dist/sessions/snapshot.js +6 -3
  231. package/dist/sessions/snapshot.js.map +1 -1
  232. package/dist/store/agent-registry-store.d.ts.map +1 -1
  233. package/dist/store/agent-registry-store.js +71 -28
  234. package/dist/store/agent-registry-store.js.map +1 -1
  235. package/dist/store/attachment-store.js +3 -3
  236. package/dist/store/attachment-store.js.map +1 -1
  237. package/dist/store/checkpoint-git-dir.d.ts +95 -0
  238. package/dist/store/checkpoint-git-dir.d.ts.map +1 -0
  239. package/dist/store/checkpoint-git-dir.js +111 -0
  240. package/dist/store/checkpoint-git-dir.js.map +1 -0
  241. package/dist/store/conduit-sqlite.d.ts +21 -1
  242. package/dist/store/conduit-sqlite.d.ts.map +1 -1
  243. package/dist/store/conduit-sqlite.js +42 -56
  244. package/dist/store/conduit-sqlite.js.map +1 -1
  245. package/dist/store/dual-scope-db.d.ts +39 -0
  246. package/dist/store/dual-scope-db.d.ts.map +1 -1
  247. package/dist/store/dual-scope-db.js +26 -8
  248. package/dist/store/dual-scope-db.js.map +1 -1
  249. package/dist/store/git-checkpoint.d.ts.map +1 -1
  250. package/dist/store/git-checkpoint.js +6 -5
  251. package/dist/store/git-checkpoint.js.map +1 -1
  252. package/dist/store/memory-sqlite.d.ts +57 -3
  253. package/dist/store/memory-sqlite.d.ts.map +1 -1
  254. package/dist/store/memory-sqlite.js +70 -89
  255. package/dist/store/memory-sqlite.js.map +1 -1
  256. package/dist/store/nexus-sqlite.d.ts +42 -0
  257. package/dist/store/nexus-sqlite.d.ts.map +1 -1
  258. package/dist/store/nexus-sqlite.js +79 -115
  259. package/dist/store/nexus-sqlite.js.map +1 -1
  260. package/dist/store/ports/domain-binding.d.ts +233 -0
  261. package/dist/store/ports/domain-binding.d.ts.map +1 -0
  262. package/dist/store/ports/domain-binding.js +500 -0
  263. package/dist/store/ports/domain-binding.js.map +1 -0
  264. package/dist/store/ports/fk-integrity.d.ts +155 -0
  265. package/dist/store/ports/fk-integrity.d.ts.map +1 -0
  266. package/dist/store/ports/fk-integrity.js +182 -0
  267. package/dist/store/ports/fk-integrity.js.map +1 -0
  268. package/dist/store/role-accessors-impl.js +2 -2
  269. package/dist/store/role-accessors-impl.js.map +1 -1
  270. package/dist/store/skills-db.d.ts +19 -0
  271. package/dist/store/skills-db.d.ts.map +1 -1
  272. package/dist/store/skills-db.js +80 -72
  273. package/dist/store/skills-db.js.map +1 -1
  274. package/dist/store/sqlite-backup.js +2 -2
  275. package/dist/store/sqlite-backup.js.map +1 -1
  276. package/dist/store/sqlite-data-accessor.js +1 -1
  277. package/dist/store/sqlite-data-accessor.js.map +1 -1
  278. package/dist/store/sqlite.d.ts +72 -10
  279. package/dist/store/sqlite.d.ts.map +1 -1
  280. package/dist/store/sqlite.js +173 -160
  281. package/dist/store/sqlite.js.map +1 -1
  282. package/dist/store/tasks-sqlite.js +2 -2
  283. package/dist/store/tasks-sqlite.js.map +1 -1
  284. package/dist/system/health.d.ts +0 -4
  285. package/dist/system/health.d.ts.map +1 -1
  286. package/dist/system/health.js +60 -3
  287. package/dist/system/health.js.map +1 -1
  288. package/dist/tasks/add.d.ts.map +1 -1
  289. package/dist/tasks/add.js +40 -4
  290. package/dist/tasks/add.js.map +1 -1
  291. package/dist/tasks/collection.d.ts +51 -0
  292. package/dist/tasks/collection.d.ts.map +1 -0
  293. package/dist/tasks/collection.js +81 -0
  294. package/dist/tasks/collection.js.map +1 -0
  295. package/dist/tasks/complete.d.ts.map +1 -1
  296. package/dist/tasks/complete.js +8 -3
  297. package/dist/tasks/complete.js.map +1 -1
  298. package/dist/tasks/evidence.d.ts.map +1 -1
  299. package/dist/tasks/evidence.js +17 -0
  300. package/dist/tasks/evidence.js.map +1 -1
  301. package/dist/tasks/find.d.ts +50 -0
  302. package/dist/tasks/find.d.ts.map +1 -1
  303. package/dist/tasks/find.js +63 -2
  304. package/dist/tasks/find.js.map +1 -1
  305. package/dist/tasks/tool-resolver.d.ts +1 -1
  306. package/dist/tasks/tool-resolver.d.ts.map +1 -1
  307. package/dist/tasks/tool-resolver.js +83 -0
  308. package/dist/tasks/tool-resolver.js.map +1 -1
  309. package/dist/tasks/tool-semaphore.d.ts +82 -12
  310. package/dist/tasks/tool-semaphore.d.ts.map +1 -1
  311. package/dist/tasks/tool-semaphore.js +79 -17
  312. package/dist/tasks/tool-semaphore.js.map +1 -1
  313. package/dist/upgrade.js +2 -2
  314. package/dist/upgrade.js.map +1 -1
  315. package/dist/validation/doctor/checks.d.ts +23 -1
  316. package/dist/validation/doctor/checks.d.ts.map +1 -1
  317. package/dist/validation/doctor/checks.js +79 -19
  318. package/dist/validation/doctor/checks.js.map +1 -1
  319. package/dist/worktree/list.js +1 -1
  320. package/dist/worktree/list.js.map +1 -1
  321. package/package.json +23 -13
  322. package/templates/CLEO-INJECTION.md +40 -25
  323. package/templates/workflows/release-prepare.yml.tmpl +73 -16
@@ -102,9 +102,9 @@ function getLogDir() {
102
102
  return currentLogDir;
103
103
  }
104
104
  function closeLogger() {
105
- return new Promise((resolve6) => {
105
+ return new Promise((resolve7) => {
106
106
  if (!rootLogger) {
107
- resolve6();
107
+ resolve7();
108
108
  return;
109
109
  }
110
110
  const logger8 = rootLogger;
@@ -116,7 +116,7 @@ function closeLogger() {
116
116
  rootLogger = null;
117
117
  currentLogDir = null;
118
118
  currentTransport = null;
119
- resolve6();
119
+ resolve7();
120
120
  };
121
121
  logger8.flush(() => {
122
122
  if (transport && typeof transport.end === "function") {
@@ -10178,6 +10178,27 @@ var init_operations_registry = __esm({
10178
10178
  type: "boolean",
10179
10179
  required: false,
10180
10180
  description: "Commit plan file before dispatching"
10181
+ },
10182
+ // T12089: the plan SCOPE. The workflow regenerates the plan when no
10183
+ // committed plan is supplied, and `cleo release plan` requires
10184
+ // `--saga | --epic | --tasks` — so without one of these the dispatched
10185
+ // run dies at "Prepare bump-PR" after a fully green preflight.
10186
+ //
10187
+ // A param absent from this registry is STRIPPED before the domain handler
10188
+ // sees it, silently. `--tasks` was accepted by the CLI, forwarded by the
10189
+ // handler and by `releaseOpen`, and still arrived empty at the workflow
10190
+ // because this declaration was the fourth hop in the chain.
10191
+ {
10192
+ name: "epic",
10193
+ type: "string",
10194
+ required: false,
10195
+ description: "Epic task ID forwarded as the plan scope (e.g. T9999)"
10196
+ },
10197
+ {
10198
+ name: "tasks",
10199
+ type: "string",
10200
+ required: false,
10201
+ description: "Comma-separated task IDs forwarded as the plan scope for a task-scoped release"
10181
10202
  }
10182
10203
  ]
10183
10204
  },
@@ -15796,6 +15817,25 @@ var init_service_provider = __esm({
15796
15817
  }
15797
15818
  });
15798
15819
 
15820
+ // packages/contracts/src/caamp-markers.ts
15821
+ var H, damagedMarkerSource, CAAMP_DAMAGED_START_PATTERN_SOURCE, CAAMP_DAMAGED_END_PATTERN_SOURCE;
15822
+ var init_caamp_markers = __esm({
15823
+ "packages/contracts/src/caamp-markers.ts"() {
15824
+ "use strict";
15825
+ H = "[ \\t\\r]";
15826
+ damagedMarkerSource = (keyword) => `^${H}*[<!-]{1,4}${H}*CAAMP${H}*:${H}*${keyword}${H}*[->]{1,3}${H}*$`;
15827
+ CAAMP_DAMAGED_START_PATTERN_SOURCE = damagedMarkerSource("START");
15828
+ CAAMP_DAMAGED_END_PATTERN_SOURCE = damagedMarkerSource("END");
15829
+ }
15830
+ });
15831
+
15832
+ // packages/contracts/src/collection-keys.ts
15833
+ var init_collection_keys = __esm({
15834
+ "packages/contracts/src/collection-keys.ts"() {
15835
+ "use strict";
15836
+ }
15837
+ });
15838
+
15799
15839
  // packages/contracts/src/index.ts
15800
15840
  var init_src = __esm({
15801
15841
  "packages/contracts/src/index.ts"() {
@@ -15863,6 +15903,8 @@ var init_src = __esm({
15863
15903
  init_validator();
15864
15904
  init_service_provider();
15865
15905
  init_workgraph();
15906
+ init_caamp_markers();
15907
+ init_collection_keys();
15866
15908
  }
15867
15909
  });
15868
15910
 
@@ -17872,7 +17914,7 @@ var init_sql = __esm({
17872
17914
  return new SQL([new StringChunk(str)]);
17873
17915
  }
17874
17916
  _sql.raw = raw;
17875
- function join34(chunks, separator) {
17917
+ function join35(chunks, separator) {
17876
17918
  const result = [];
17877
17919
  for (const [i, chunk] of chunks.entries()) {
17878
17920
  if (i > 0 && separator !== void 0) result.push(separator);
@@ -17880,7 +17922,7 @@ var init_sql = __esm({
17880
17922
  }
17881
17923
  return new SQL(result);
17882
17924
  }
17883
- _sql.join = join34;
17925
+ _sql.join = join35;
17884
17926
  function identifier(value) {
17885
17927
  return new Name(value);
17886
17928
  }
@@ -19849,7 +19891,7 @@ var init_select = __esm({
19849
19891
  const baseTableName = this.tableName;
19850
19892
  const tableName = getTableLikeName(table);
19851
19893
  for (const item of extractUsedTable(table)) this.usedTables.add(item);
19852
- if (typeof tableName === "string" && this.config.joins?.some((join34) => join34.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
19894
+ if (typeof tableName === "string" && this.config.joins?.some((join35) => join35.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
19853
19895
  if (!this.isPartialSelect) {
19854
19896
  if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
19855
19897
  if (typeof tableName === "string" && !is(table, SQL)) {
@@ -21446,7 +21488,7 @@ var init_dialect = __esm({
21446
21488
  if (!joins2) return;
21447
21489
  const withEntries = Object.entries(joins2).filter(([_, v]) => v);
21448
21490
  if (!withEntries.length) return;
21449
- return sql.join(withEntries.map(([k, join34]) => {
21491
+ return sql.join(withEntries.map(([k, join35]) => {
21450
21492
  const relation = tableConfig.relations[k];
21451
21493
  const isSingle2 = is(relation, One);
21452
21494
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
@@ -21457,7 +21499,7 @@ var init_dialect = __esm({
21457
21499
  table: targetTable,
21458
21500
  mode: isSingle2 ? "first" : "many",
21459
21501
  schema,
21460
- queryConfig: join34,
21502
+ queryConfig: join35,
21461
21503
  tableConfig: schema[relation.targetTableName],
21462
21504
  relationWhere: filter2,
21463
21505
  isNested: true,
@@ -21471,7 +21513,7 @@ var init_dialect = __esm({
21471
21513
  key: k,
21472
21514
  selection: innerQuery.selection,
21473
21515
  isArray: !isSingle2,
21474
- isOptional: (relation.optional ?? false) || join34 !== true && !!join34.where
21516
+ isOptional: (relation.optional ?? false) || join35 !== true && !!join35.where
21475
21517
  });
21476
21518
  const jsonColumns = sql.join(innerQuery.selection.map((s) => {
21477
21519
  return sql`${sql.raw(this.escapeString(s.key))}, ${s.selection ? sql`${jsonb}(${sql.identifier(s.key)})` : sql.identifier(s.key)}`;
@@ -21893,7 +21935,7 @@ var init_update = __esm({
21893
21935
  createJoin(joinType) {
21894
21936
  return ((table, on) => {
21895
21937
  const tableName = getTableLikeName(table);
21896
- if (typeof tableName === "string" && this.config.joins.some((join34) => join34.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
21938
+ if (typeof tableName === "string" && this.config.joins.some((join35) => join35.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
21897
21939
  if (typeof on === "function") {
21898
21940
  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;
21899
21941
  on = on(new Proxy(this.config.table[Table.Symbol.Columns], new SelectionProxyHandler({
@@ -23712,7 +23754,7 @@ function resolveDbIdentity(db) {
23712
23754
  return identity;
23713
23755
  }
23714
23756
  function sleepAsync(ms) {
23715
- return new Promise((resolve6) => setTimeout(resolve6, Math.max(0, Math.round(ms))));
23757
+ return new Promise((resolve7) => setTimeout(resolve7, Math.max(0, Math.round(ms))));
23716
23758
  }
23717
23759
  function isPidAlive(pid) {
23718
23760
  try {
@@ -24530,7 +24572,7 @@ async function sendResourceRelease(socketPath, cls, holderId) {
24530
24572
  return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
24531
24573
  }
24532
24574
  function sendLeaseRequest(socketPath, request, expectedKind) {
24533
- return new Promise((resolve6) => {
24575
+ return new Promise((resolve7) => {
24534
24576
  const id = `ra-${process.pid}-${request.kind}`;
24535
24577
  const envelope = LeaseIpcRequestEnvelopeSchema.parse({
24536
24578
  protocol_version: LEASE_IPC_PROTOCOL_VERSION,
@@ -24548,7 +24590,7 @@ function sendLeaseRequest(socketPath, request, expectedKind) {
24548
24590
  settled = true;
24549
24591
  socket.removeAllListeners();
24550
24592
  socket.destroy();
24551
- resolve6(value);
24593
+ resolve7(value);
24552
24594
  };
24553
24595
  const degrade = (reason) => done({ unavailable: true, reason });
24554
24596
  socket.setTimeout(REQUEST_TIMEOUT_MS);
@@ -24671,7 +24713,9 @@ function computeClassBudget(cls, sample, opts = {}) {
24671
24713
  return Math.max(1, cpus - 2);
24672
24714
  case "test-run":
24673
24715
  case "scoped-build": {
24674
- const base = Math.max(1, Math.floor(cpus / 4));
24716
+ const estRamBytes = (opts.testRunEstRamMb ?? 24576) * MB;
24717
+ const byMem = Math.floor((availBytes - headroomBytes) / estRamBytes);
24718
+ const base = clamp2(1, byMem, Math.max(1, Math.floor(cpus / 4)));
24675
24719
  if (some > floor) return 1;
24676
24720
  if (some > hold) return Math.max(1, Math.floor(base / 2));
24677
24721
  return base;
@@ -25164,6 +25208,11 @@ var init_registry = __esm({
25164
25208
  * });
25165
25209
  * ```
25166
25210
  */
25211
+ // T12071: keyed on the EVENT so the payload shape is checked against
25212
+ // `HookEventPayloadMap`. The previous `<T extends HookPayload>` form inferred
25213
+ // T from the argument, relating the event and the payload not at all — which
25214
+ // is how `PostToolUse` came to be dispatched with `newStatus` instead of
25215
+ // `status` and filled 29% of BRAIN with "status: undefined".
25167
25216
  async dispatch(event, projectRoot, payload) {
25168
25217
  if (!this.config.enabled) return;
25169
25218
  const resolvedEvent = this.resolveEvent(event);
@@ -27973,8 +28022,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
27973
28022
  }
27974
28023
  let initResolve = null;
27975
28024
  let initReject = null;
27976
- const initPromise = new Promise((resolve6, reject) => {
27977
- initResolve = resolve6;
28025
+ const initPromise = new Promise((resolve7, reject) => {
28026
+ initResolve = resolve7;
27978
28027
  initReject = reject;
27979
28028
  });
27980
28029
  _cache.set(key, {
@@ -28227,24 +28276,35 @@ var init_dual_scope_db = __esm({
28227
28276
  async openProject(dbPath, options) {
28228
28277
  const normalized = resolve3(dbPath);
28229
28278
  if (options?.dedicated) {
28230
- const handle = await openDualScopeDbAtPath("project", normalized, void 0, {
28279
+ const handle = await openDualScopeDbAtPath("project", normalized, options?.exodusCwd, {
28231
28280
  dedicated: true
28232
28281
  });
28233
28282
  return this.buildStore("project", handle, 0);
28234
28283
  }
28235
- return this.openEntry("project", normalized);
28284
+ return this.openEntry("project", normalized, 0, options?.exodusCwd);
28236
28285
  }
28237
28286
  /** @inheritdoc */
28238
28287
  async openGlobal(options) {
28239
28288
  const dbPath = resolveDualScopeDbPath("global");
28240
28289
  const normalized = resolve3(dbPath);
28241
28290
  if (options?.dedicated) {
28242
- const handle = await openDualScopeDbAtPath("global", normalized, void 0, {
28291
+ const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
28292
+ dedicated: true
28293
+ });
28294
+ return this.buildStore("global", handle, 0);
28295
+ }
28296
+ return this.openEntry("global", normalized, 0, options?.exodusCwd);
28297
+ }
28298
+ /** @inheritdoc */
28299
+ async openGlobalAt(dbPath, options) {
28300
+ const normalized = resolve3(dbPath);
28301
+ if (options?.dedicated) {
28302
+ const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
28243
28303
  dedicated: true
28244
28304
  });
28245
28305
  return this.buildStore("global", handle, 0);
28246
28306
  }
28247
- return this.openEntry("global", normalized);
28307
+ return this.openEntry("global", normalized, 0, options?.exodusCwd);
28248
28308
  }
28249
28309
  /** @inheritdoc */
28250
28310
  closeProject(dbPath) {
@@ -28270,7 +28330,7 @@ var init_dual_scope_db = __esm({
28270
28330
  * retry calls this with `depth + 1`. A second dead handle at depth 1
28271
28331
  * throws {@link LivenessExhaustedError} instead of recursing further.
28272
28332
  */
28273
- async openEntry(scope, dbPath, depth = 0) {
28333
+ async openEntry(scope, dbPath, depth = 0, exodusCwd) {
28274
28334
  const key = cacheKey(scope, dbPath);
28275
28335
  const existing = this._registry.get(key);
28276
28336
  if (existing) {
@@ -28285,8 +28345,8 @@ var init_dual_scope_db = __esm({
28285
28345
  const entryId = ++this._nextId;
28286
28346
  let initResolve;
28287
28347
  let initReject;
28288
- const initPromise = new Promise((resolve6, reject) => {
28289
- initResolve = resolve6;
28348
+ const initPromise = new Promise((resolve7, reject) => {
28349
+ initResolve = resolve7;
28290
28350
  initReject = reject;
28291
28351
  });
28292
28352
  this._registry.set(key, { id: entryId, store: null, initPromise });
@@ -28297,7 +28357,7 @@ var init_dual_scope_db = __esm({
28297
28357
  }
28298
28358
  });
28299
28359
  try {
28300
- const dualHandle = scope === "project" ? await this.openDualScopeFn("project", dbPath) : await this.openDualScopeFn("global", dbPath);
28360
+ const dualHandle = scope === "project" ? await this.openDualScopeFn("project", dbPath, exodusCwd) : await this.openDualScopeFn("global", dbPath, exodusCwd);
28301
28361
  const current = this._registry.get(key);
28302
28362
  if (!current || current.id !== entryId) {
28303
28363
  throw new EntryCancelledError(scope, dbPath);
@@ -28308,7 +28368,7 @@ var init_dual_scope_db = __esm({
28308
28368
  if (depth >= 1) {
28309
28369
  throw new LivenessExhaustedError(scope, dbPath);
28310
28370
  }
28311
- const retryStore = await this.openEntry(scope, dbPath, depth + 1);
28371
+ const retryStore = await this.openEntry(scope, dbPath, depth + 1, exodusCwd);
28312
28372
  initResolve(retryStore);
28313
28373
  return retryStore;
28314
28374
  }
@@ -28404,6 +28464,151 @@ var init_dual_scope_db = __esm({
28404
28464
  }
28405
28465
  });
28406
28466
 
28467
+ // packages/core/src/store/ports/domain-binding.ts
28468
+ import { resolve as resolve4 } from "node:path";
28469
+ function getCleoRuntime() {
28470
+ if (!_runtime) {
28471
+ _runtime = createCleoRuntime();
28472
+ }
28473
+ return _runtime;
28474
+ }
28475
+ function bindingKey(scope, dbPath, domain2) {
28476
+ return `${scope}::${dbPath}::${domain2}`;
28477
+ }
28478
+ function nativeOf(store) {
28479
+ const native = store.db.$client;
28480
+ if (!native) {
28481
+ throw new Error(
28482
+ `T12037: CleoRuntime store for ${store.scope}::${store.dbPath} exposed no $client \u2014 cannot bind a domain schema to it.`
28483
+ );
28484
+ }
28485
+ return native;
28486
+ }
28487
+ function reuseValid(key, store) {
28488
+ const row = _bindings.get(key);
28489
+ if (!row) return void 0;
28490
+ if (row.store !== store || !store.isOpen || !row.native.isOpen) {
28491
+ _bindings.delete(key);
28492
+ return void 0;
28493
+ }
28494
+ return row;
28495
+ }
28496
+ async function bindAgainst(key, store, establish) {
28497
+ const cached3 = reuseValid(key, store);
28498
+ if (cached3) return cached3;
28499
+ const pending = _inflight.get(key);
28500
+ if (pending) {
28501
+ const row = await pending;
28502
+ if (row.store === store && row.native.isOpen) return row;
28503
+ return bindAgainst(key, store, establish);
28504
+ }
28505
+ const native = nativeOf(store);
28506
+ const flight = (async () => {
28507
+ const db = await establish(native, store);
28508
+ const row = { store, native, db };
28509
+ if (store.isOpen && native.isOpen) {
28510
+ _bindings.set(key, row);
28511
+ }
28512
+ return row;
28513
+ })();
28514
+ _inflight.set(key, flight);
28515
+ try {
28516
+ return await flight;
28517
+ } finally {
28518
+ if (_inflight.get(key) === flight) {
28519
+ _inflight.delete(key);
28520
+ }
28521
+ }
28522
+ }
28523
+ async function bindLive(scope, key, dbPath, openStore, establish) {
28524
+ let lastError;
28525
+ for (let attempt = 0; attempt < MAX_LIVENESS_ATTEMPTS; attempt += 1) {
28526
+ let store;
28527
+ try {
28528
+ store = await openStore();
28529
+ } catch (err) {
28530
+ lastError = err;
28531
+ releaseDomainBindings({ scope, dbPath });
28532
+ if (attempt + 1 >= MAX_LIVENESS_ATTEMPTS) throw err;
28533
+ continue;
28534
+ }
28535
+ try {
28536
+ const row = await bindAgainst(key, store, establish);
28537
+ if (row.store.isOpen && row.native.isOpen) return row;
28538
+ } catch (err) {
28539
+ lastError = err;
28540
+ if (store.isOpen) throw err;
28541
+ }
28542
+ releaseDomainBindings({ scope, dbPath });
28543
+ try {
28544
+ store.close();
28545
+ } catch {
28546
+ }
28547
+ }
28548
+ if (lastError !== void 0) throw lastError;
28549
+ throw new Error(
28550
+ `T12037: could not bind ${key} over a live connection after ${MAX_LIVENESS_ATTEMPTS} attempts \u2014 the consolidated handle was closed each time.`
28551
+ );
28552
+ }
28553
+ async function bindProjectDomain(domain2, cwd, establish) {
28554
+ const dbPath = resolve4(resolveDualScopeDbPath("project", cwd));
28555
+ const row = await bindLive(
28556
+ "project",
28557
+ bindingKey("project", dbPath, domain2),
28558
+ dbPath,
28559
+ () => getCleoRuntime().openProject(dbPath, { exodusCwd: cwd }),
28560
+ establish
28561
+ );
28562
+ return row;
28563
+ }
28564
+ function releaseDomainBindings(filter2) {
28565
+ if (!filter2) {
28566
+ _bindings.clear();
28567
+ return;
28568
+ }
28569
+ const wantPath = filter2.dbPath === void 0 ? void 0 : resolve4(filter2.dbPath);
28570
+ for (const key of [..._bindings.keys()]) {
28571
+ const sep = key.indexOf("::");
28572
+ const lastSep = key.lastIndexOf("::");
28573
+ const scope = key.slice(0, sep);
28574
+ const dbPath = key.slice(sep + 2, lastSep);
28575
+ const domain2 = key.slice(lastSep + 2);
28576
+ if (filter2.scope !== void 0 && scope !== filter2.scope) continue;
28577
+ if (wantPath !== void 0 && dbPath !== wantPath) continue;
28578
+ if (filter2.domain !== void 0 && domain2 !== filter2.domain) continue;
28579
+ _bindings.delete(key);
28580
+ }
28581
+ }
28582
+ function boundProjectNative(domain2, cwd) {
28583
+ return peekProjectDomain(domain2, cwd)?.native ?? null;
28584
+ }
28585
+ function peekProjectDomain(domain2, cwd) {
28586
+ const dbPath = resolve4(resolveDualScopeDbPath("project", cwd));
28587
+ const row = _bindings.get(bindingKey("project", dbPath, domain2));
28588
+ if (row?.native.isOpen) return row;
28589
+ if (cwd !== void 0) return null;
28590
+ const suffix = `::${domain2}`;
28591
+ let sole;
28592
+ for (const [key, candidate] of _bindings) {
28593
+ if (!key.startsWith("project::") || !key.endsWith(suffix)) continue;
28594
+ if (!candidate.native.isOpen) continue;
28595
+ if (sole) return null;
28596
+ sole = candidate;
28597
+ }
28598
+ return sole ?? null;
28599
+ }
28600
+ var _runtime, _bindings, _inflight, MAX_LIVENESS_ATTEMPTS;
28601
+ var init_domain_binding = __esm({
28602
+ "packages/core/src/store/ports/domain-binding.ts"() {
28603
+ "use strict";
28604
+ init_dual_scope_db();
28605
+ _runtime = null;
28606
+ _bindings = /* @__PURE__ */ new Map();
28607
+ _inflight = /* @__PURE__ */ new Map();
28608
+ MAX_LIVENESS_ATTEMPTS = 2;
28609
+ }
28610
+ });
28611
+
28407
28612
  // packages/core/src/store/schema/nexus-schema.ts
28408
28613
  var nexus_schema_exports = {};
28409
28614
  __export(nexus_schema_exports, {
@@ -28912,6 +29117,7 @@ var nexus_sqlite_exports = {};
28912
29117
  __export(nexus_sqlite_exports, {
28913
29118
  NEXUS_SCHEMA_VERSION: () => NEXUS_SCHEMA_VERSION,
28914
29119
  _resetNestedNexusWarningGate: () => _resetNestedNexusWarningGate,
29120
+ bindNexusDomain: () => bindNexusDomain,
28915
29121
  closeNexusDb: () => closeNexusDb,
28916
29122
  detectAndWarnOnNestedNexus: () => detectAndWarnOnNestedNexus,
28917
29123
  getNestedNexusSentinelPath: () => getNestedNexusSentinelPath,
@@ -29120,13 +29326,13 @@ function ensureNexusRelationWeights(nativeDb) {
29120
29326
  nativeDb.exec(`PRAGMA foreign_keys=${fkWasOn ? "ON" : "OFF"}`);
29121
29327
  }
29122
29328
  }
29123
- function runNexusMigrations(nativeDb, db) {
29329
+ function runNexusMigrations(nativeDb, db, dbPath) {
29124
29330
  const migrationsFolder = resolveNexusMigrationsFolder();
29125
- if (tableExists4(nativeDb, "nexus_nodes") && _nexusDbPath) {
29126
- const backupPath = _nexusDbPath.replace(/\.db$/, "-pre-cleo.db.bak");
29331
+ if (tableExists4(nativeDb, "nexus_nodes")) {
29332
+ const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
29127
29333
  if (!existsSync15(backupPath)) {
29128
29334
  try {
29129
- copyFileSync4(_nexusDbPath, backupPath);
29335
+ copyFileSync4(dbPath, backupPath);
29130
29336
  } catch {
29131
29337
  }
29132
29338
  }
@@ -29168,75 +29374,45 @@ function runNexusMigrations(nativeDb, db) {
29168
29374
  ensureNexusFts5(nativeDb);
29169
29375
  }
29170
29376
  async function getNexusDb() {
29171
- const requestedPath = getNexusDbPath();
29377
+ return (await bindNexusDomain()).db.drizzle;
29378
+ }
29379
+ async function bindNexusDomain() {
29172
29380
  const requestedRegistryPath = getNexusRegistryDbPath();
29173
- if (_nexusDb && _nexusDbPath !== requestedPath) {
29174
- resetNexusDbState();
29175
- }
29176
- if (_nexusDb && _nexusRegistryPath !== requestedRegistryPath) {
29177
- resetNexusDbState();
29381
+ const bound = peekProjectDomain("nexus");
29382
+ if (bound && bound.db.registryPath !== requestedRegistryPath) {
29383
+ releaseDomainBindings({ scope: "project", domain: "nexus" });
29178
29384
  }
29179
- if (_nexusDb && (_nexusNativeDb === null || !_nexusNativeDb.isOpen)) {
29180
- resetNexusDbState();
29181
- }
29182
- if (_nexusDb) {
29183
- if (_nexusNativeDb) {
29184
- try {
29185
- ensureGlobalRegistryAttached(_nexusNativeDb);
29186
- } catch {
29187
- resetNexusDbState();
29188
- }
29189
- }
29190
- if (_nexusDb) return _nexusDb;
29191
- }
29192
- if (_nexusInitPromise) return _nexusInitPromise;
29193
- _nexusInitPromise = (async () => {
29194
- const dbPath = requestedPath;
29195
- _nexusDbPath = dbPath;
29196
- _nexusRegistryPath = requestedRegistryPath;
29197
- detectAndWarnOnNestedNexus();
29198
- await openDualScopeDb("global");
29199
- const dualHandle = await openDualScopeDb("project");
29200
- const nativeDb = dualHandle.db.$client ?? null;
29201
- if (!nativeDb) {
29202
- throw new Error(
29203
- "T11648: openDualScopeDb returned a handle without $client \u2014 cannot extract DatabaseSync for the nexus-schema drizzle wrapping."
29204
- );
29205
- }
29206
- _nexusNativeDb = nativeDb;
29385
+ detectAndWarnOnNestedNexus();
29386
+ await openDualScopeDb("global");
29387
+ const binding = await bindProjectDomain("nexus", void 0, (nativeDb, store) => {
29207
29388
  ensureGlobalRegistryAttached(nativeDb);
29208
29389
  const db = drizzle({ client: nativeDb });
29209
- runNexusMigrations(nativeDb, db);
29390
+ runNexusMigrations(nativeDb, db, store.dbPath);
29210
29391
  nativeDb.prepare(
29211
29392
  `INSERT OR IGNORE INTO nexus_schema_meta (key, value) VALUES ('schemaVersion', '${NEXUS_SCHEMA_VERSION}')`
29212
29393
  ).run();
29213
- _nexusDb = db;
29214
- return db;
29215
- })();
29394
+ return { drizzle: db, registryPath: requestedRegistryPath };
29395
+ });
29216
29396
  try {
29217
- return await _nexusInitPromise;
29218
- } finally {
29219
- _nexusInitPromise = null;
29397
+ ensureGlobalRegistryAttached(binding.native);
29398
+ } catch {
29399
+ releaseDomainBindings({ scope: "project", domain: "nexus" });
29400
+ throw new Error(
29401
+ "T12039: nexus binding lost its GLOBAL registry ATTACH and could not re-attach."
29402
+ );
29220
29403
  }
29404
+ return binding;
29221
29405
  }
29222
29406
  function closeNexusDb() {
29223
- _nexusNativeDb = null;
29224
- _nexusDb = null;
29225
- _nexusDbPath = null;
29226
- _nexusRegistryPath = null;
29227
- _nexusInitPromise = null;
29407
+ releaseDomainBindings({ scope: "project", domain: "nexus" });
29228
29408
  }
29229
29409
  function resetNexusDbState() {
29230
- _nexusNativeDb = null;
29231
- _nexusDb = null;
29232
- _nexusDbPath = null;
29233
- _nexusRegistryPath = null;
29234
- _nexusInitPromise = null;
29410
+ releaseDomainBindings({ scope: "project", domain: "nexus" });
29235
29411
  }
29236
29412
  function getNexusNativeDb() {
29237
- return _nexusNativeDb;
29413
+ return boundProjectNative("nexus");
29238
29414
  }
29239
- var NEXUS_SCHEMA_VERSION, _nexusDb, _nexusNativeDb, _nexusDbPath, _nexusRegistryPath, _nexusInitPromise, NEXUS_GLOBAL_ATTACH_ALIAS, NESTED_NEXUS_SENTINEL, _warnedNestedPaths;
29415
+ var NEXUS_SCHEMA_VERSION, NEXUS_GLOBAL_ATTACH_ALIAS, NESTED_NEXUS_SENTINEL, _warnedNestedPaths;
29240
29416
  var init_nexus_sqlite = __esm({
29241
29417
  "packages/core/src/store/nexus-sqlite.ts"() {
29242
29418
  "use strict";
@@ -29245,15 +29421,11 @@ var init_nexus_sqlite = __esm({
29245
29421
  init_paths();
29246
29422
  init_dual_scope_db();
29247
29423
  init_migration_manager();
29424
+ init_domain_binding();
29248
29425
  init_resolve_migrations_folder();
29249
29426
  init_nexus_schema();
29250
29427
  init_with_retry();
29251
29428
  NEXUS_SCHEMA_VERSION = "1.0.0";
29252
- _nexusDb = null;
29253
- _nexusNativeDb = null;
29254
- _nexusDbPath = null;
29255
- _nexusRegistryPath = null;
29256
- _nexusInitPromise = null;
29257
29429
  NEXUS_GLOBAL_ATTACH_ALIAS = "nexus_global";
29258
29430
  NESTED_NEXUS_SENTINEL = "nexus.db";
29259
29431
  _warnedNestedPaths = /* @__PURE__ */ new Set();
@@ -29265,7 +29437,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
29265
29437
  import { existsSync as existsSync16, readFileSync as readFileSync5, statSync as statSync5 } from "node:fs";
29266
29438
  import { createRequire as createRequire5 } from "node:module";
29267
29439
  import { homedir } from "node:os";
29268
- import { basename as basename4, dirname as dirname7, join as join17, resolve as resolve4 } from "node:path";
29440
+ import { basename as basename4, dirname as dirname7, join as join17, resolve as resolve5 } from "node:path";
29269
29441
  import {
29270
29442
  computeCanonicalProjectId as _computeCanonicalProjectId,
29271
29443
  getCanonicalTemplatesTildePath as _getCanonicalTemplatesTildePath,
@@ -29332,24 +29504,24 @@ function getCleoDirAbsolute(cwd, opts) {
29332
29504
  try {
29333
29505
  const projectRoot = getProjectRoot(cwd);
29334
29506
  const canonical = _resolveCanonicalCleoDir(project.projectId);
29335
- if (canonical !== null && canonical === resolve4(projectRoot, cleoDir)) {
29507
+ if (canonical !== null && canonical === resolve5(projectRoot, cleoDir)) {
29336
29508
  return canonical;
29337
29509
  }
29338
- return resolve4(projectRoot, cleoDir);
29510
+ return resolve5(projectRoot, cleoDir);
29339
29511
  } catch {
29340
- return resolve4(project.projectRoot, cleoDir);
29512
+ return resolve5(project.projectRoot, cleoDir);
29341
29513
  }
29342
29514
  }
29343
29515
  try {
29344
- return resolve4(getProjectRoot(cwd), cleoDir);
29516
+ return resolve5(getProjectRoot(cwd), cleoDir);
29345
29517
  } catch (err) {
29346
29518
  if (opts?.bootstrap) {
29347
- return resolve4(cwd ?? process.cwd(), cleoDir);
29519
+ return resolve5(cwd ?? process.cwd(), cleoDir);
29348
29520
  }
29349
29521
  if (_cwdHasGitAncestor(cwd)) {
29350
29522
  throw err;
29351
29523
  }
29352
- return resolve4(cwd ?? process.cwd(), cleoDir);
29524
+ return resolve5(cwd ?? process.cwd(), cleoDir);
29353
29525
  }
29354
29526
  }
29355
29527
  function _resolveProjectByCwdFromNexus(cwd) {
@@ -29357,7 +29529,7 @@ function _resolveProjectByCwdFromNexus(cwd) {
29357
29529
  const cleoHome = getCleoHome();
29358
29530
  const globalDbPath = join17(cleoHome, "cleo.db");
29359
29531
  if (!existsSync16(globalDbPath)) return null;
29360
- const start = resolve4(cwd ?? process.cwd());
29532
+ const start = resolve5(cwd ?? process.cwd());
29361
29533
  let current = start;
29362
29534
  const DatabaseSync2 = _getDatabaseSyncCtor();
29363
29535
  const db = new DatabaseSync2(globalDbPath, { readOnly: true });
@@ -29390,7 +29562,7 @@ function _cleoDirEnvOverride() {
29390
29562
  }
29391
29563
  function _findCleoDirRoot(cwd) {
29392
29564
  const homeRoot = homedir();
29393
- let current = resolve4(cwd ?? process.cwd());
29565
+ let current = resolve5(cwd ?? process.cwd());
29394
29566
  while (true) {
29395
29567
  const isDangerousRoot = current === homeRoot || current === "/" || current === "";
29396
29568
  if (!isDangerousRoot) {
@@ -29420,7 +29592,7 @@ function resolveCleoDir(cwd) {
29420
29592
  if (root !== null) {
29421
29593
  return join17(root, ".cleo");
29422
29594
  }
29423
- const start = resolve4(cwd ?? process.cwd());
29595
+ const start = resolve5(cwd ?? process.cwd());
29424
29596
  let current = start;
29425
29597
  while (true) {
29426
29598
  const mainRepo = _resolveMainRepoFromGitlink(current);
@@ -29456,15 +29628,15 @@ function _resolveCleoDir(cwd) {
29456
29628
  const project = _pathsResolveProjectByCwd(cwd);
29457
29629
  if (project !== null) {
29458
29630
  try {
29459
- return resolve4(getProjectRoot(cwd), cleoDir);
29631
+ return resolve5(getProjectRoot(cwd), cleoDir);
29460
29632
  } catch {
29461
- return resolve4(project.projectRoot, cleoDir);
29633
+ return resolve5(project.projectRoot, cleoDir);
29462
29634
  }
29463
29635
  }
29464
29636
  return getCleoDirAbsolute(cwd);
29465
29637
  }
29466
29638
  function _cwdHasGitAncestor(cwd) {
29467
- const start = resolve4(cwd ?? process.cwd());
29639
+ const start = resolve5(cwd ?? process.cwd());
29468
29640
  let current = start;
29469
29641
  while (true) {
29470
29642
  const gitMarker = join17(current, ".git");
@@ -29564,7 +29736,7 @@ function getProjectRoot(cwd) {
29564
29736
  }
29565
29737
  return cleoDirEnv;
29566
29738
  }
29567
- const start = resolve4(cwd ?? process.cwd());
29739
+ const start = resolve5(cwd ?? process.cwd());
29568
29740
  let current = start;
29569
29741
  const mainRepoFromStart = _resolveMainRepoFromGitlink(start);
29570
29742
  if (mainRepoFromStart !== null) return mainRepoFromStart;
@@ -29657,7 +29829,7 @@ async function registerProjectOnEncounter(projectRoot, infoProjectId) {
29657
29829
  const db = await getNexusDb2();
29658
29830
  const existingRows = await db.select().from(projectRegistry2).where(eq2(projectRegistry2.projectId, immutableId)).limit(1);
29659
29831
  const now = (/* @__PURE__ */ new Date()).toISOString();
29660
- const resolvedPath = resolve4(projectRoot);
29832
+ const resolvedPath = resolve5(projectRoot);
29661
29833
  const projectName = _readProjectNameFromInfo(resolvedPath) || basename4(projectRoot) || "unnamed";
29662
29834
  if (existingRows.length > 0) {
29663
29835
  const existingPath = existingRows[0].projectPath;
@@ -32935,6 +33107,76 @@ var init_credential_pool = __esm({
32935
33107
  }
32936
33108
  });
32937
33109
 
33110
+ // packages/core/src/llm/local-inference-probe.ts
33111
+ function extractModels(body) {
33112
+ if (body === null || typeof body !== "object") return [];
33113
+ const rec = body;
33114
+ if (Array.isArray(rec.models)) {
33115
+ return rec.models.map(
33116
+ (m) => m !== null && typeof m === "object" ? m.name ?? m.model : void 0
33117
+ ).filter((n) => typeof n === "string");
33118
+ }
33119
+ if (Array.isArray(rec.data)) {
33120
+ return rec.data.map((m) => m !== null && typeof m === "object" ? m.id : void 0).filter((n) => typeof n === "string");
33121
+ }
33122
+ return [];
33123
+ }
33124
+ async function detectLocalInference(opts = {}) {
33125
+ if (process.env["CLEO_DISABLE_LOCAL_INFERENCE"]?.trim()) return null;
33126
+ if (!opts.force && cached !== void 0) return cached;
33127
+ for (const endpoint of LOCAL_ENDPOINTS) {
33128
+ try {
33129
+ const response = await fetch(endpoint.tagsUrl, {
33130
+ signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
33131
+ });
33132
+ if (!response.ok) continue;
33133
+ const models = extractModels(await response.json());
33134
+ if (models.length === 0) continue;
33135
+ cached = {
33136
+ name: endpoint.name,
33137
+ baseUrl: endpoint.baseUrl,
33138
+ openAiBaseUrl: endpoint.openAiBaseUrl,
33139
+ models
33140
+ };
33141
+ return cached;
33142
+ } catch {
33143
+ }
33144
+ }
33145
+ cached = null;
33146
+ return cached;
33147
+ }
33148
+ async function listOllamaModels(baseUrl) {
33149
+ try {
33150
+ const url2 = `${baseUrl.replace(/\/+$/, "")}/api/tags`;
33151
+ const response = await fetch(url2, { signal: AbortSignal.timeout(PROBE_TIMEOUT_MS) });
33152
+ if (!response.ok) return [];
33153
+ return extractModels(await response.json());
33154
+ } catch {
33155
+ return [];
33156
+ }
33157
+ }
33158
+ var LOCAL_ENDPOINTS, PROBE_TIMEOUT_MS, cached;
33159
+ var init_local_inference_probe = __esm({
33160
+ "packages/core/src/llm/local-inference-probe.ts"() {
33161
+ "use strict";
33162
+ LOCAL_ENDPOINTS = [
33163
+ {
33164
+ name: "ollama",
33165
+ tagsUrl: "http://127.0.0.1:11434/api/tags",
33166
+ baseUrl: "http://127.0.0.1:11434",
33167
+ openAiBaseUrl: "http://127.0.0.1:11434/v1"
33168
+ },
33169
+ {
33170
+ name: "lm-studio",
33171
+ tagsUrl: "http://127.0.0.1:1234/v1/models",
33172
+ baseUrl: "http://127.0.0.1:1234",
33173
+ openAiBaseUrl: "http://127.0.0.1:1234/v1"
33174
+ }
33175
+ ];
33176
+ PROBE_TIMEOUT_MS = 300;
33177
+ }
33178
+ });
33179
+
32938
33180
  // packages/core/src/llm/catalog-cache.ts
32939
33181
  import {
32940
33182
  existsSync as existsSync27,
@@ -33058,9 +33300,9 @@ var init_catalog_model_resolver = __esm({
33058
33300
  // packages/core/src/llm/cross-provider-selector.ts
33059
33301
  import { totalmem as totalmem2 } from "node:os";
33060
33302
  async function probeOllamaAlive(baseUrl) {
33061
- const cached2 = _ollamaProbeCache.get(baseUrl);
33062
- if (cached2 && Date.now() - cached2.checkedAt < OLLAMA_PROBE_TTL_MS) {
33063
- return cached2.alive;
33303
+ const cached3 = _ollamaProbeCache.get(baseUrl);
33304
+ if (cached3 && Date.now() - cached3.checkedAt < OLLAMA_PROBE_TTL_MS) {
33305
+ return cached3.alive;
33064
33306
  }
33065
33307
  let alive = false;
33066
33308
  try {
@@ -33102,6 +33344,16 @@ function isProvisioned(provider) {
33102
33344
  const cred = resolveCredentials(provider);
33103
33345
  return (cred.apiKey?.trim().length ?? 0) > 0;
33104
33346
  }
33347
+ function reconcileOllamaModel(preferred, installed) {
33348
+ if (installed.length === 0) return preferred;
33349
+ if (installed.includes(preferred)) return preferred;
33350
+ const family = preferred.split(":")[0];
33351
+ if (family !== void 0 && family !== "") {
33352
+ const sameFamily = installed.find((m) => m.split(":")[0] === family);
33353
+ if (sameFamily !== void 0) return sameFamily;
33354
+ }
33355
+ return installed[0] ?? preferred;
33356
+ }
33105
33357
  function scoreProvider(provider, providerTier, taskTier, ollamaAlive, costInputPerMillion) {
33106
33358
  let score = TIER_BASE[providerTier];
33107
33359
  if (taskTier === "frontier" && providerTier === "frontier") {
@@ -33134,6 +33386,7 @@ function roleTierFor(role) {
33134
33386
  }
33135
33387
  async function selectBestProvisioned(role, opts) {
33136
33388
  const taskTier = roleTierFor(role);
33389
+ const excluded = new Set(opts.exclude ?? []);
33137
33390
  for (const id of BUILTIN_PROVIDER_IDS) {
33138
33391
  const creds = await listCredentials(id);
33139
33392
  const hasExpiredOAuth = creds.some(
@@ -33158,10 +33411,23 @@ async function selectBestProvisioned(role, opts) {
33158
33411
  }
33159
33412
  const provisionedIds = [];
33160
33413
  for (const id of BUILTIN_PROVIDER_IDS) {
33414
+ if (excluded.has(id)) continue;
33161
33415
  if (isProvisioned(id)) {
33162
33416
  provisionedIds.push(id);
33163
33417
  }
33164
33418
  }
33419
+ let localModels = [];
33420
+ if (!excluded.has("ollama") && !provisionedIds.includes("ollama")) {
33421
+ const local = await detectLocalInference();
33422
+ if (local !== null && local.name === "ollama") {
33423
+ provisionedIds.push("ollama");
33424
+ localModels = local.models;
33425
+ logger3.debug(
33426
+ { baseUrl: local.baseUrl, models: local.models },
33427
+ "cross-provider-selector: unlisted ollama daemon is live \u2014 admitting as provisioned"
33428
+ );
33429
+ }
33430
+ }
33165
33431
  if (provisionedIds.length === 0) {
33166
33432
  logger3.warn(
33167
33433
  {
@@ -33178,11 +33444,12 @@ async function selectBestProvisioned(role, opts) {
33178
33444
  const { resolveProviderDefaultModel: resolveProviderDefaultModel2, catalogKeyForProvider: catalogKeyForProvider2 } = await Promise.resolve().then(() => (init_catalog_model_resolver(), catalog_model_resolver_exports));
33179
33445
  const { pickCredentialForProvider: pickCredentialForProvider2 } = await Promise.resolve().then(() => (init_credentials_store(), credentials_store_exports));
33180
33446
  const ollamaProvisioned = provisionedIds.includes("ollama");
33181
- let ollamaAlive = false;
33182
- if (ollamaProvisioned) {
33447
+ let ollamaAlive = localModels.length > 0;
33448
+ if (ollamaProvisioned && !ollamaAlive) {
33183
33449
  const profile = await getProviderProfile2("ollama");
33184
33450
  const ollamaBase = profile?.baseUrl ?? "http://localhost:11434";
33185
33451
  ollamaAlive = await probeOllamaAlive(ollamaBase);
33452
+ if (ollamaAlive) localModels = await listOllamaModels(ollamaBase);
33186
33453
  }
33187
33454
  const scored = [];
33188
33455
  for (const id of provisionedIds) {
@@ -33212,6 +33479,7 @@ async function selectBestProvisioned(role, opts) {
33212
33479
  } else {
33213
33480
  model = ollamaDefaultModelForTier(winner.tier, ramBytes);
33214
33481
  }
33482
+ model = reconcileOllamaModel(model, localModels);
33215
33483
  const catalogKey = catalogKeyForProvider2(winner.id);
33216
33484
  const catalogModel = resolveProviderDefaultModel2(catalogKey);
33217
33485
  if (!catalogModel?.startsWith("gemma4")) {
@@ -33255,6 +33523,7 @@ var init_cross_provider_selector = __esm({
33255
33523
  init_credential_pool();
33256
33524
  init_credentials2();
33257
33525
  init_credentials_store();
33526
+ init_local_inference_probe();
33258
33527
  logger3 = getLogger("llm-cross-provider-selector");
33259
33528
  BUILTIN_PROVIDER_IDS = [
33260
33529
  "anthropic",
@@ -33466,6 +33735,16 @@ async function selectProviderModel(llm, role, systemKey, profileOverride, projec
33466
33735
  source: "implicit-fallback"
33467
33736
  };
33468
33737
  }
33738
+ async function applyProviderExclusions(selected, role, projectRoot, exclude) {
33739
+ if (exclude === void 0 || exclude.length === 0) return selected;
33740
+ if (!exclude.includes(selected.provider)) return selected;
33741
+ try {
33742
+ const substitute = await selectBestProvisioned(role, { projectRoot, exclude });
33743
+ if (substitute !== null) return substitute;
33744
+ } catch {
33745
+ }
33746
+ return selected;
33747
+ }
33469
33748
  async function resolveCredentialForRole(provider, credentialLabel, projectRoot) {
33470
33749
  try {
33471
33750
  await new CredentialPool(provider).refreshExpiredOAuth();
@@ -33480,7 +33759,9 @@ async function resolveCredentialForRole(provider, credentialLabel, projectRoot)
33480
33759
  provider,
33481
33760
  apiKey: stored.accessToken,
33482
33761
  source: "cred-file",
33483
- authType: wireAuthType
33762
+ authType: wireAuthType,
33763
+ // T12081: preserve the stored endpoint (Ollama/LM Studio/vLLM/…).
33764
+ baseUrl: stored.baseUrl ?? null
33484
33765
  },
33485
33766
  usedLabel: stored.label
33486
33767
  };
@@ -33496,7 +33777,9 @@ async function resolveCredentialForRole(provider, credentialLabel, projectRoot)
33496
33777
  provider,
33497
33778
  apiKey: picked.accessToken,
33498
33779
  source: "cred-file",
33499
- authType: wireAuthType
33780
+ authType: wireAuthType,
33781
+ // T12081: preserve the stored endpoint (Ollama/LM Studio/vLLM/…).
33782
+ baseUrl: picked.baseUrl ?? null
33500
33783
  },
33501
33784
  usedLabel: picked.label
33502
33785
  };
@@ -33506,6 +33789,23 @@ async function resolveCredentialForRole(provider, credentialLabel, projectRoot)
33506
33789
  if (cred.apiKey) {
33507
33790
  return { credential: cred, usedLabel: void 0 };
33508
33791
  }
33792
+ if (provider === "ollama") {
33793
+ const local = await detectLocalInference();
33794
+ if (local !== null && local.name === "ollama") {
33795
+ return {
33796
+ credential: {
33797
+ provider,
33798
+ apiKey: LOCAL_PLACEHOLDER_TOKEN,
33799
+ source: "local-daemon",
33800
+ authType: "api_key",
33801
+ // ROOT url, not the `/v1` form: `deriveApiWire('ollama')` selects the
33802
+ // NATIVE transport, which appends `/api/chat` itself.
33803
+ baseUrl: local.baseUrl
33804
+ },
33805
+ usedLabel: void 0
33806
+ };
33807
+ }
33808
+ }
33509
33809
  return { credential: null, usedLabel: void 0 };
33510
33810
  }
33511
33811
  async function resolveLLMForRole(role, opts) {
@@ -33518,13 +33818,19 @@ async function resolveLLMForRole(role, opts) {
33518
33818
  config2 = void 0;
33519
33819
  }
33520
33820
  const llmBlock = readLlmBlock(config2);
33521
- const { provider, model, credentialLabel, source } = await selectProviderModel(
33821
+ const selected = await selectProviderModel(
33522
33822
  llmBlock,
33523
33823
  role,
33524
33824
  opts?.systemKey,
33525
33825
  opts?.profileOverride,
33526
33826
  projectRoot
33527
33827
  );
33828
+ const { provider, model, credentialLabel, source } = await applyProviderExclusions(
33829
+ selected,
33830
+ role,
33831
+ projectRoot,
33832
+ opts?.excludeProviders
33833
+ );
33528
33834
  const { credential, usedLabel } = await resolveCredentialForRole(
33529
33835
  provider,
33530
33836
  credentialLabel,
@@ -33550,7 +33856,12 @@ async function resolveLLMForRole(role, opts) {
33550
33856
  credentialMetadata = {
33551
33857
  provider: credential.provider,
33552
33858
  source: credential.source,
33553
- authType: wireAuthType
33859
+ authType: wireAuthType,
33860
+ // T12081: carry the credential's OWN endpoint. Without it a consumer
33861
+ // building a transport cannot tell that this credential targets a local
33862
+ // or proxied host, and falls back to the provider's public API — which
33863
+ // rejected every Ollama / LM Studio / vLLM / OpenRouter credential 401.
33864
+ baseUrl: credential.baseUrl ?? null
33554
33865
  };
33555
33866
  sealedCredential = makeSealedCredential({
33556
33867
  provider: credential.provider,
@@ -33578,7 +33889,7 @@ async function resolveLLMForRole(role, opts) {
33578
33889
  authType
33579
33890
  };
33580
33891
  }
33581
- var IMPLICIT_FALLBACK_PROVIDER;
33892
+ var IMPLICIT_FALLBACK_PROVIDER, LOCAL_PLACEHOLDER_TOKEN;
33582
33893
  var init_role_resolver = __esm({
33583
33894
  "packages/core/src/llm/role-resolver.ts"() {
33584
33895
  "use strict";
@@ -33589,10 +33900,12 @@ var init_role_resolver = __esm({
33589
33900
  init_credentials_store();
33590
33901
  init_cross_provider_selector();
33591
33902
  init_fallback_model();
33903
+ init_local_inference_probe();
33592
33904
  init_sealed_credential();
33593
33905
  init_system_of_use_registry();
33594
33906
  init_anthropic_client_factory();
33595
33907
  IMPLICIT_FALLBACK_PROVIDER = "anthropic";
33908
+ LOCAL_PLACEHOLDER_TOKEN = "local";
33596
33909
  }
33597
33910
  });
33598
33911
 
@@ -33847,7 +34160,9 @@ async function resolveLLMForSystem(system, opts) {
33847
34160
  systemKey,
33848
34161
  // T11759: pin a named profile (e.g. a `.cantbook` stage's `profile:`) as
33849
34162
  // the highest-priority resolution tier. Absent/incomplete → falls through.
33850
- ...opts?.profile !== void 0 ? { profileOverride: opts.profile } : {}
34163
+ ...opts?.profile !== void 0 ? { profileOverride: opts.profile } : {},
34164
+ // T12084: carry exclusions through to the provisioning-aware tier.
34165
+ ...opts?.excludeProviders !== void 0 ? { excludeProviders: opts.excludeProviders } : {}
33851
34166
  });
33852
34167
  } catch (err) {
33853
34168
  logger6.warn(
@@ -34158,7 +34473,7 @@ function storedToResolved(stored) {
34158
34473
  };
34159
34474
  }
34160
34475
  function sleep2(ms) {
34161
- return new Promise((resolve6) => setTimeout(resolve6, ms));
34476
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
34162
34477
  }
34163
34478
  function backoffMs(policy, attempt) {
34164
34479
  const base = policy.baseDelayMs * 2 ** attempt;
@@ -36700,9 +37015,9 @@ var init_chat_completions = __esm({
36700
37015
  outputTokens: response.usage?.completion_tokens ?? 0
36701
37016
  };
36702
37017
  const promptDetails = response.usage?.["prompt_tokens_details"];
36703
- const cached2 = promptDetails?.["cached_tokens"];
36704
- if (typeof cached2 === "number" && cached2 > 0) {
36705
- usage.cachedTokens = cached2;
37018
+ const cached3 = promptDetails?.["cached_tokens"];
37019
+ if (typeof cached3 === "number" && cached3 > 0) {
37020
+ usage.cachedTokens = cached3;
36706
37021
  }
36707
37022
  return {
36708
37023
  id: response.id ?? `chat-${Date.now().toString(36)}`,
@@ -36944,9 +37259,9 @@ function normalizeUsage(usage) {
36944
37259
  const outputTokens = usage["output_tokens"] ?? 0;
36945
37260
  const normalized = { inputTokens, outputTokens };
36946
37261
  const details = usage["input_tokens_details"];
36947
- const cached2 = details?.["cached_tokens"];
36948
- if (typeof cached2 === "number" && cached2 > 0) {
36949
- normalized.cachedTokens = cached2;
37262
+ const cached3 = details?.["cached_tokens"];
37263
+ if (typeof cached3 === "number" && cached3 > 0) {
37264
+ normalized.cachedTokens = cached3;
36950
37265
  }
36951
37266
  return normalized;
36952
37267
  }
@@ -37980,7 +38295,7 @@ function normalizeOllamaToolCall(tc) {
37980
38295
  };
37981
38296
  }
37982
38297
  function sleep3(ms) {
37983
- return new Promise((resolve6) => setTimeout(resolve6, ms));
38298
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
37984
38299
  }
37985
38300
  var OLLAMA_DEFAULT_BASE_URL, MAX_RETRIES, INITIAL_BACKOFF_MS, RETRYABLE_STATUS_CODES, OllamaTransport;
37986
38301
  var init_ollama2 = __esm({
@@ -38668,7 +38983,7 @@ __export(util_exports, {
38668
38983
  assignProp: () => assignProp,
38669
38984
  base64ToUint8Array: () => base64ToUint8Array,
38670
38985
  base64urlToUint8Array: () => base64urlToUint8Array,
38671
- cached: () => cached,
38986
+ cached: () => cached2,
38672
38987
  captureStackTrace: () => captureStackTrace,
38673
38988
  cleanEnum: () => cleanEnum,
38674
38989
  cleanRegex: () => cleanRegex,
@@ -38744,7 +39059,7 @@ function jsonStringifyReplacer(_, value) {
38744
39059
  return value.toString();
38745
39060
  return value;
38746
39061
  }
38747
- function cached(getter) {
39062
+ function cached2(getter) {
38748
39063
  const set2 = false;
38749
39064
  return {
38750
39065
  get value() {
@@ -39260,7 +39575,7 @@ var init_util = __esm({
39260
39575
  EVALUATING = /* @__PURE__ */ Symbol("evaluating");
39261
39576
  captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {
39262
39577
  };
39263
- allowsEval = cached(() => {
39578
+ allowsEval = cached2(() => {
39264
39579
  if (typeof navigator !== "undefined" && navigator?.userAgent?.includes("Cloudflare")) {
39265
39580
  return false;
39266
39581
  }
@@ -41327,7 +41642,7 @@ var init_schemas = __esm({
41327
41642
  }
41328
41643
  });
41329
41644
  }
41330
- const _normalized = cached(() => normalizeDef(def2));
41645
+ const _normalized = cached2(() => normalizeDef(def2));
41331
41646
  defineLazy(inst._zod, "propValues", () => {
41332
41647
  const shape = def2.shape;
41333
41648
  const propValues = {};
@@ -41378,7 +41693,7 @@ var init_schemas = __esm({
41378
41693
  $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def2) => {
41379
41694
  $ZodObject.init(inst, def2);
41380
41695
  const superParse = inst._zod.parse;
41381
- const _normalized = cached(() => normalizeDef(def2));
41696
+ const _normalized = cached2(() => normalizeDef(def2));
41382
41697
  const generateFastpass = (shape) => {
41383
41698
  const doc = new Doc(["shape", "payload", "ctx"]);
41384
41699
  const normalized = _normalized.value;
@@ -41570,7 +41885,7 @@ var init_schemas = __esm({
41570
41885
  }
41571
41886
  return propValues;
41572
41887
  });
41573
- const disc = cached(() => {
41888
+ const disc = cached2(() => {
41574
41889
  const opts = def2.options;
41575
41890
  const map2 = /* @__PURE__ */ new Map();
41576
41891
  for (const o of opts) {
@@ -58494,7 +58809,7 @@ function createProviderToolFactoryWithOutputSchema({
58494
58809
  supportsDeferredResults
58495
58810
  });
58496
58811
  }
58497
- async function resolve5(value) {
58812
+ async function resolve6(value) {
58498
58813
  if (typeof value === "function") {
58499
58814
  value = value();
58500
58815
  }
@@ -62528,14 +62843,14 @@ var init_dist4 = __esm({
62528
62843
  headers
62529
62844
  }) {
62530
62845
  return combineHeaders(
62531
- await resolve5(this.config.headers),
62846
+ await resolve6(this.config.headers),
62532
62847
  headers,
62533
62848
  betas.size > 0 ? { "anthropic-beta": Array.from(betas).join(",") } : {}
62534
62849
  );
62535
62850
  }
62536
62851
  async getBetasFromHeaders(requestHeaders) {
62537
62852
  var _a17, _b16;
62538
- const configHeaders = await resolve5(this.config.headers);
62853
+ const configHeaders = await resolve6(this.config.headers);
62539
62854
  const configBetaHeader = (_a17 = configHeaders["anthropic-beta"]) != null ? _a17 : "";
62540
62855
  const requestBetaHeader = (_b16 = requestHeaders == null ? void 0 : requestHeaders["anthropic-beta"]) != null ? _b16 : "";
62541
62856
  return new Set(
@@ -66120,8 +66435,8 @@ var init_model_runner = __esm({
66120
66435
  });
66121
66436
 
66122
66437
  // packages/core/src/selfimprove/fix-gen.ts
66123
- import { writeFileSync as writeFileSync11 } from "node:fs";
66124
- import { resolve as resolvePath2 } from "node:path";
66438
+ import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
66439
+ import { dirname as dirname13, join as join34, resolve as resolvePath2 } from "node:path";
66125
66440
  import { cwd as processCwd } from "node:process";
66126
66441
 
66127
66442
  // packages/utils/src/redact.ts
@@ -66383,7 +66698,7 @@ var FIXGEN_SYSTEM = "task-executor";
66383
66698
  var UNIFIED_DIFF_MARKERS = ["diff --git ", "--- ", "+++ ", "@@ "];
66384
66699
  function fixPatchPath(scenario, cwd) {
66385
66700
  const safeScenario = scenario.replace(/[^a-z0-9-]/gi, "-");
66386
- return resolvePath2(cwd ?? processCwd(), `selfimprove-${safeScenario}.patch`);
66701
+ return resolvePath2(cwd ?? processCwd(), join34(".cleo", "selfimprove", `${safeScenario}.patch`));
66387
66702
  }
66388
66703
  function looksLikeUnifiedDiff(text2) {
66389
66704
  if (text2.trim().length === 0) return false;
@@ -66468,6 +66783,7 @@ async function generateFixPatch(opts) {
66468
66783
  }
66469
66784
  const diff = output.diff.endsWith("\n") ? output.diff : `${output.diff}
66470
66785
  `;
66786
+ mkdirSync12(dirname13(patchPath), { recursive: true });
66471
66787
  writeFileSync11(patchPath, diff, "utf8");
66472
66788
  const bytes = Buffer.byteLength(diff, "utf8");
66473
66789
  logger8.info(
@@ -66476,6 +66792,7 @@ async function generateFixPatch(opts) {
66476
66792
  );
66477
66793
  return { kind: "written", patchPath, bytes, model: output.model };
66478
66794
  }
66795
+ var MAX_FIXGEN_FAILOVERS = 2;
66479
66796
  function createLlmFixGenerator(opts = {}) {
66480
66797
  return {
66481
66798
  async propose(request) {
@@ -66483,49 +66800,68 @@ function createLlmFixGenerator(opts = {}) {
66483
66800
  const { resolveLLMForSystem: resolveLLMForSystem2 } = await Promise.resolve().then(() => (init_system_resolver2(), system_resolver_exports));
66484
66801
  const { ModelRunner: ModelRunner2 } = await Promise.resolve().then(() => (init_model_runner(), model_runner_exports));
66485
66802
  const projectRoot = opts.projectRoot ?? request.repoContext.projectRoot;
66486
- const resolved = await resolveLLMForSystem2(FIXGEN_SYSTEM, { projectRoot });
66487
- if (!resolved.sealedCredential && resolved.authType !== "aws_sdk") {
66488
- return { kind: "none", reason: "no-credential-resolved" };
66489
- }
66490
- const apiKey = resolved.sealedCredential ? (await resolved.sealedCredential.fetch()).value : null;
66491
- const built = await ModelRunner2.build({
66492
- provider: resolved.provider,
66493
- model: resolved.model,
66494
- credential: resolved.credential ? {
66495
- provider: resolved.credential.provider,
66496
- apiKey,
66497
- source: resolved.credential.source,
66498
- authType: resolved.credential.authType
66499
- } : null,
66500
- source: resolved.source,
66501
- ...resolved.credentialLabel !== void 0 ? { credentialLabel: resolved.credentialLabel } : {},
66502
- apiMode: resolved.apiMode,
66503
- baseUrl: resolved.baseUrl,
66504
- authType: resolved.authType,
66505
- ...resolved.capabilities !== void 0 ? { capabilities: resolved.capabilities } : {}
66506
- });
66507
- const { system, user } = buildFixGenPrompt(request);
66508
- try {
66509
- const response = await built.session.send([{ role: "user", content: user }], {
66510
- systemSuffix: system
66803
+ const excludeProviders = [];
66804
+ for (let attempt = 0; attempt <= MAX_FIXGEN_FAILOVERS; attempt++) {
66805
+ const resolved = await resolveLLMForSystem2(FIXGEN_SYSTEM, {
66806
+ projectRoot,
66807
+ excludeProviders: [...excludeProviders]
66511
66808
  });
66512
- const text2 = (response.content ?? "").trim();
66513
- if (text2.length === 0 || text2 === "NO_PATCH") {
66514
- const rawReply = text2.length > 0 ? truncateReply(text2) : void 0;
66515
- return {
66516
- kind: "none",
66517
- reason: "model-declined",
66518
- ...rawReply !== void 0 ? { rawReply } : {}
66519
- };
66809
+ if (!resolved.sealedCredential && resolved.authType !== "aws_sdk") {
66810
+ return { kind: "none", reason: "no-credential-resolved" };
66811
+ }
66812
+ if (excludeProviders.includes(resolved.provider)) {
66813
+ return { kind: "none", reason: "llm-call-failed" };
66814
+ }
66815
+ const apiKey = resolved.sealedCredential ? (await resolved.sealedCredential.fetch()).value : null;
66816
+ const built = await ModelRunner2.build({
66817
+ provider: resolved.provider,
66818
+ model: resolved.model,
66819
+ credential: resolved.credential ? {
66820
+ provider: resolved.credential.provider,
66821
+ apiKey,
66822
+ source: resolved.credential.source,
66823
+ authType: resolved.credential.authType
66824
+ } : null,
66825
+ source: resolved.source,
66826
+ ...resolved.credentialLabel !== void 0 ? { credentialLabel: resolved.credentialLabel } : {},
66827
+ apiMode: resolved.apiMode,
66828
+ baseUrl: resolved.baseUrl,
66829
+ authType: resolved.authType,
66830
+ ...resolved.capabilities !== void 0 ? { capabilities: resolved.capabilities } : {}
66831
+ });
66832
+ const { system, user } = buildFixGenPrompt(request);
66833
+ try {
66834
+ const response = await built.session.send([{ role: "user", content: user }], {
66835
+ systemSuffix: system
66836
+ });
66837
+ const text2 = (response.content ?? "").trim();
66838
+ if (text2.length === 0 || text2 === "NO_PATCH") {
66839
+ const rawReply = text2.length > 0 ? truncateReply(text2) : void 0;
66840
+ return {
66841
+ kind: "none",
66842
+ reason: "model-declined",
66843
+ ...rawReply !== void 0 ? { rawReply } : {}
66844
+ };
66845
+ }
66846
+ return { kind: "patch", diff: stripCodeFences(text2), model: response.model };
66847
+ } catch (err) {
66848
+ logger8.warn(
66849
+ {
66850
+ system: FIXGEN_SYSTEM,
66851
+ provider: resolved.provider,
66852
+ model: resolved.model,
66853
+ attempt: attempt + 1,
66854
+ err: err instanceof Error ? err.message : String(err)
66855
+ },
66856
+ attempt < MAX_FIXGEN_FAILOVERS ? "fix-gen LLM call failed \u2014 failing over to another provider" : "fix-gen LLM call failed \u2014 degrading to no-patch"
66857
+ );
66858
+ if (attempt >= MAX_FIXGEN_FAILOVERS) {
66859
+ return { kind: "none", reason: "llm-call-failed" };
66860
+ }
66861
+ excludeProviders.push(resolved.provider);
66520
66862
  }
66521
- return { kind: "patch", diff: stripCodeFences(text2), model: response.model };
66522
- } catch (err) {
66523
- logger8.warn(
66524
- { system: FIXGEN_SYSTEM, err: err instanceof Error ? err.message : String(err) },
66525
- "fix-gen LLM call failed \u2014 degrading to no-patch"
66526
- );
66527
- return { kind: "none", reason: "llm-call-failed" };
66528
66863
  }
66864
+ return { kind: "none", reason: "llm-call-failed" };
66529
66865
  }
66530
66866
  };
66531
66867
  }