@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
@@ -10043,6 +10043,27 @@ var init_operations_registry = __esm({
10043
10043
  type: "boolean",
10044
10044
  required: false,
10045
10045
  description: "Commit plan file before dispatching"
10046
+ },
10047
+ // T12089: the plan SCOPE. The workflow regenerates the plan when no
10048
+ // committed plan is supplied, and `cleo release plan` requires
10049
+ // `--saga | --epic | --tasks` — so without one of these the dispatched
10050
+ // run dies at "Prepare bump-PR" after a fully green preflight.
10051
+ //
10052
+ // A param absent from this registry is STRIPPED before the domain handler
10053
+ // sees it, silently. `--tasks` was accepted by the CLI, forwarded by the
10054
+ // handler and by `releaseOpen`, and still arrived empty at the workflow
10055
+ // because this declaration was the fourth hop in the chain.
10056
+ {
10057
+ name: "epic",
10058
+ type: "string",
10059
+ required: false,
10060
+ description: "Epic task ID forwarded as the plan scope (e.g. T9999)"
10061
+ },
10062
+ {
10063
+ name: "tasks",
10064
+ type: "string",
10065
+ required: false,
10066
+ description: "Comma-separated task IDs forwarded as the plan scope for a task-scoped release"
10046
10067
  }
10047
10068
  ]
10048
10069
  },
@@ -15722,6 +15743,25 @@ var init_service_provider = __esm({
15722
15743
  }
15723
15744
  });
15724
15745
 
15746
+ // packages/contracts/src/caamp-markers.ts
15747
+ var H, damagedMarkerSource, CAAMP_DAMAGED_START_PATTERN_SOURCE, CAAMP_DAMAGED_END_PATTERN_SOURCE;
15748
+ var init_caamp_markers = __esm({
15749
+ "packages/contracts/src/caamp-markers.ts"() {
15750
+ "use strict";
15751
+ H = "[ \\t\\r]";
15752
+ damagedMarkerSource = (keyword) => `^${H}*[<!-]{1,4}${H}*CAAMP${H}*:${H}*${keyword}${H}*[->]{1,3}${H}*$`;
15753
+ CAAMP_DAMAGED_START_PATTERN_SOURCE = damagedMarkerSource("START");
15754
+ CAAMP_DAMAGED_END_PATTERN_SOURCE = damagedMarkerSource("END");
15755
+ }
15756
+ });
15757
+
15758
+ // packages/contracts/src/collection-keys.ts
15759
+ var init_collection_keys = __esm({
15760
+ "packages/contracts/src/collection-keys.ts"() {
15761
+ "use strict";
15762
+ }
15763
+ });
15764
+
15725
15765
  // packages/contracts/src/index.ts
15726
15766
  var init_src = __esm({
15727
15767
  "packages/contracts/src/index.ts"() {
@@ -15789,6 +15829,8 @@ var init_src = __esm({
15789
15829
  init_validator();
15790
15830
  init_service_provider();
15791
15831
  init_workgraph();
15832
+ init_caamp_markers();
15833
+ init_collection_keys();
15792
15834
  }
15793
15835
  });
15794
15836
 
@@ -23511,7 +23553,7 @@ function resolveDbIdentity(db) {
23511
23553
  return identity;
23512
23554
  }
23513
23555
  function sleepAsync(ms) {
23514
- return new Promise((resolve6) => setTimeout(resolve6, Math.max(0, Math.round(ms))));
23556
+ return new Promise((resolve7) => setTimeout(resolve7, Math.max(0, Math.round(ms))));
23515
23557
  }
23516
23558
  function isPidAlive(pid) {
23517
23559
  try {
@@ -24329,7 +24371,7 @@ async function sendResourceRelease(socketPath, cls, holderId) {
24329
24371
  return { unavailable: true, reason: `unexpected response kind: ${result.kind}` };
24330
24372
  }
24331
24373
  function sendLeaseRequest(socketPath, request, expectedKind) {
24332
- return new Promise((resolve6) => {
24374
+ return new Promise((resolve7) => {
24333
24375
  const id = `ra-${process.pid}-${request.kind}`;
24334
24376
  const envelope = LeaseIpcRequestEnvelopeSchema.parse({
24335
24377
  protocol_version: LEASE_IPC_PROTOCOL_VERSION,
@@ -24347,7 +24389,7 @@ function sendLeaseRequest(socketPath, request, expectedKind) {
24347
24389
  settled = true;
24348
24390
  socket.removeAllListeners();
24349
24391
  socket.destroy();
24350
- resolve6(value);
24392
+ resolve7(value);
24351
24393
  };
24352
24394
  const degrade = (reason) => done({ unavailable: true, reason });
24353
24395
  socket.setTimeout(REQUEST_TIMEOUT_MS);
@@ -24470,7 +24512,9 @@ function computeClassBudget(cls, sample, opts = {}) {
24470
24512
  return Math.max(1, cpus - 2);
24471
24513
  case "test-run":
24472
24514
  case "scoped-build": {
24473
- const base = Math.max(1, Math.floor(cpus / 4));
24515
+ const estRamBytes = (opts.testRunEstRamMb ?? 24576) * MB;
24516
+ const byMem = Math.floor((availBytes - headroomBytes) / estRamBytes);
24517
+ const base = clamp(1, byMem, Math.max(1, Math.floor(cpus / 4)));
24474
24518
  if (some > floor) return 1;
24475
24519
  if (some > hold) return Math.max(1, Math.floor(base / 2));
24476
24520
  return base;
@@ -24963,6 +25007,11 @@ var init_registry = __esm({
24963
25007
  * });
24964
25008
  * ```
24965
25009
  */
25010
+ // T12071: keyed on the EVENT so the payload shape is checked against
25011
+ // `HookEventPayloadMap`. The previous `<T extends HookPayload>` form inferred
25012
+ // T from the argument, relating the event and the payload not at all — which
25013
+ // is how `PostToolUse` came to be dispatched with `newStatus` instead of
25014
+ // `status` and filled 29% of BRAIN with "status: undefined".
24966
25015
  async dispatch(event, projectRoot, payload) {
24967
25016
  if (!this.config.enabled) return;
24968
25017
  const resolvedEvent = this.resolveEvent(event);
@@ -27772,8 +27821,8 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
27772
27821
  }
27773
27822
  let initResolve = null;
27774
27823
  let initReject = null;
27775
- const initPromise = new Promise((resolve6, reject) => {
27776
- initResolve = resolve6;
27824
+ const initPromise = new Promise((resolve7, reject) => {
27825
+ initResolve = resolve7;
27777
27826
  initReject = reject;
27778
27827
  });
27779
27828
  _cache.set(key, {
@@ -28026,24 +28075,35 @@ var init_dual_scope_db = __esm({
28026
28075
  async openProject(dbPath, options) {
28027
28076
  const normalized = resolve3(dbPath);
28028
28077
  if (options?.dedicated) {
28029
- const handle = await openDualScopeDbAtPath("project", normalized, void 0, {
28078
+ const handle = await openDualScopeDbAtPath("project", normalized, options?.exodusCwd, {
28030
28079
  dedicated: true
28031
28080
  });
28032
28081
  return this.buildStore("project", handle, 0);
28033
28082
  }
28034
- return this.openEntry("project", normalized);
28083
+ return this.openEntry("project", normalized, 0, options?.exodusCwd);
28035
28084
  }
28036
28085
  /** @inheritdoc */
28037
28086
  async openGlobal(options) {
28038
28087
  const dbPath = resolveDualScopeDbPath("global");
28039
28088
  const normalized = resolve3(dbPath);
28040
28089
  if (options?.dedicated) {
28041
- const handle = await openDualScopeDbAtPath("global", normalized, void 0, {
28090
+ const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
28091
+ dedicated: true
28092
+ });
28093
+ return this.buildStore("global", handle, 0);
28094
+ }
28095
+ return this.openEntry("global", normalized, 0, options?.exodusCwd);
28096
+ }
28097
+ /** @inheritdoc */
28098
+ async openGlobalAt(dbPath, options) {
28099
+ const normalized = resolve3(dbPath);
28100
+ if (options?.dedicated) {
28101
+ const handle = await openDualScopeDbAtPath("global", normalized, options?.exodusCwd, {
28042
28102
  dedicated: true
28043
28103
  });
28044
28104
  return this.buildStore("global", handle, 0);
28045
28105
  }
28046
- return this.openEntry("global", normalized);
28106
+ return this.openEntry("global", normalized, 0, options?.exodusCwd);
28047
28107
  }
28048
28108
  /** @inheritdoc */
28049
28109
  closeProject(dbPath) {
@@ -28069,7 +28129,7 @@ var init_dual_scope_db = __esm({
28069
28129
  * retry calls this with `depth + 1`. A second dead handle at depth 1
28070
28130
  * throws {@link LivenessExhaustedError} instead of recursing further.
28071
28131
  */
28072
- async openEntry(scope, dbPath, depth = 0) {
28132
+ async openEntry(scope, dbPath, depth = 0, exodusCwd) {
28073
28133
  const key = cacheKey(scope, dbPath);
28074
28134
  const existing = this._registry.get(key);
28075
28135
  if (existing) {
@@ -28084,8 +28144,8 @@ var init_dual_scope_db = __esm({
28084
28144
  const entryId = ++this._nextId;
28085
28145
  let initResolve;
28086
28146
  let initReject;
28087
- const initPromise = new Promise((resolve6, reject) => {
28088
- initResolve = resolve6;
28147
+ const initPromise = new Promise((resolve7, reject) => {
28148
+ initResolve = resolve7;
28089
28149
  initReject = reject;
28090
28150
  });
28091
28151
  this._registry.set(key, { id: entryId, store: null, initPromise });
@@ -28096,7 +28156,7 @@ var init_dual_scope_db = __esm({
28096
28156
  }
28097
28157
  });
28098
28158
  try {
28099
- const dualHandle = scope === "project" ? await this.openDualScopeFn("project", dbPath) : await this.openDualScopeFn("global", dbPath);
28159
+ const dualHandle = scope === "project" ? await this.openDualScopeFn("project", dbPath, exodusCwd) : await this.openDualScopeFn("global", dbPath, exodusCwd);
28100
28160
  const current = this._registry.get(key);
28101
28161
  if (!current || current.id !== entryId) {
28102
28162
  throw new EntryCancelledError(scope, dbPath);
@@ -28107,7 +28167,7 @@ var init_dual_scope_db = __esm({
28107
28167
  if (depth >= 1) {
28108
28168
  throw new LivenessExhaustedError(scope, dbPath);
28109
28169
  }
28110
- const retryStore = await this.openEntry(scope, dbPath, depth + 1);
28170
+ const retryStore = await this.openEntry(scope, dbPath, depth + 1, exodusCwd);
28111
28171
  initResolve(retryStore);
28112
28172
  return retryStore;
28113
28173
  }
@@ -28203,6 +28263,151 @@ var init_dual_scope_db = __esm({
28203
28263
  }
28204
28264
  });
28205
28265
 
28266
+ // packages/core/src/store/ports/domain-binding.ts
28267
+ import { resolve as resolve4 } from "node:path";
28268
+ function getCleoRuntime() {
28269
+ if (!_runtime) {
28270
+ _runtime = createCleoRuntime();
28271
+ }
28272
+ return _runtime;
28273
+ }
28274
+ function bindingKey(scope, dbPath, domain2) {
28275
+ return `${scope}::${dbPath}::${domain2}`;
28276
+ }
28277
+ function nativeOf(store) {
28278
+ const native = store.db.$client;
28279
+ if (!native) {
28280
+ throw new Error(
28281
+ `T12037: CleoRuntime store for ${store.scope}::${store.dbPath} exposed no $client \u2014 cannot bind a domain schema to it.`
28282
+ );
28283
+ }
28284
+ return native;
28285
+ }
28286
+ function reuseValid(key, store) {
28287
+ const row = _bindings.get(key);
28288
+ if (!row) return void 0;
28289
+ if (row.store !== store || !store.isOpen || !row.native.isOpen) {
28290
+ _bindings.delete(key);
28291
+ return void 0;
28292
+ }
28293
+ return row;
28294
+ }
28295
+ async function bindAgainst(key, store, establish) {
28296
+ const cached3 = reuseValid(key, store);
28297
+ if (cached3) return cached3;
28298
+ const pending = _inflight.get(key);
28299
+ if (pending) {
28300
+ const row = await pending;
28301
+ if (row.store === store && row.native.isOpen) return row;
28302
+ return bindAgainst(key, store, establish);
28303
+ }
28304
+ const native = nativeOf(store);
28305
+ const flight = (async () => {
28306
+ const db = await establish(native, store);
28307
+ const row = { store, native, db };
28308
+ if (store.isOpen && native.isOpen) {
28309
+ _bindings.set(key, row);
28310
+ }
28311
+ return row;
28312
+ })();
28313
+ _inflight.set(key, flight);
28314
+ try {
28315
+ return await flight;
28316
+ } finally {
28317
+ if (_inflight.get(key) === flight) {
28318
+ _inflight.delete(key);
28319
+ }
28320
+ }
28321
+ }
28322
+ async function bindLive(scope, key, dbPath, openStore, establish) {
28323
+ let lastError;
28324
+ for (let attempt = 0; attempt < MAX_LIVENESS_ATTEMPTS; attempt += 1) {
28325
+ let store;
28326
+ try {
28327
+ store = await openStore();
28328
+ } catch (err) {
28329
+ lastError = err;
28330
+ releaseDomainBindings({ scope, dbPath });
28331
+ if (attempt + 1 >= MAX_LIVENESS_ATTEMPTS) throw err;
28332
+ continue;
28333
+ }
28334
+ try {
28335
+ const row = await bindAgainst(key, store, establish);
28336
+ if (row.store.isOpen && row.native.isOpen) return row;
28337
+ } catch (err) {
28338
+ lastError = err;
28339
+ if (store.isOpen) throw err;
28340
+ }
28341
+ releaseDomainBindings({ scope, dbPath });
28342
+ try {
28343
+ store.close();
28344
+ } catch {
28345
+ }
28346
+ }
28347
+ if (lastError !== void 0) throw lastError;
28348
+ throw new Error(
28349
+ `T12037: could not bind ${key} over a live connection after ${MAX_LIVENESS_ATTEMPTS} attempts \u2014 the consolidated handle was closed each time.`
28350
+ );
28351
+ }
28352
+ async function bindProjectDomain(domain2, cwd, establish) {
28353
+ const dbPath = resolve4(resolveDualScopeDbPath("project", cwd));
28354
+ const row = await bindLive(
28355
+ "project",
28356
+ bindingKey("project", dbPath, domain2),
28357
+ dbPath,
28358
+ () => getCleoRuntime().openProject(dbPath, { exodusCwd: cwd }),
28359
+ establish
28360
+ );
28361
+ return row;
28362
+ }
28363
+ function releaseDomainBindings(filter2) {
28364
+ if (!filter2) {
28365
+ _bindings.clear();
28366
+ return;
28367
+ }
28368
+ const wantPath = filter2.dbPath === void 0 ? void 0 : resolve4(filter2.dbPath);
28369
+ for (const key of [..._bindings.keys()]) {
28370
+ const sep = key.indexOf("::");
28371
+ const lastSep = key.lastIndexOf("::");
28372
+ const scope = key.slice(0, sep);
28373
+ const dbPath = key.slice(sep + 2, lastSep);
28374
+ const domain2 = key.slice(lastSep + 2);
28375
+ if (filter2.scope !== void 0 && scope !== filter2.scope) continue;
28376
+ if (wantPath !== void 0 && dbPath !== wantPath) continue;
28377
+ if (filter2.domain !== void 0 && domain2 !== filter2.domain) continue;
28378
+ _bindings.delete(key);
28379
+ }
28380
+ }
28381
+ function boundProjectNative(domain2, cwd) {
28382
+ return peekProjectDomain(domain2, cwd)?.native ?? null;
28383
+ }
28384
+ function peekProjectDomain(domain2, cwd) {
28385
+ const dbPath = resolve4(resolveDualScopeDbPath("project", cwd));
28386
+ const row = _bindings.get(bindingKey("project", dbPath, domain2));
28387
+ if (row?.native.isOpen) return row;
28388
+ if (cwd !== void 0) return null;
28389
+ const suffix = `::${domain2}`;
28390
+ let sole;
28391
+ for (const [key, candidate] of _bindings) {
28392
+ if (!key.startsWith("project::") || !key.endsWith(suffix)) continue;
28393
+ if (!candidate.native.isOpen) continue;
28394
+ if (sole) return null;
28395
+ sole = candidate;
28396
+ }
28397
+ return sole ?? null;
28398
+ }
28399
+ var _runtime, _bindings, _inflight, MAX_LIVENESS_ATTEMPTS;
28400
+ var init_domain_binding = __esm({
28401
+ "packages/core/src/store/ports/domain-binding.ts"() {
28402
+ "use strict";
28403
+ init_dual_scope_db();
28404
+ _runtime = null;
28405
+ _bindings = /* @__PURE__ */ new Map();
28406
+ _inflight = /* @__PURE__ */ new Map();
28407
+ MAX_LIVENESS_ATTEMPTS = 2;
28408
+ }
28409
+ });
28410
+
28206
28411
  // packages/core/src/store/schema/nexus-schema.ts
28207
28412
  var nexus_schema_exports = {};
28208
28413
  __export(nexus_schema_exports, {
@@ -28711,6 +28916,7 @@ var nexus_sqlite_exports = {};
28711
28916
  __export(nexus_sqlite_exports, {
28712
28917
  NEXUS_SCHEMA_VERSION: () => NEXUS_SCHEMA_VERSION,
28713
28918
  _resetNestedNexusWarningGate: () => _resetNestedNexusWarningGate,
28919
+ bindNexusDomain: () => bindNexusDomain,
28714
28920
  closeNexusDb: () => closeNexusDb,
28715
28921
  detectAndWarnOnNestedNexus: () => detectAndWarnOnNestedNexus,
28716
28922
  getNestedNexusSentinelPath: () => getNestedNexusSentinelPath,
@@ -28919,13 +29125,13 @@ function ensureNexusRelationWeights(nativeDb) {
28919
29125
  nativeDb.exec(`PRAGMA foreign_keys=${fkWasOn ? "ON" : "OFF"}`);
28920
29126
  }
28921
29127
  }
28922
- function runNexusMigrations(nativeDb, db) {
29128
+ function runNexusMigrations(nativeDb, db, dbPath) {
28923
29129
  const migrationsFolder = resolveNexusMigrationsFolder();
28924
- if (tableExists4(nativeDb, "nexus_nodes") && _nexusDbPath) {
28925
- const backupPath = _nexusDbPath.replace(/\.db$/, "-pre-cleo.db.bak");
29130
+ if (tableExists4(nativeDb, "nexus_nodes")) {
29131
+ const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
28926
29132
  if (!existsSync14(backupPath)) {
28927
29133
  try {
28928
- copyFileSync4(_nexusDbPath, backupPath);
29134
+ copyFileSync4(dbPath, backupPath);
28929
29135
  } catch {
28930
29136
  }
28931
29137
  }
@@ -28967,75 +29173,45 @@ function runNexusMigrations(nativeDb, db) {
28967
29173
  ensureNexusFts5(nativeDb);
28968
29174
  }
28969
29175
  async function getNexusDb() {
28970
- const requestedPath = getNexusDbPath();
29176
+ return (await bindNexusDomain()).db.drizzle;
29177
+ }
29178
+ async function bindNexusDomain() {
28971
29179
  const requestedRegistryPath = getNexusRegistryDbPath();
28972
- if (_nexusDb && _nexusDbPath !== requestedPath) {
28973
- resetNexusDbState();
29180
+ const bound = peekProjectDomain("nexus");
29181
+ if (bound && bound.db.registryPath !== requestedRegistryPath) {
29182
+ releaseDomainBindings({ scope: "project", domain: "nexus" });
28974
29183
  }
28975
- if (_nexusDb && _nexusRegistryPath !== requestedRegistryPath) {
28976
- resetNexusDbState();
28977
- }
28978
- if (_nexusDb && (_nexusNativeDb === null || !_nexusNativeDb.isOpen)) {
28979
- resetNexusDbState();
28980
- }
28981
- if (_nexusDb) {
28982
- if (_nexusNativeDb) {
28983
- try {
28984
- ensureGlobalRegistryAttached(_nexusNativeDb);
28985
- } catch {
28986
- resetNexusDbState();
28987
- }
28988
- }
28989
- if (_nexusDb) return _nexusDb;
28990
- }
28991
- if (_nexusInitPromise) return _nexusInitPromise;
28992
- _nexusInitPromise = (async () => {
28993
- const dbPath = requestedPath;
28994
- _nexusDbPath = dbPath;
28995
- _nexusRegistryPath = requestedRegistryPath;
28996
- detectAndWarnOnNestedNexus();
28997
- await openDualScopeDb("global");
28998
- const dualHandle = await openDualScopeDb("project");
28999
- const nativeDb = dualHandle.db.$client ?? null;
29000
- if (!nativeDb) {
29001
- throw new Error(
29002
- "T11648: openDualScopeDb returned a handle without $client \u2014 cannot extract DatabaseSync for the nexus-schema drizzle wrapping."
29003
- );
29004
- }
29005
- _nexusNativeDb = nativeDb;
29184
+ detectAndWarnOnNestedNexus();
29185
+ await openDualScopeDb("global");
29186
+ const binding = await bindProjectDomain("nexus", void 0, (nativeDb, store) => {
29006
29187
  ensureGlobalRegistryAttached(nativeDb);
29007
29188
  const db = drizzle({ client: nativeDb });
29008
- runNexusMigrations(nativeDb, db);
29189
+ runNexusMigrations(nativeDb, db, store.dbPath);
29009
29190
  nativeDb.prepare(
29010
29191
  `INSERT OR IGNORE INTO nexus_schema_meta (key, value) VALUES ('schemaVersion', '${NEXUS_SCHEMA_VERSION}')`
29011
29192
  ).run();
29012
- _nexusDb = db;
29013
- return db;
29014
- })();
29193
+ return { drizzle: db, registryPath: requestedRegistryPath };
29194
+ });
29015
29195
  try {
29016
- return await _nexusInitPromise;
29017
- } finally {
29018
- _nexusInitPromise = null;
29196
+ ensureGlobalRegistryAttached(binding.native);
29197
+ } catch {
29198
+ releaseDomainBindings({ scope: "project", domain: "nexus" });
29199
+ throw new Error(
29200
+ "T12039: nexus binding lost its GLOBAL registry ATTACH and could not re-attach."
29201
+ );
29019
29202
  }
29203
+ return binding;
29020
29204
  }
29021
29205
  function closeNexusDb() {
29022
- _nexusNativeDb = null;
29023
- _nexusDb = null;
29024
- _nexusDbPath = null;
29025
- _nexusRegistryPath = null;
29026
- _nexusInitPromise = null;
29206
+ releaseDomainBindings({ scope: "project", domain: "nexus" });
29027
29207
  }
29028
29208
  function resetNexusDbState() {
29029
- _nexusNativeDb = null;
29030
- _nexusDb = null;
29031
- _nexusDbPath = null;
29032
- _nexusRegistryPath = null;
29033
- _nexusInitPromise = null;
29209
+ releaseDomainBindings({ scope: "project", domain: "nexus" });
29034
29210
  }
29035
29211
  function getNexusNativeDb() {
29036
- return _nexusNativeDb;
29212
+ return boundProjectNative("nexus");
29037
29213
  }
29038
- var NEXUS_SCHEMA_VERSION, _nexusDb, _nexusNativeDb, _nexusDbPath, _nexusRegistryPath, _nexusInitPromise, NEXUS_GLOBAL_ATTACH_ALIAS, NESTED_NEXUS_SENTINEL, _warnedNestedPaths;
29214
+ var NEXUS_SCHEMA_VERSION, NEXUS_GLOBAL_ATTACH_ALIAS, NESTED_NEXUS_SENTINEL, _warnedNestedPaths;
29039
29215
  var init_nexus_sqlite = __esm({
29040
29216
  "packages/core/src/store/nexus-sqlite.ts"() {
29041
29217
  "use strict";
@@ -29044,15 +29220,11 @@ var init_nexus_sqlite = __esm({
29044
29220
  init_paths();
29045
29221
  init_dual_scope_db();
29046
29222
  init_migration_manager();
29223
+ init_domain_binding();
29047
29224
  init_resolve_migrations_folder();
29048
29225
  init_nexus_schema();
29049
29226
  init_with_retry();
29050
29227
  NEXUS_SCHEMA_VERSION = "1.0.0";
29051
- _nexusDb = null;
29052
- _nexusNativeDb = null;
29053
- _nexusDbPath = null;
29054
- _nexusRegistryPath = null;
29055
- _nexusInitPromise = null;
29056
29228
  NEXUS_GLOBAL_ATTACH_ALIAS = "nexus_global";
29057
29229
  NESTED_NEXUS_SENTINEL = "nexus.db";
29058
29230
  _warnedNestedPaths = /* @__PURE__ */ new Set();
@@ -29064,7 +29236,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
29064
29236
  import { existsSync as existsSync15, readFileSync as readFileSync4, statSync as statSync5 } from "node:fs";
29065
29237
  import { createRequire as createRequire5 } from "node:module";
29066
29238
  import { homedir } from "node:os";
29067
- import { basename as basename4, dirname as dirname6, join as join15, resolve as resolve4 } from "node:path";
29239
+ import { basename as basename4, dirname as dirname6, join as join15, resolve as resolve5 } from "node:path";
29068
29240
  import {
29069
29241
  computeCanonicalProjectId as _computeCanonicalProjectId,
29070
29242
  getCanonicalTemplatesTildePath as _getCanonicalTemplatesTildePath,
@@ -29131,24 +29303,24 @@ function getCleoDirAbsolute(cwd, opts) {
29131
29303
  try {
29132
29304
  const projectRoot = getProjectRoot(cwd);
29133
29305
  const canonical = _resolveCanonicalCleoDir(project.projectId);
29134
- if (canonical !== null && canonical === resolve4(projectRoot, cleoDir)) {
29306
+ if (canonical !== null && canonical === resolve5(projectRoot, cleoDir)) {
29135
29307
  return canonical;
29136
29308
  }
29137
- return resolve4(projectRoot, cleoDir);
29309
+ return resolve5(projectRoot, cleoDir);
29138
29310
  } catch {
29139
- return resolve4(project.projectRoot, cleoDir);
29311
+ return resolve5(project.projectRoot, cleoDir);
29140
29312
  }
29141
29313
  }
29142
29314
  try {
29143
- return resolve4(getProjectRoot(cwd), cleoDir);
29315
+ return resolve5(getProjectRoot(cwd), cleoDir);
29144
29316
  } catch (err) {
29145
29317
  if (opts?.bootstrap) {
29146
- return resolve4(cwd ?? process.cwd(), cleoDir);
29318
+ return resolve5(cwd ?? process.cwd(), cleoDir);
29147
29319
  }
29148
29320
  if (_cwdHasGitAncestor(cwd)) {
29149
29321
  throw err;
29150
29322
  }
29151
- return resolve4(cwd ?? process.cwd(), cleoDir);
29323
+ return resolve5(cwd ?? process.cwd(), cleoDir);
29152
29324
  }
29153
29325
  }
29154
29326
  function _resolveProjectByCwdFromNexus(cwd) {
@@ -29156,7 +29328,7 @@ function _resolveProjectByCwdFromNexus(cwd) {
29156
29328
  const cleoHome = getCleoHome();
29157
29329
  const globalDbPath = join15(cleoHome, "cleo.db");
29158
29330
  if (!existsSync15(globalDbPath)) return null;
29159
- const start = resolve4(cwd ?? process.cwd());
29331
+ const start = resolve5(cwd ?? process.cwd());
29160
29332
  let current = start;
29161
29333
  const DatabaseSync2 = _getDatabaseSyncCtor();
29162
29334
  const db = new DatabaseSync2(globalDbPath, { readOnly: true });
@@ -29189,7 +29361,7 @@ function _cleoDirEnvOverride() {
29189
29361
  }
29190
29362
  function _findCleoDirRoot(cwd) {
29191
29363
  const homeRoot = homedir();
29192
- let current = resolve4(cwd ?? process.cwd());
29364
+ let current = resolve5(cwd ?? process.cwd());
29193
29365
  while (true) {
29194
29366
  const isDangerousRoot = current === homeRoot || current === "/" || current === "";
29195
29367
  if (!isDangerousRoot) {
@@ -29219,7 +29391,7 @@ function resolveCleoDir(cwd) {
29219
29391
  if (root !== null) {
29220
29392
  return join15(root, ".cleo");
29221
29393
  }
29222
- const start = resolve4(cwd ?? process.cwd());
29394
+ const start = resolve5(cwd ?? process.cwd());
29223
29395
  let current = start;
29224
29396
  while (true) {
29225
29397
  const mainRepo = _resolveMainRepoFromGitlink(current);
@@ -29255,15 +29427,15 @@ function _resolveCleoDir(cwd) {
29255
29427
  const project = _pathsResolveProjectByCwd(cwd);
29256
29428
  if (project !== null) {
29257
29429
  try {
29258
- return resolve4(getProjectRoot(cwd), cleoDir);
29430
+ return resolve5(getProjectRoot(cwd), cleoDir);
29259
29431
  } catch {
29260
- return resolve4(project.projectRoot, cleoDir);
29432
+ return resolve5(project.projectRoot, cleoDir);
29261
29433
  }
29262
29434
  }
29263
29435
  return getCleoDirAbsolute(cwd);
29264
29436
  }
29265
29437
  function _cwdHasGitAncestor(cwd) {
29266
- const start = resolve4(cwd ?? process.cwd());
29438
+ const start = resolve5(cwd ?? process.cwd());
29267
29439
  let current = start;
29268
29440
  while (true) {
29269
29441
  const gitMarker = join15(current, ".git");
@@ -29363,7 +29535,7 @@ function getProjectRoot(cwd) {
29363
29535
  }
29364
29536
  return cleoDirEnv;
29365
29537
  }
29366
- const start = resolve4(cwd ?? process.cwd());
29538
+ const start = resolve5(cwd ?? process.cwd());
29367
29539
  let current = start;
29368
29540
  const mainRepoFromStart = _resolveMainRepoFromGitlink(start);
29369
29541
  if (mainRepoFromStart !== null) return mainRepoFromStart;
@@ -29456,7 +29628,7 @@ async function registerProjectOnEncounter(projectRoot, infoProjectId) {
29456
29628
  const db = await getNexusDb2();
29457
29629
  const existingRows = await db.select().from(projectRegistry2).where(eq2(projectRegistry2.projectId, immutableId)).limit(1);
29458
29630
  const now = (/* @__PURE__ */ new Date()).toISOString();
29459
- const resolvedPath = resolve4(projectRoot);
29631
+ const resolvedPath = resolve5(projectRoot);
29460
29632
  const projectName = _readProjectNameFromInfo(resolvedPath) || basename4(projectRoot) || "unnamed";
29461
29633
  if (existingRows.length > 0) {
29462
29634
  const existingPath = existingRows[0].projectPath;
@@ -33317,7 +33489,7 @@ function storedToResolved(stored) {
33317
33489
  };
33318
33490
  }
33319
33491
  function sleep2(ms) {
33320
- return new Promise((resolve6) => setTimeout(resolve6, ms));
33492
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
33321
33493
  }
33322
33494
  function backoffMs(policy, attempt) {
33323
33495
  const base = policy.baseDelayMs * 2 ** attempt;
@@ -35931,9 +36103,9 @@ var init_chat_completions = __esm({
35931
36103
  outputTokens: response.usage?.completion_tokens ?? 0
35932
36104
  };
35933
36105
  const promptDetails = response.usage?.["prompt_tokens_details"];
35934
- const cached2 = promptDetails?.["cached_tokens"];
35935
- if (typeof cached2 === "number" && cached2 > 0) {
35936
- usage.cachedTokens = cached2;
36106
+ const cached3 = promptDetails?.["cached_tokens"];
36107
+ if (typeof cached3 === "number" && cached3 > 0) {
36108
+ usage.cachedTokens = cached3;
35937
36109
  }
35938
36110
  return {
35939
36111
  id: response.id ?? `chat-${Date.now().toString(36)}`,
@@ -36175,9 +36347,9 @@ function normalizeUsage(usage) {
36175
36347
  const outputTokens = usage["output_tokens"] ?? 0;
36176
36348
  const normalized = { inputTokens, outputTokens };
36177
36349
  const details = usage["input_tokens_details"];
36178
- const cached2 = details?.["cached_tokens"];
36179
- if (typeof cached2 === "number" && cached2 > 0) {
36180
- normalized.cachedTokens = cached2;
36350
+ const cached3 = details?.["cached_tokens"];
36351
+ if (typeof cached3 === "number" && cached3 > 0) {
36352
+ normalized.cachedTokens = cached3;
36181
36353
  }
36182
36354
  return normalized;
36183
36355
  }
@@ -37211,7 +37383,7 @@ function normalizeOllamaToolCall(tc) {
37211
37383
  };
37212
37384
  }
37213
37385
  function sleep3(ms) {
37214
- return new Promise((resolve6) => setTimeout(resolve6, ms));
37386
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
37215
37387
  }
37216
37388
  var OLLAMA_DEFAULT_BASE_URL, MAX_RETRIES, INITIAL_BACKOFF_MS, RETRYABLE_STATUS_CODES, OllamaTransport;
37217
37389
  var init_ollama2 = __esm({
@@ -57725,7 +57897,7 @@ function createProviderToolFactoryWithOutputSchema({
57725
57897
  supportsDeferredResults
57726
57898
  });
57727
57899
  }
57728
- async function resolve5(value) {
57900
+ async function resolve6(value) {
57729
57901
  if (typeof value === "function") {
57730
57902
  value = value();
57731
57903
  }
@@ -61759,14 +61931,14 @@ var init_dist4 = __esm({
61759
61931
  headers
61760
61932
  }) {
61761
61933
  return combineHeaders(
61762
- await resolve5(this.config.headers),
61934
+ await resolve6(this.config.headers),
61763
61935
  headers,
61764
61936
  betas.size > 0 ? { "anthropic-beta": Array.from(betas).join(",") } : {}
61765
61937
  );
61766
61938
  }
61767
61939
  async getBetasFromHeaders(requestHeaders) {
61768
61940
  var _a17, _b16;
61769
- const configHeaders = await resolve5(this.config.headers);
61941
+ const configHeaders = await resolve6(this.config.headers);
61770
61942
  const configBetaHeader = (_a17 = configHeaders["anthropic-beta"]) != null ? _a17 : "";
61771
61943
  const requestBetaHeader = (_b16 = requestHeaders == null ? void 0 : requestHeaders["anthropic-beta"]) != null ? _b16 : "";
61772
61944
  return new Set(
@@ -65350,6 +65522,76 @@ var init_model_runner = __esm({
65350
65522
  }
65351
65523
  });
65352
65524
 
65525
+ // packages/core/src/llm/local-inference-probe.ts
65526
+ function extractModels(body) {
65527
+ if (body === null || typeof body !== "object") return [];
65528
+ const rec = body;
65529
+ if (Array.isArray(rec.models)) {
65530
+ return rec.models.map(
65531
+ (m) => m !== null && typeof m === "object" ? m.name ?? m.model : void 0
65532
+ ).filter((n) => typeof n === "string");
65533
+ }
65534
+ if (Array.isArray(rec.data)) {
65535
+ return rec.data.map((m) => m !== null && typeof m === "object" ? m.id : void 0).filter((n) => typeof n === "string");
65536
+ }
65537
+ return [];
65538
+ }
65539
+ async function detectLocalInference(opts = {}) {
65540
+ if (process.env["CLEO_DISABLE_LOCAL_INFERENCE"]?.trim()) return null;
65541
+ if (!opts.force && cached2 !== void 0) return cached2;
65542
+ for (const endpoint of LOCAL_ENDPOINTS) {
65543
+ try {
65544
+ const response = await fetch(endpoint.tagsUrl, {
65545
+ signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
65546
+ });
65547
+ if (!response.ok) continue;
65548
+ const models = extractModels(await response.json());
65549
+ if (models.length === 0) continue;
65550
+ cached2 = {
65551
+ name: endpoint.name,
65552
+ baseUrl: endpoint.baseUrl,
65553
+ openAiBaseUrl: endpoint.openAiBaseUrl,
65554
+ models
65555
+ };
65556
+ return cached2;
65557
+ } catch {
65558
+ }
65559
+ }
65560
+ cached2 = null;
65561
+ return cached2;
65562
+ }
65563
+ async function listOllamaModels(baseUrl) {
65564
+ try {
65565
+ const url2 = `${baseUrl.replace(/\/+$/, "")}/api/tags`;
65566
+ const response = await fetch(url2, { signal: AbortSignal.timeout(PROBE_TIMEOUT_MS) });
65567
+ if (!response.ok) return [];
65568
+ return extractModels(await response.json());
65569
+ } catch {
65570
+ return [];
65571
+ }
65572
+ }
65573
+ var LOCAL_ENDPOINTS, PROBE_TIMEOUT_MS, cached2;
65574
+ var init_local_inference_probe = __esm({
65575
+ "packages/core/src/llm/local-inference-probe.ts"() {
65576
+ "use strict";
65577
+ LOCAL_ENDPOINTS = [
65578
+ {
65579
+ name: "ollama",
65580
+ tagsUrl: "http://127.0.0.1:11434/api/tags",
65581
+ baseUrl: "http://127.0.0.1:11434",
65582
+ openAiBaseUrl: "http://127.0.0.1:11434/v1"
65583
+ },
65584
+ {
65585
+ name: "lm-studio",
65586
+ tagsUrl: "http://127.0.0.1:1234/v1/models",
65587
+ baseUrl: "http://127.0.0.1:1234",
65588
+ openAiBaseUrl: "http://127.0.0.1:1234/v1"
65589
+ }
65590
+ ];
65591
+ PROBE_TIMEOUT_MS = 300;
65592
+ }
65593
+ });
65594
+
65353
65595
  // packages/core/src/llm/catalog-model-resolver.ts
65354
65596
  var catalog_model_resolver_exports = {};
65355
65597
  __export(catalog_model_resolver_exports, {
@@ -65434,9 +65676,9 @@ var init_catalog_model_resolver = __esm({
65434
65676
  // packages/core/src/llm/cross-provider-selector.ts
65435
65677
  import { totalmem as totalmem2 } from "node:os";
65436
65678
  async function probeOllamaAlive(baseUrl) {
65437
- const cached2 = _ollamaProbeCache.get(baseUrl);
65438
- if (cached2 && Date.now() - cached2.checkedAt < OLLAMA_PROBE_TTL_MS) {
65439
- return cached2.alive;
65679
+ const cached3 = _ollamaProbeCache.get(baseUrl);
65680
+ if (cached3 && Date.now() - cached3.checkedAt < OLLAMA_PROBE_TTL_MS) {
65681
+ return cached3.alive;
65440
65682
  }
65441
65683
  let alive = false;
65442
65684
  try {
@@ -65478,6 +65720,16 @@ function isProvisioned(provider) {
65478
65720
  const cred = resolveCredentials(provider);
65479
65721
  return (cred.apiKey?.trim().length ?? 0) > 0;
65480
65722
  }
65723
+ function reconcileOllamaModel(preferred, installed) {
65724
+ if (installed.length === 0) return preferred;
65725
+ if (installed.includes(preferred)) return preferred;
65726
+ const family = preferred.split(":")[0];
65727
+ if (family !== void 0 && family !== "") {
65728
+ const sameFamily = installed.find((m) => m.split(":")[0] === family);
65729
+ if (sameFamily !== void 0) return sameFamily;
65730
+ }
65731
+ return installed[0] ?? preferred;
65732
+ }
65481
65733
  function scoreProvider(provider, providerTier, taskTier, ollamaAlive, costInputPerMillion) {
65482
65734
  let score = TIER_BASE[providerTier];
65483
65735
  if (taskTier === "frontier" && providerTier === "frontier") {
@@ -65510,6 +65762,7 @@ function roleTierFor(role) {
65510
65762
  }
65511
65763
  async function selectBestProvisioned(role, opts) {
65512
65764
  const taskTier = roleTierFor(role);
65765
+ const excluded = new Set(opts.exclude ?? []);
65513
65766
  for (const id of BUILTIN_PROVIDER_IDS) {
65514
65767
  const creds = await listCredentials(id);
65515
65768
  const hasExpiredOAuth = creds.some(
@@ -65534,10 +65787,23 @@ async function selectBestProvisioned(role, opts) {
65534
65787
  }
65535
65788
  const provisionedIds = [];
65536
65789
  for (const id of BUILTIN_PROVIDER_IDS) {
65790
+ if (excluded.has(id)) continue;
65537
65791
  if (isProvisioned(id)) {
65538
65792
  provisionedIds.push(id);
65539
65793
  }
65540
65794
  }
65795
+ let localModels = [];
65796
+ if (!excluded.has("ollama") && !provisionedIds.includes("ollama")) {
65797
+ const local = await detectLocalInference();
65798
+ if (local !== null && local.name === "ollama") {
65799
+ provisionedIds.push("ollama");
65800
+ localModels = local.models;
65801
+ logger4.debug(
65802
+ { baseUrl: local.baseUrl, models: local.models },
65803
+ "cross-provider-selector: unlisted ollama daemon is live \u2014 admitting as provisioned"
65804
+ );
65805
+ }
65806
+ }
65541
65807
  if (provisionedIds.length === 0) {
65542
65808
  logger4.warn(
65543
65809
  {
@@ -65554,11 +65820,12 @@ async function selectBestProvisioned(role, opts) {
65554
65820
  const { resolveProviderDefaultModel: resolveProviderDefaultModel2, catalogKeyForProvider: catalogKeyForProvider2 } = await Promise.resolve().then(() => (init_catalog_model_resolver(), catalog_model_resolver_exports));
65555
65821
  const { pickCredentialForProvider: pickCredentialForProvider2 } = await Promise.resolve().then(() => (init_credentials_store(), credentials_store_exports));
65556
65822
  const ollamaProvisioned = provisionedIds.includes("ollama");
65557
- let ollamaAlive = false;
65558
- if (ollamaProvisioned) {
65823
+ let ollamaAlive = localModels.length > 0;
65824
+ if (ollamaProvisioned && !ollamaAlive) {
65559
65825
  const profile = await getProviderProfile2("ollama");
65560
65826
  const ollamaBase = profile?.baseUrl ?? "http://localhost:11434";
65561
65827
  ollamaAlive = await probeOllamaAlive(ollamaBase);
65828
+ if (ollamaAlive) localModels = await listOllamaModels(ollamaBase);
65562
65829
  }
65563
65830
  const scored = [];
65564
65831
  for (const id of provisionedIds) {
@@ -65588,6 +65855,7 @@ async function selectBestProvisioned(role, opts) {
65588
65855
  } else {
65589
65856
  model = ollamaDefaultModelForTier(winner.tier, ramBytes);
65590
65857
  }
65858
+ model = reconcileOllamaModel(model, localModels);
65591
65859
  const catalogKey = catalogKeyForProvider2(winner.id);
65592
65860
  const catalogModel = resolveProviderDefaultModel2(catalogKey);
65593
65861
  if (!catalogModel?.startsWith("gemma4")) {
@@ -65631,6 +65899,7 @@ var init_cross_provider_selector = __esm({
65631
65899
  init_credential_pool();
65632
65900
  init_credentials2();
65633
65901
  init_credentials_store();
65902
+ init_local_inference_probe();
65634
65903
  logger4 = getLogger("llm-cross-provider-selector");
65635
65904
  BUILTIN_PROVIDER_IDS = [
65636
65905
  "anthropic",
@@ -65747,6 +66016,7 @@ __export(role_resolver_exports, {
65747
66016
  HYGIENE_FALLBACK_MODEL: () => HYGIENE_FALLBACK_MODEL,
65748
66017
  IMPLICIT_FALLBACK_MODEL: () => IMPLICIT_FALLBACK_MODEL,
65749
66018
  IMPLICIT_FALLBACK_PROVIDER: () => IMPLICIT_FALLBACK_PROVIDER,
66019
+ LOCAL_PLACEHOLDER_TOKEN: () => LOCAL_PLACEHOLDER_TOKEN,
65750
66020
  resolveAnthropicForRole: () => resolveAnthropicForRole,
65751
66021
  resolveLLMForRole: () => resolveLLMForRole
65752
66022
  });
@@ -65850,6 +66120,16 @@ async function selectProviderModel(llm, role, systemKey, profileOverride, projec
65850
66120
  source: "implicit-fallback"
65851
66121
  };
65852
66122
  }
66123
+ async function applyProviderExclusions(selected, role, projectRoot, exclude) {
66124
+ if (exclude === void 0 || exclude.length === 0) return selected;
66125
+ if (!exclude.includes(selected.provider)) return selected;
66126
+ try {
66127
+ const substitute = await selectBestProvisioned(role, { projectRoot, exclude });
66128
+ if (substitute !== null) return substitute;
66129
+ } catch {
66130
+ }
66131
+ return selected;
66132
+ }
65853
66133
  async function resolveCredentialForRole(provider, credentialLabel, projectRoot) {
65854
66134
  try {
65855
66135
  await new CredentialPool(provider).refreshExpiredOAuth();
@@ -65864,7 +66144,9 @@ async function resolveCredentialForRole(provider, credentialLabel, projectRoot)
65864
66144
  provider,
65865
66145
  apiKey: stored.accessToken,
65866
66146
  source: "cred-file",
65867
- authType: wireAuthType
66147
+ authType: wireAuthType,
66148
+ // T12081: preserve the stored endpoint (Ollama/LM Studio/vLLM/…).
66149
+ baseUrl: stored.baseUrl ?? null
65868
66150
  },
65869
66151
  usedLabel: stored.label
65870
66152
  };
@@ -65880,7 +66162,9 @@ async function resolveCredentialForRole(provider, credentialLabel, projectRoot)
65880
66162
  provider,
65881
66163
  apiKey: picked.accessToken,
65882
66164
  source: "cred-file",
65883
- authType: wireAuthType
66165
+ authType: wireAuthType,
66166
+ // T12081: preserve the stored endpoint (Ollama/LM Studio/vLLM/…).
66167
+ baseUrl: picked.baseUrl ?? null
65884
66168
  },
65885
66169
  usedLabel: picked.label
65886
66170
  };
@@ -65890,6 +66174,23 @@ async function resolveCredentialForRole(provider, credentialLabel, projectRoot)
65890
66174
  if (cred.apiKey) {
65891
66175
  return { credential: cred, usedLabel: void 0 };
65892
66176
  }
66177
+ if (provider === "ollama") {
66178
+ const local = await detectLocalInference();
66179
+ if (local !== null && local.name === "ollama") {
66180
+ return {
66181
+ credential: {
66182
+ provider,
66183
+ apiKey: LOCAL_PLACEHOLDER_TOKEN,
66184
+ source: "local-daemon",
66185
+ authType: "api_key",
66186
+ // ROOT url, not the `/v1` form: `deriveApiWire('ollama')` selects the
66187
+ // NATIVE transport, which appends `/api/chat` itself.
66188
+ baseUrl: local.baseUrl
66189
+ },
66190
+ usedLabel: void 0
66191
+ };
66192
+ }
66193
+ }
65893
66194
  return { credential: null, usedLabel: void 0 };
65894
66195
  }
65895
66196
  async function resolveLLMForRole(role, opts) {
@@ -65902,13 +66203,19 @@ async function resolveLLMForRole(role, opts) {
65902
66203
  config2 = void 0;
65903
66204
  }
65904
66205
  const llmBlock = readLlmBlock(config2);
65905
- const { provider, model, credentialLabel, source } = await selectProviderModel(
66206
+ const selected = await selectProviderModel(
65906
66207
  llmBlock,
65907
66208
  role,
65908
66209
  opts?.systemKey,
65909
66210
  opts?.profileOverride,
65910
66211
  projectRoot
65911
66212
  );
66213
+ const { provider, model, credentialLabel, source } = await applyProviderExclusions(
66214
+ selected,
66215
+ role,
66216
+ projectRoot,
66217
+ opts?.excludeProviders
66218
+ );
65912
66219
  const { credential, usedLabel } = await resolveCredentialForRole(
65913
66220
  provider,
65914
66221
  credentialLabel,
@@ -65934,7 +66241,12 @@ async function resolveLLMForRole(role, opts) {
65934
66241
  credentialMetadata = {
65935
66242
  provider: credential.provider,
65936
66243
  source: credential.source,
65937
- authType: wireAuthType
66244
+ authType: wireAuthType,
66245
+ // T12081: carry the credential's OWN endpoint. Without it a consumer
66246
+ // building a transport cannot tell that this credential targets a local
66247
+ // or proxied host, and falls back to the provider's public API — which
66248
+ // rejected every Ollama / LM Studio / vLLM / OpenRouter credential 401.
66249
+ baseUrl: credential.baseUrl ?? null
65938
66250
  };
65939
66251
  sealedCredential = makeSealedCredential({
65940
66252
  provider: credential.provider,
@@ -65976,7 +66288,7 @@ async function resolveAnthropicForRole(role, opts) {
65976
66288
  model: llm.model
65977
66289
  };
65978
66290
  }
65979
- var IMPLICIT_FALLBACK_PROVIDER, HYGIENE_FALLBACK_MODEL;
66291
+ var IMPLICIT_FALLBACK_PROVIDER, LOCAL_PLACEHOLDER_TOKEN, HYGIENE_FALLBACK_MODEL;
65980
66292
  var init_role_resolver = __esm({
65981
66293
  "packages/core/src/llm/role-resolver.ts"() {
65982
66294
  "use strict";
@@ -65987,10 +66299,12 @@ var init_role_resolver = __esm({
65987
66299
  init_credentials_store();
65988
66300
  init_cross_provider_selector();
65989
66301
  init_fallback_model();
66302
+ init_local_inference_probe();
65990
66303
  init_sealed_credential();
65991
66304
  init_system_of_use_registry();
65992
66305
  init_anthropic_client_factory();
65993
66306
  IMPLICIT_FALLBACK_PROVIDER = "anthropic";
66307
+ LOCAL_PLACEHOLDER_TOKEN = "local";
65994
66308
  HYGIENE_FALLBACK_MODEL = "claude-sonnet-4-6";
65995
66309
  }
65996
66310
  });
@@ -66849,8 +67163,8 @@ var _engineRegistry = /* @__PURE__ */ new Map([
66849
67163
  registerContextEngine("llm-summarization", _engineRegistry.get("compression"));
66850
67164
  var _executorCache = /* @__PURE__ */ new Map();
66851
67165
  async function getLlmExecutor(role) {
66852
- const cached2 = _executorCache.get(role);
66853
- if (cached2 !== void 0) return cached2;
67166
+ const cached3 = _executorCache.get(role);
67167
+ if (cached3 !== void 0) return cached3;
66854
67168
  const contextEngine = _engineRegistry.get(role);
66855
67169
  const factory11 = new DefaultLlmExecutorFactory({ contextEngine });
66856
67170
  const executor = await factory11.createForRole(role);