@cleocode/core 2026.6.12 → 2026.6.13

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 (385) hide show
  1. package/dist/conduit/local-transport.d.ts +12 -0
  2. package/dist/conduit/local-transport.d.ts.map +1 -1
  3. package/dist/conduit/local-transport.js +53 -23
  4. package/dist/conduit/local-transport.js.map +1 -1
  5. package/dist/crypto/credentials.d.ts +37 -0
  6. package/dist/crypto/credentials.d.ts.map +1 -1
  7. package/dist/crypto/credentials.js +110 -0
  8. package/dist/crypto/credentials.js.map +1 -1
  9. package/dist/dispatch/contracts/derive-output-contract.d.ts +86 -0
  10. package/dist/dispatch/contracts/derive-output-contract.d.ts.map +1 -0
  11. package/dist/dispatch/contracts/derive-output-contract.js +347 -0
  12. package/dist/dispatch/contracts/derive-output-contract.js.map +1 -0
  13. package/dist/dispatch/contracts/ensures-schema.d.ts +77 -0
  14. package/dist/dispatch/contracts/ensures-schema.d.ts.map +1 -0
  15. package/dist/dispatch/contracts/ensures-schema.js +91 -0
  16. package/dist/dispatch/contracts/ensures-schema.js.map +1 -0
  17. package/dist/dispatch/contracts/output-contracts.d.ts +27 -5
  18. package/dist/dispatch/contracts/output-contracts.d.ts.map +1 -1
  19. package/dist/dispatch/contracts/output-contracts.js +29 -6
  20. package/dist/dispatch/contracts/output-contracts.js.map +1 -1
  21. package/dist/docs/export-document.js +2294 -1250
  22. package/dist/docs/export-document.js.map +3 -3
  23. package/dist/go/driver.d.ts +132 -7
  24. package/dist/go/driver.d.ts.map +1 -1
  25. package/dist/go/driver.js +135 -10
  26. package/dist/go/driver.js.map +1 -1
  27. package/dist/go/index.d.ts +1 -1
  28. package/dist/go/index.d.ts.map +1 -1
  29. package/dist/go/index.js +1 -1
  30. package/dist/go/index.js.map +1 -1
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +5 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/internal.d.ts +13 -10
  36. package/dist/internal.d.ts.map +1 -1
  37. package/dist/internal.js +11 -11
  38. package/dist/internal.js.map +1 -1
  39. package/dist/lifecycle/engine-ops.d.ts.map +1 -1
  40. package/dist/lifecycle/engine-ops.js +7 -4
  41. package/dist/lifecycle/engine-ops.js.map +1 -1
  42. package/dist/lifecycle/ivtr-loop.d.ts +108 -183
  43. package/dist/lifecycle/ivtr-loop.d.ts.map +1 -1
  44. package/dist/lifecycle/ivtr-loop.js +207 -522
  45. package/dist/lifecycle/ivtr-loop.js.map +1 -1
  46. package/dist/llm/auxiliary-fallback.js +1 -1
  47. package/dist/llm/auxiliary-fallback.js.map +1 -1
  48. package/dist/llm/cli-ops.d.ts +14 -1
  49. package/dist/llm/cli-ops.d.ts.map +1 -1
  50. package/dist/llm/cli-ops.js +41 -12
  51. package/dist/llm/cli-ops.js.map +1 -1
  52. package/dist/llm/concrete-session.d.ts.map +1 -1
  53. package/dist/llm/concrete-session.js +4 -0
  54. package/dist/llm/concrete-session.js.map +1 -1
  55. package/dist/llm/credentials.d.ts +35 -0
  56. package/dist/llm/credentials.d.ts.map +1 -1
  57. package/dist/llm/credentials.js +49 -0
  58. package/dist/llm/credentials.js.map +1 -1
  59. package/dist/llm/index.d.ts +4 -0
  60. package/dist/llm/index.d.ts.map +1 -1
  61. package/dist/llm/index.js +4 -0
  62. package/dist/llm/index.js.map +1 -1
  63. package/dist/llm/pi/gondolin-loader.d.ts +241 -0
  64. package/dist/llm/pi/gondolin-loader.d.ts.map +1 -0
  65. package/dist/llm/pi/gondolin-loader.js +195 -0
  66. package/dist/llm/pi/gondolin-loader.js.map +1 -0
  67. package/dist/llm/pi/index.d.ts +28 -0
  68. package/dist/llm/pi/index.d.ts.map +1 -0
  69. package/dist/llm/pi/index.js +27 -0
  70. package/dist/llm/pi/index.js.map +1 -0
  71. package/dist/llm/pi/pi-agent-adapter.d.ts +135 -0
  72. package/dist/llm/pi/pi-agent-adapter.d.ts.map +1 -0
  73. package/dist/llm/pi/pi-agent-adapter.js +329 -0
  74. package/dist/llm/pi/pi-agent-adapter.js.map +1 -0
  75. package/dist/llm/pi/pi-errors.d.ts +161 -0
  76. package/dist/llm/pi/pi-errors.d.ts.map +1 -0
  77. package/dist/llm/pi/pi-errors.js +296 -0
  78. package/dist/llm/pi/pi-errors.js.map +1 -0
  79. package/dist/llm/pi/pi-execution-env.d.ts +286 -0
  80. package/dist/llm/pi/pi-execution-env.d.ts.map +1 -0
  81. package/dist/llm/pi/pi-execution-env.js +406 -0
  82. package/dist/llm/pi/pi-execution-env.js.map +1 -0
  83. package/dist/llm/pi/pi-gondolin-env.d.ts +227 -0
  84. package/dist/llm/pi/pi-gondolin-env.d.ts.map +1 -0
  85. package/dist/llm/pi/pi-gondolin-env.js +541 -0
  86. package/dist/llm/pi/pi-gondolin-env.js.map +1 -0
  87. package/dist/llm/pi/pi-session-storage.d.ts +154 -0
  88. package/dist/llm/pi/pi-session-storage.d.ts.map +1 -0
  89. package/dist/llm/pi/pi-session-storage.js +314 -0
  90. package/dist/llm/pi/pi-session-storage.js.map +1 -0
  91. package/dist/llm/pi/pi-stream-fn.d.ts +124 -0
  92. package/dist/llm/pi/pi-stream-fn.d.ts.map +1 -0
  93. package/dist/llm/pi/pi-stream-fn.js +504 -0
  94. package/dist/llm/pi/pi-stream-fn.js.map +1 -0
  95. package/dist/llm/pi/pi-tool-bridge.d.ts +99 -0
  96. package/dist/llm/pi/pi-tool-bridge.d.ts.map +1 -0
  97. package/dist/llm/pi/pi-tool-bridge.js +117 -0
  98. package/dist/llm/pi/pi-tool-bridge.js.map +1 -0
  99. package/dist/llm/pi/pi-types.d.ts +56 -0
  100. package/dist/llm/pi/pi-types.d.ts.map +1 -0
  101. package/dist/llm/pi/pi-types.js +16 -0
  102. package/dist/llm/pi/pi-types.js.map +1 -0
  103. package/dist/llm/pi/resolve-execution-env.d.ts +194 -0
  104. package/dist/llm/pi/resolve-execution-env.d.ts.map +1 -0
  105. package/dist/llm/pi/resolve-execution-env.js +132 -0
  106. package/dist/llm/pi/resolve-execution-env.js.map +1 -0
  107. package/dist/llm/plugin-facade.js +2253 -1151
  108. package/dist/llm/plugin-facade.js.map +3 -3
  109. package/dist/llm/role-executor.d.ts.map +1 -1
  110. package/dist/llm/role-executor.js +8 -5
  111. package/dist/llm/role-executor.js.map +1 -1
  112. package/dist/llm/role-resolver.d.ts +46 -14
  113. package/dist/llm/role-resolver.d.ts.map +1 -1
  114. package/dist/llm/role-resolver.js +178 -20
  115. package/dist/llm/role-resolver.js.map +1 -1
  116. package/dist/llm/sealed-credential.d.ts +125 -0
  117. package/dist/llm/sealed-credential.d.ts.map +1 -0
  118. package/dist/llm/sealed-credential.js +133 -0
  119. package/dist/llm/sealed-credential.js.map +1 -0
  120. package/dist/llm/session-factory.d.ts.map +1 -1
  121. package/dist/llm/session-factory.js +6 -2
  122. package/dist/llm/session-factory.js.map +1 -1
  123. package/dist/llm/system-key.d.ts +67 -0
  124. package/dist/llm/system-key.d.ts.map +1 -0
  125. package/dist/llm/system-key.js +87 -0
  126. package/dist/llm/system-key.js.map +1 -0
  127. package/dist/llm/system-of-use-registry.d.ts +119 -0
  128. package/dist/llm/system-of-use-registry.d.ts.map +1 -0
  129. package/dist/llm/system-of-use-registry.js +200 -0
  130. package/dist/llm/system-of-use-registry.js.map +1 -0
  131. package/dist/llm/system-resolver.d.ts +32 -10
  132. package/dist/llm/system-resolver.d.ts.map +1 -1
  133. package/dist/llm/system-resolver.js +70 -18
  134. package/dist/llm/system-resolver.js.map +1 -1
  135. package/dist/memory/brain-writer-thread.d.ts.map +1 -1
  136. package/dist/memory/brain-writer-thread.js +116 -11
  137. package/dist/memory/brain-writer-thread.js.map +1 -1
  138. package/dist/memory/claude-mem-migration.d.ts.map +1 -1
  139. package/dist/memory/claude-mem-migration.js +21 -0
  140. package/dist/memory/claude-mem-migration.js.map +1 -1
  141. package/dist/memory/graph-memory-bridge.d.ts.map +1 -1
  142. package/dist/memory/graph-memory-bridge.js +32 -25
  143. package/dist/memory/graph-memory-bridge.js.map +1 -1
  144. package/dist/memory/llm-backend-resolver.js +23 -5
  145. package/dist/memory/llm-backend-resolver.js.map +1 -1
  146. package/dist/nexus/migrations/M-split-graph.d.ts.map +1 -1
  147. package/dist/nexus/migrations/M-split-graph.js +60 -53
  148. package/dist/nexus/migrations/M-split-graph.js.map +1 -1
  149. package/dist/orchestrate/pivot.d.ts.map +1 -1
  150. package/dist/orchestrate/pivot.js +20 -2
  151. package/dist/orchestrate/pivot.js.map +1 -1
  152. package/dist/release/engine-ops.js +2 -2
  153. package/dist/release/engine-ops.js.map +1 -1
  154. package/dist/routing/capability-matrix.d.ts.map +1 -1
  155. package/dist/routing/capability-matrix.js +0 -57
  156. package/dist/routing/capability-matrix.js.map +1 -1
  157. package/dist/selfimprove/budget.d.ts +206 -0
  158. package/dist/selfimprove/budget.d.ts.map +1 -0
  159. package/dist/selfimprove/budget.js +203 -0
  160. package/dist/selfimprove/budget.js.map +1 -0
  161. package/dist/selfimprove/dhq-adapter.d.ts +105 -0
  162. package/dist/selfimprove/dhq-adapter.d.ts.map +1 -0
  163. package/dist/selfimprove/dhq-adapter.js +95 -0
  164. package/dist/selfimprove/dhq-adapter.js.map +1 -0
  165. package/dist/selfimprove/draft-pr.d.ts +129 -0
  166. package/dist/selfimprove/draft-pr.d.ts.map +1 -0
  167. package/dist/selfimprove/draft-pr.js +158 -0
  168. package/dist/selfimprove/draft-pr.js.map +1 -0
  169. package/dist/selfimprove/envelope-diff.d.ts +162 -0
  170. package/dist/selfimprove/envelope-diff.d.ts.map +1 -0
  171. package/dist/selfimprove/envelope-diff.js +321 -0
  172. package/dist/selfimprove/envelope-diff.js.map +1 -0
  173. package/dist/selfimprove/replay.d.ts +121 -0
  174. package/dist/selfimprove/replay.d.ts.map +1 -0
  175. package/dist/selfimprove/replay.js +109 -0
  176. package/dist/selfimprove/replay.js.map +1 -0
  177. package/dist/selfimprove/run-loop.d.ts +148 -0
  178. package/dist/selfimprove/run-loop.d.ts.map +1 -0
  179. package/dist/selfimprove/run-loop.js +240 -0
  180. package/dist/selfimprove/run-loop.js.map +1 -0
  181. package/dist/selfimprove/scenario.d.ts +145 -0
  182. package/dist/selfimprove/scenario.d.ts.map +1 -0
  183. package/dist/selfimprove/scenario.js +243 -0
  184. package/dist/selfimprove/scenario.js.map +1 -0
  185. package/dist/sentient/daemon-entry.js +5 -0
  186. package/dist/sentient/daemon-entry.js.map +1 -1
  187. package/dist/sentient/daemon.d.ts.map +1 -1
  188. package/dist/sentient/daemon.js +19 -0
  189. package/dist/sentient/daemon.js.map +1 -1
  190. package/dist/sentient/hygiene-scan.d.ts.map +1 -1
  191. package/dist/sentient/hygiene-scan.js +14 -6
  192. package/dist/sentient/hygiene-scan.js.map +1 -1
  193. package/dist/sessions/briefing.d.ts.map +1 -1
  194. package/dist/sessions/briefing.js +13 -9
  195. package/dist/sessions/briefing.js.map +1 -1
  196. package/dist/sessions/connection-session-handle.d.ts +161 -0
  197. package/dist/sessions/connection-session-handle.d.ts.map +1 -0
  198. package/dist/sessions/connection-session-handle.js +168 -0
  199. package/dist/sessions/connection-session-handle.js.map +1 -0
  200. package/dist/sessions/handoff.d.ts.map +1 -1
  201. package/dist/sessions/handoff.js +9 -0
  202. package/dist/sessions/handoff.js.map +1 -1
  203. package/dist/sessions/index.d.ts +4 -1
  204. package/dist/sessions/index.d.ts.map +1 -1
  205. package/dist/sessions/index.js +31 -1
  206. package/dist/sessions/index.js.map +1 -1
  207. package/dist/sessions/session-id.d.ts +34 -0
  208. package/dist/sessions/session-id.d.ts.map +1 -1
  209. package/dist/sessions/session-id.js +37 -0
  210. package/dist/sessions/session-id.js.map +1 -1
  211. package/dist/sessions/session-manifest-mirror.d.ts +115 -0
  212. package/dist/sessions/session-manifest-mirror.d.ts.map +1 -0
  213. package/dist/sessions/session-manifest-mirror.js +250 -0
  214. package/dist/sessions/session-manifest-mirror.js.map +1 -0
  215. package/dist/sessions/session-switch.d.ts.map +1 -1
  216. package/dist/sessions/session-switch.js +5 -2
  217. package/dist/sessions/session-switch.js.map +1 -1
  218. package/dist/store/converters.d.ts.map +1 -1
  219. package/dist/store/converters.js +2 -0
  220. package/dist/store/converters.js.map +1 -1
  221. package/dist/store/db-helpers.d.ts.map +1 -1
  222. package/dist/store/db-helpers.js +2 -0
  223. package/dist/store/db-helpers.js.map +1 -1
  224. package/dist/store/dual-scope-db.d.ts.map +1 -1
  225. package/dist/store/dual-scope-db.js +87 -47
  226. package/dist/store/dual-scope-db.js.map +1 -1
  227. package/dist/store/pi-session-store.d.ts +151 -0
  228. package/dist/store/pi-session-store.d.ts.map +1 -0
  229. package/dist/store/pi-session-store.js +166 -0
  230. package/dist/store/pi-session-store.js.map +1 -0
  231. package/dist/store/safety-data-accessor.d.ts +1 -0
  232. package/dist/store/safety-data-accessor.d.ts.map +1 -1
  233. package/dist/store/safety-data-accessor.js +5 -0
  234. package/dist/store/safety-data-accessor.js.map +1 -1
  235. package/dist/store/schema/cleo-global/accounts.d.ts +357 -0
  236. package/dist/store/schema/cleo-global/accounts.d.ts.map +1 -0
  237. package/dist/store/schema/cleo-global/accounts.js +136 -0
  238. package/dist/store/schema/cleo-global/accounts.js.map +1 -0
  239. package/dist/store/schema/cleo-global/index.d.ts +2 -0
  240. package/dist/store/schema/cleo-global/index.d.ts.map +1 -1
  241. package/dist/store/schema/cleo-global/index.js +2 -0
  242. package/dist/store/schema/cleo-global/index.js.map +1 -1
  243. package/dist/store/schema/cleo-global/session-manifest.d.ts +217 -0
  244. package/dist/store/schema/cleo-global/session-manifest.d.ts.map +1 -0
  245. package/dist/store/schema/cleo-global/session-manifest.js +99 -0
  246. package/dist/store/schema/cleo-global/session-manifest.js.map +1 -0
  247. package/dist/store/schema/cleo-project/tasks-core.d.ts +16 -0
  248. package/dist/store/schema/cleo-project/tasks-core.d.ts.map +1 -1
  249. package/dist/store/schema/cleo-project/tasks-core.js +14 -0
  250. package/dist/store/schema/cleo-project/tasks-core.js.map +1 -1
  251. package/dist/store/schema/tasks.d.ts +16 -0
  252. package/dist/store/schema/tasks.d.ts.map +1 -1
  253. package/dist/store/schema/tasks.js +10 -0
  254. package/dist/store/schema/tasks.js.map +1 -1
  255. package/dist/store/selfimprove-dhq-schema.d.ts +284 -0
  256. package/dist/store/selfimprove-dhq-schema.d.ts.map +1 -0
  257. package/dist/store/selfimprove-dhq-schema.js +128 -0
  258. package/dist/store/selfimprove-dhq-schema.js.map +1 -0
  259. package/dist/store/selfimprove-dhq-store.d.ts +175 -0
  260. package/dist/store/selfimprove-dhq-store.d.ts.map +1 -0
  261. package/dist/store/selfimprove-dhq-store.js +182 -0
  262. package/dist/store/selfimprove-dhq-store.js.map +1 -0
  263. package/dist/store/session-store.d.ts +52 -13
  264. package/dist/store/session-store.d.ts.map +1 -1
  265. package/dist/store/session-store.js +71 -13
  266. package/dist/store/session-store.js.map +1 -1
  267. package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
  268. package/dist/store/sqlite-data-accessor.js +7 -0
  269. package/dist/store/sqlite-data-accessor.js.map +1 -1
  270. package/dist/store/umbrella-data-accessor.d.ts +1 -0
  271. package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
  272. package/dist/store/umbrella-data-accessor.js +5 -0
  273. package/dist/store/umbrella-data-accessor.js.map +1 -1
  274. package/dist/store/validation-schemas.d.ts +32 -0
  275. package/dist/store/validation-schemas.d.ts.map +1 -1
  276. package/dist/store/writer-lease-schema.d.ts +392 -0
  277. package/dist/store/writer-lease-schema.d.ts.map +1 -0
  278. package/dist/store/writer-lease-schema.js +142 -0
  279. package/dist/store/writer-lease-schema.js.map +1 -0
  280. package/dist/store/writer-lease.d.ts +368 -0
  281. package/dist/store/writer-lease.d.ts.map +1 -0
  282. package/dist/store/writer-lease.js +1002 -0
  283. package/dist/store/writer-lease.js.map +1 -0
  284. package/dist/tasks/backfill-child-projections.d.ts.map +1 -1
  285. package/dist/tasks/backfill-child-projections.js +14 -9
  286. package/dist/tasks/backfill-child-projections.js.map +1 -1
  287. package/dist/tasks/complete.d.ts.map +1 -1
  288. package/dist/tasks/complete.js +7 -10
  289. package/dist/tasks/complete.js.map +1 -1
  290. package/dist/tasks/duplicate-detector.d.ts.map +1 -1
  291. package/dist/tasks/duplicate-detector.js +14 -7
  292. package/dist/tasks/duplicate-detector.js.map +1 -1
  293. package/dist/telemetry/index.d.ts.map +1 -1
  294. package/dist/telemetry/index.js +10 -4
  295. package/dist/telemetry/index.js.map +1 -1
  296. package/dist/tools/agent-registry.d.ts +250 -0
  297. package/dist/tools/agent-registry.d.ts.map +1 -0
  298. package/dist/tools/agent-registry.js +292 -0
  299. package/dist/tools/agent-registry.js.map +1 -0
  300. package/dist/tools/agent-tool-families.d.ts +107 -0
  301. package/dist/tools/agent-tool-families.d.ts.map +1 -0
  302. package/dist/tools/agent-tool-families.js +527 -0
  303. package/dist/tools/agent-tool-families.js.map +1 -0
  304. package/dist/tools/browser-driver.d.ts +183 -0
  305. package/dist/tools/browser-driver.d.ts.map +1 -0
  306. package/dist/tools/browser-driver.js +242 -0
  307. package/dist/tools/browser-driver.js.map +1 -0
  308. package/dist/tools/builtin-agent-tools.d.ts +36 -0
  309. package/dist/tools/builtin-agent-tools.d.ts.map +1 -0
  310. package/dist/tools/builtin-agent-tools.js +150 -0
  311. package/dist/tools/builtin-agent-tools.js.map +1 -0
  312. package/dist/tools/dispatch.d.ts +370 -0
  313. package/dist/tools/dispatch.d.ts.map +1 -0
  314. package/dist/tools/dispatch.js +505 -0
  315. package/dist/tools/dispatch.js.map +1 -0
  316. package/dist/tools/env-scrub.d.ts +93 -0
  317. package/dist/tools/env-scrub.d.ts.map +1 -0
  318. package/dist/tools/env-scrub.js +176 -0
  319. package/dist/tools/env-scrub.js.map +1 -0
  320. package/dist/tools/fs.d.ts +30 -0
  321. package/dist/tools/fs.d.ts.map +1 -1
  322. package/dist/tools/fs.js +55 -2
  323. package/dist/tools/fs.js.map +1 -1
  324. package/dist/tools/guard.d.ts +15 -0
  325. package/dist/tools/guard.d.ts.map +1 -1
  326. package/dist/tools/guard.js +49 -12
  327. package/dist/tools/guard.js.map +1 -1
  328. package/dist/tools/index.d.ts +10 -0
  329. package/dist/tools/index.d.ts.map +1 -1
  330. package/dist/tools/index.js +37 -0
  331. package/dist/tools/index.js.map +1 -1
  332. package/dist/tools/pty.d.ts +45 -0
  333. package/dist/tools/pty.d.ts.map +1 -0
  334. package/dist/tools/pty.js +166 -0
  335. package/dist/tools/pty.js.map +1 -0
  336. package/dist/tools/schema-gen.d.ts +57 -0
  337. package/dist/tools/schema-gen.d.ts.map +1 -0
  338. package/dist/tools/schema-gen.js +52 -0
  339. package/dist/tools/schema-gen.js.map +1 -0
  340. package/dist/tools/shell.d.ts +12 -0
  341. package/dist/tools/shell.d.ts.map +1 -1
  342. package/dist/tools/shell.js +14 -1
  343. package/dist/tools/shell.js.map +1 -1
  344. package/dist/tools/web-agent-tools.d.ts +72 -0
  345. package/dist/tools/web-agent-tools.d.ts.map +1 -0
  346. package/dist/tools/web-agent-tools.js +393 -0
  347. package/dist/tools/web-agent-tools.js.map +1 -0
  348. package/dist/tools/web-search-backends.d.ts +156 -0
  349. package/dist/tools/web-search-backends.d.ts.map +1 -0
  350. package/dist/tools/web-search-backends.js +290 -0
  351. package/dist/tools/web-search-backends.js.map +1 -0
  352. package/dist/validation/ops.d.ts +1 -15
  353. package/dist/validation/ops.d.ts.map +1 -1
  354. package/dist/validation/ops.js +0 -20
  355. package/dist/validation/ops.js.map +1 -1
  356. package/migrations/drizzle-cleo-global/20260607000000_t11891-writer-leases/migration.sql +55 -0
  357. package/migrations/drizzle-cleo-global/20260607010000_t11639-session-manifest/migration.sql +43 -0
  358. package/migrations/drizzle-cleo-global/20260608000000_t11899-pi-session-tree/migration.sql +52 -0
  359. package/migrations/drizzle-cleo-global/20260608010000_t11709-accounts-credential-pool/migration.sql +72 -0
  360. package/migrations/drizzle-cleo-global/20260608020000_t11889-selfimprove-dhq/migration.sql +64 -0
  361. package/migrations/drizzle-cleo-project/20260607000000_t11891-writer-leases/migration.sql +55 -0
  362. package/migrations/drizzle-cleo-project/20260607010000_t11639-session-parent/migration.sql +22 -0
  363. package/migrations/drizzle-cleo-project/20260608000000_t11899-pi-session-tree/migration.sql +52 -0
  364. package/migrations/drizzle-cleo-project/20260608020000_t11889-selfimprove-dhq/migration.sql +64 -0
  365. package/package.json +15 -13
  366. package/dist/lifecycle/chain-composition.d.ts +0 -30
  367. package/dist/lifecycle/chain-composition.d.ts.map +0 -1
  368. package/dist/lifecycle/chain-composition.js +0 -152
  369. package/dist/lifecycle/chain-composition.js.map +0 -1
  370. package/dist/lifecycle/chain-store.d.ts +0 -70
  371. package/dist/lifecycle/chain-store.d.ts.map +0 -1
  372. package/dist/lifecycle/chain-store.js +0 -246
  373. package/dist/lifecycle/chain-store.js.map +0 -1
  374. package/dist/lifecycle/default-chain.d.ts +0 -39
  375. package/dist/lifecycle/default-chain.d.ts.map +0 -1
  376. package/dist/lifecycle/default-chain.js +0 -176
  377. package/dist/lifecycle/default-chain.js.map +0 -1
  378. package/dist/lifecycle/tessera-engine.d.ts +0 -48
  379. package/dist/lifecycle/tessera-engine.d.ts.map +0 -1
  380. package/dist/lifecycle/tessera-engine.js +0 -249
  381. package/dist/lifecycle/tessera-engine.js.map +0 -1
  382. package/dist/validation/chain-validation.d.ts +0 -43
  383. package/dist/validation/chain-validation.d.ts.map +0 -1
  384. package/dist/validation/chain-validation.js +0 -146
  385. package/dist/validation/chain-validation.js.map +0 -1
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Pi ↔ dispatch-engine bridge (T1740 · AC6 · epic T11456).
3
+ *
4
+ * Closes the agent tool-call loop for the in-process Pi runner. Pi's agent loop
5
+ * executes a tool the model emits by calling the `execute(toolCallId, params,
6
+ * signal)` method of the matching `AgentTool` it finds on `AgentContext.tools`.
7
+ * Before T1740 the Pi adapter advertised the registry's tool SCHEMAS to the
8
+ * model (`pi-stream-fn.ts` → `SendOptions.tools`) but supplied NO executables —
9
+ * so a model tool-call had nothing to run and the loop could only stream text.
10
+ *
11
+ * {@link buildPiAgentTools} projects the {@link AgentToolRegistry} into the
12
+ * `AgentTool[]` the loop needs, binding each tool's `execute` body to the T1740
13
+ * {@link ToolDispatchEngine}. When the model emits a tool call, Pi invokes the
14
+ * bound `execute`, which runs the call THROUGH the dispatch engine — lookup +
15
+ * Zod-validate + availability + budget + guarded execution + LLM-safe
16
+ * formatting — and returns the classified result as an `AgentToolResult` Pi
17
+ * feeds back to the model as a `tool_result`. That is the closed loop:
18
+ *
19
+ * model tool-call → Pi AgentTool.execute → ToolDispatchEngine.dispatch →
20
+ * GuardedToolSurface side effect → formatted result → back to the model.
21
+ *
22
+ * ## Boundary cleanliness
23
+ *
24
+ * - **Gate-11** — this module defines NO atomic tool primitive; it CONSUMES the
25
+ * frozen registry (`toOpenAITools`-shaped schemas) and the dispatch engine.
26
+ * - **Gate-13** — no LLM resolution / transport / client construction here; the
27
+ * only LLM route stays in {@link createPiStreamFn}. Tool execution is pure
28
+ * side-effect dispatch through the guard.
29
+ * - **Gate-10** — the Pi `AgentTool.parameters` is a TypeBox `TSchema`; the
30
+ * registry carries Zod. We convert via the shared {@link zodSchemaToOpenAITool}
31
+ * generator (Zod v4 native `z.toJSONSchema`) and pass the resulting JSON-Schema
32
+ * object through as the (structurally-compatible) `parameters` WITHOUT a
33
+ * typebox value-import, matching `pi-stream-fn.ts`'s quarantine.
34
+ *
35
+ * @task T1740
36
+ * @epic T11456
37
+ * @see ../../tools/dispatch.js — the dispatch engine this binds the loop to
38
+ * @see ./pi-stream-fn.js — the sibling that advertises the same tools' schemas
39
+ */
40
+ import { getLogger } from '../../logger.js';
41
+ import { zodSchemaToOpenAITool } from '../../tools/schema-gen.js';
42
+ const logger = getLogger('pi-tool-bridge');
43
+ /**
44
+ * Project an {@link AgentToolRegistry} into the `AgentTool[]` the Pi loop
45
+ * executes, binding every tool's `execute` to the shared {@link
46
+ * ToolDispatchEngine} (AC6).
47
+ *
48
+ * One {@link ToolDispatchEngine} instance is shared across all returned tools so
49
+ * the run-scoped budget (call count / time ceilings) is enforced ACROSS the
50
+ * whole turn, not per tool. Each `execute`:
51
+ * 1. wraps Pi's `(toolCallId, params)` into a {@link ToolCall};
52
+ * 2. dispatches it through the engine (validate → availability → budget →
53
+ * guarded execution → format);
54
+ * 3. returns the formatted content as an `AgentToolResult` Pi feeds back.
55
+ *
56
+ * @param engine - The dispatch engine (carries registry + guard + budget).
57
+ * @returns The `AgentTool[]` to assign to `AgentContext.tools`.
58
+ */
59
+ export function buildPiAgentTools(engine, registry) {
60
+ return registry.list().map((descriptor) => {
61
+ // Reuse the SINGLE shared schema generator so the bridge's advertised schema
62
+ // is byte-identical to what `pi-stream-fn.ts` puts on the wire (DRY, Gate-10
63
+ // — Zod → JSON-Schema, no typebox value-import).
64
+ const { inputSchema } = zodSchemaToOpenAITool({
65
+ name: descriptor.name,
66
+ description: descriptor.description,
67
+ parameters: descriptor.parameters,
68
+ });
69
+ return {
70
+ name: descriptor.name,
71
+ description: descriptor.description,
72
+ parameters: inputSchema,
73
+ label: descriptor.name,
74
+ async execute(toolCallId, params, signal) {
75
+ const call = {
76
+ id: toolCallId,
77
+ name: descriptor.name,
78
+ // Pi passes the schema-validated params object; normalize a non-object
79
+ // to an empty record so the engine's own re-validation runs cleanly.
80
+ arguments: isRecord(params) ? params : {},
81
+ };
82
+ const result = await engine.dispatch(call, signal);
83
+ if (!result.ok) {
84
+ logger.debug({ tool: descriptor.name, kind: result.kind, code: result.code }, 'pi tool dispatch failed (contained)');
85
+ }
86
+ return toAgentToolResult(result);
87
+ },
88
+ };
89
+ });
90
+ }
91
+ /**
92
+ * Convert a {@link ToolDispatchResult} into the {@link PiBridgeToolResult} the
93
+ * loop reads. Success → the `display` body; failure → the redacted, classified
94
+ * `[CODE] message` body. Either way it is a normal (non-throwing) result so the
95
+ * loop continues — Pi's contract is that a tool encodes failure in its result,
96
+ * not by throwing.
97
+ *
98
+ * @param result - The dispatch outcome.
99
+ * @returns The Pi-shaped tool result.
100
+ */
101
+ function toAgentToolResult(result) {
102
+ const text = result.ok
103
+ ? result.display
104
+ : `[${result.code}] ${result.message}${formatIssues(result)}`;
105
+ return { content: [{ type: 'text', text }], details: result };
106
+ }
107
+ /** Append flattened arg-validation issues to a failure body, when present. */
108
+ function formatIssues(result) {
109
+ if (!result.issues || result.issues.length === 0)
110
+ return '';
111
+ return `\n${result.issues.map((i) => `- ${i.path ? `${i.path}: ` : ''}${i.message}`).join('\n')}`;
112
+ }
113
+ /** Narrow an unknown to a plain record (Pi may hand a non-object on edge cases). */
114
+ function isRecord(value) {
115
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
116
+ }
117
+ //# sourceMappingURL=pi-tool-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-tool-bridge.js","sourceRoot":"","sources":["../../../src/llm/pi/pi-tool-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,MAAM,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAAC;AAyC3C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAA0B,EAC1B,QAA2B;IAE3B,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACxC,6EAA6E;QAC7E,6EAA6E;QAC7E,iDAAiD;QACjD,MAAM,EAAE,WAAW,EAAE,GAAG,qBAAqB,CAAC;YAC5C,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,WAAW,EAAE,UAAU,CAAC,WAAW;YACnC,UAAU,EAAE,UAAU,CAAC,UAAU;SAClC,CAAC,CAAC;QACH,OAAO;YACL,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,WAAW,EAAE,UAAU,CAAC,WAAW;YACnC,UAAU,EAAE,WAAW;YACvB,KAAK,EAAE,UAAU,CAAC,IAAI;YACtB,KAAK,CAAC,OAAO,CACX,UAAkB,EAClB,MAAe,EACf,MAAoB;gBAEpB,MAAM,IAAI,GAAa;oBACrB,EAAE,EAAE,UAAU;oBACd,IAAI,EAAE,UAAU,CAAC,IAAI;oBACrB,uEAAuE;oBACvE,qEAAqE;oBACrE,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;iBAC1C,CAAC;gBACF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACnD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,CACV,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAC/D,qCAAqC,CACtC,CAAC;gBACJ,CAAC;gBACD,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,iBAAiB,CAAC,MAA0B;IACnD,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE;QACpB,CAAC,CAAC,MAAM,CAAC,OAAO;QAChB,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;IAChE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAChE,CAAC;AAED,8EAA8E;AAC9E,SAAS,YAAY,CAAC,MAAkD;IACtE,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5D,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACpG,CAAC;AAED,oFAAoF;AACpF,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Core-internal Pi adapter types (T11761 · S2 · T11898).
3
+ *
4
+ * These types are the in-process contract between {@link createPiStreamFn} and
5
+ * {@link PiAgentAdapter}. They are deliberately **core-internal** — NOT promoted
6
+ * to `@cleocode/contracts` (Gate-4 Contracts Fan-Out: a type imported by >2
7
+ * packages must move to contracts; these are imported only within
8
+ * `core/src/llm/pi/`, so they stay here per YAGNI). The package barrel re-exports
9
+ * ONLY `createPiSkillRunner` (everything else, including these types, is internal).
10
+ *
11
+ * @epic T10403
12
+ * @task T11761
13
+ * @task T11898
14
+ */
15
+ import type { SystemOfUseLabel } from '@cleocode/contracts';
16
+ /**
17
+ * Run context handed to the Pi adapter + streamFn for a single agent run.
18
+ *
19
+ * Carries the resolution chokepoint key ({@link system}) and the daemon-stamped
20
+ * identity (NEVER minted by the adapter — read from env via the session-id
21
+ * resolvers). The adapter runs with ZERO authority: it resolves its LLM through
22
+ * `system`, never opens a DB writer, and never self-mints a session id.
23
+ */
24
+ export interface PiAgentRunContext {
25
+ /**
26
+ * Semantic system-of-use label → role → resolved LLM, via the E9
27
+ * {@link import('../system-resolver.js').resolveLLMForSystem} chokepoint
28
+ * (e.g. `'task-executor'`).
29
+ */
30
+ readonly system: SystemOfUseLabel;
31
+ /** Daemon-stamped session identity (read from `CLEO_SESSION_ID`, NEVER minted). */
32
+ readonly sessionId: string;
33
+ /** Daemon-stamped agent id (`CLEO_AGENT_ID`), or `null` when un-stamped. */
34
+ readonly agentId: string | null;
35
+ /** Parent session id (`CLEO_PARENT_SESSION_ID`), or `null` at the fork root. */
36
+ readonly parentSessionId: string | null;
37
+ /** Project root for config + credential resolution. Defaults to `process.cwd()`. */
38
+ readonly projectRoot?: string;
39
+ /** Abort propagation into Pi's agent loop. */
40
+ readonly signal?: AbortSignal;
41
+ }
42
+ /**
43
+ * Terminal result of a single {@link PiAgentAdapter.run}.
44
+ *
45
+ * `output` carries the aggregated assistant text + any structured bindings, in
46
+ * the shape the `SkillRunner` slot projects onto a `SkillExecuteResult`.
47
+ */
48
+ export interface PiAgentResult {
49
+ /** Whether the agent run succeeded or failed. */
50
+ readonly status: 'success' | 'failure';
51
+ /** Aggregated terminal output (assistant text + structured bindings). */
52
+ readonly output: Readonly<Record<string, unknown>>;
53
+ /** Human-readable failure reason; present iff `status === 'failure'`. */
54
+ readonly error?: string;
55
+ }
56
+ //# sourceMappingURL=pi-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-types.d.ts","sourceRoot":"","sources":["../../../src/llm/pi/pi-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gFAAgF;IAChF,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IACvC,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Core-internal Pi adapter types (T11761 · S2 · T11898).
3
+ *
4
+ * These types are the in-process contract between {@link createPiStreamFn} and
5
+ * {@link PiAgentAdapter}. They are deliberately **core-internal** — NOT promoted
6
+ * to `@cleocode/contracts` (Gate-4 Contracts Fan-Out: a type imported by >2
7
+ * packages must move to contracts; these are imported only within
8
+ * `core/src/llm/pi/`, so they stay here per YAGNI). The package barrel re-exports
9
+ * ONLY `createPiSkillRunner` (everything else, including these types, is internal).
10
+ *
11
+ * @epic T10403
12
+ * @task T11761
13
+ * @task T11898
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=pi-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-types.js","sourceRoot":"","sources":["../../../src/llm/pi/pi-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Per-run {@link PiExecutionEnv} selector + CI process-isolation fallback
3
+ * (T11910 · T11888-C · P5 Gondolin · epic T11599).
4
+ *
5
+ * The self-improvement loop wants ONE swap point that picks the strongest
6
+ * available confinement backend for a run and SILENTLY DEGRADES when the stronger
7
+ * one is unavailable — never erroring, never coupling the caller to whether a VM
8
+ * booted. That is this module:
9
+ *
10
+ * - When `backend: 'gondolin'` is requested AND the Gondolin sandbox is available
11
+ * (the optional `@earendil-works/gondolin` package loads AND `/dev/kvm` exists
12
+ * AND a working `qemu-system-x86_64` is on `PATH` — the AND-gate of
13
+ * {@link import('./gondolin-loader.js').isGondolinAvailable}), the selector boots
14
+ * a micro-VM-backed {@link import('./pi-gondolin-env.js').GondolinExecutionEnv}
15
+ * (confinement = the VM boundary itself; guest has ZERO host authority).
16
+ * - OTHERWISE — `backend: 'in-process'`, OR `'gondolin'` requested on a box where
17
+ * the package / `/dev/kvm` / QEMU is absent (the CI + most-developer-machines
18
+ * case) — it returns the always-available in-process deny-first
19
+ * {@link import('./pi-execution-env.js').GuardedExecutionEnv} (`ToolGuard` +
20
+ * workspace boundary). The loop runs IDENTICALLY over either backend (the
21
+ * `PiExecutionEnv` contract is byte-for-byte identical), just without VM
22
+ * isolation in the fallback.
23
+ *
24
+ * So in CI — gondolin uninstalled AND `/dev/kvm`/QEMU usually absent —
25
+ * `isGondolinAvailable()` is `false`, the selector returns the in-process env, and
26
+ * the suite stays green with ZERO VM infra. The degradation is structural: a box
27
+ * that requested the VM but lacks the infra gets the guarded fallback, not an
28
+ * error.
29
+ *
30
+ * Optional-dep discipline (D11142): this module imports ONLY sibling Pi modules
31
+ * (`./gondolin-loader.js`, `./pi-gondolin-env.js`, `./pi-execution-env.js`). It has
32
+ * NO `import type` from `@earendil-works/gondolin` — the gondolin package is loaded
33
+ * lazily (and ONLY when chosen) inside `createGondolinExecutionEnv`. `core` builds
34
+ * + all non-gondolin tests pass with gondolin ABSENT, and this module is
35
+ * import-time side-effect-free (no top-level VM boot, no host probe).
36
+ *
37
+ * Scope (T11888-C): this is the SELECTOR ONLY. It does NOT wire the
38
+ * `pi-agent-adapter.ts` env seam (a separate follow-up) — it is the single
39
+ * function the loop calls to obtain a per-run env.
40
+ *
41
+ * @epic T11599
42
+ * @task T11910
43
+ * @see ./gondolin-loader.js — the optional-dep availability probe (`isGondolinAvailable`)
44
+ * @see ./pi-gondolin-env.js — the VM-backed backend booted when available
45
+ * @see ./pi-execution-env.js — the in-process `GuardedExecutionEnv` fallback
46
+ */
47
+ import type { ToolGuard } from '../../tools/guard.js';
48
+ import { type PiExecutionEnv } from './pi-execution-env.js';
49
+ import { type CreateGondolinExecutionEnvOptions } from './pi-gondolin-env.js';
50
+ /**
51
+ * Which confinement backend a run REQUESTS. `'gondolin'` is a PREFERENCE, not a
52
+ * guarantee — when the VM infra is absent the selector degrades to `'in-process'`
53
+ * (the guarded fallback). `'in-process'` always resolves to the in-process
54
+ * {@link import('./pi-execution-env.js').GuardedExecutionEnv} (no VM probe at all).
55
+ */
56
+ export type ExecutionEnvBackend = 'gondolin' | 'in-process';
57
+ /**
58
+ * Options for {@link resolveExecutionEnv}. The `guard` + `workspaceRoot` pair is
59
+ * ALWAYS required because they back the in-process fallback (the guarded env that
60
+ * runs when the VM is unavailable or not requested). The VM-only fields
61
+ * (`seededCopyDir`, `allowedHosts`, `vaultSecrets`, `memory`, `env`) are consumed
62
+ * ONLY when a Gondolin VM is actually booted.
63
+ */
64
+ export interface ResolveExecutionEnvOptions {
65
+ /**
66
+ * The confinement backend this run PREFERS. `'gondolin'` boots a micro-VM when
67
+ * available and degrades to the guarded env otherwise; `'in-process'` always
68
+ * resolves to the guarded env.
69
+ */
70
+ readonly backend: ExecutionEnvBackend;
71
+ /**
72
+ * The deny-first guard surface backing the in-process fallback. REQUIRED even
73
+ * when `backend: 'gondolin'` — it is what the selector returns when the VM is
74
+ * unavailable. Must be an `enforce`-mode guard (the fallback factory asserts it).
75
+ */
76
+ readonly guard: ToolGuard;
77
+ /**
78
+ * The absolute workspace root the in-process fallback confines every fs path
79
+ * under. Used ONLY by the guarded fallback (the VM confines to its own
80
+ * `/workspace` mount).
81
+ */
82
+ readonly workspaceRoot: string;
83
+ /**
84
+ * The disposable seeded-copy host directory mounted RW at `/workspace` inside
85
+ * the guest. REQUIRED when a VM is actually booted (`backend: 'gondolin'` AND
86
+ * available); MUST be a `VACUUM INTO` snapshot dir, NEVER a path containing the
87
+ * live `.cleo/tasks.db` / `.cleo/brain.db`. Ignored by the fallback.
88
+ */
89
+ readonly seededCopyDir?: string;
90
+ /**
91
+ * Outbound host allowlist forwarded to the VM's egress hooks. Defaults to `[]`
92
+ * (DENY ALL) inside the VM factory when omitted. Ignored by the fallback.
93
+ */
94
+ readonly allowedHosts?: readonly string[];
95
+ /**
96
+ * Host-side secret injections for the VM's egress proxy (the guest only ever
97
+ * sees each entry's `placeholder`). Ignored by the fallback.
98
+ */
99
+ readonly vaultSecrets?: CreateGondolinExecutionEnvOptions['vaultSecrets'];
100
+ /**
101
+ * Guest memory bound (e.g. `"1G"`) for a booted VM. Defaults inside the VM
102
+ * factory. Ignored by the fallback.
103
+ */
104
+ readonly memory?: string;
105
+ /**
106
+ * Guest environment — the ONLY env a booted VM's guest sees (host `process.env`
107
+ * is NEVER inherited). Ignored by the fallback.
108
+ */
109
+ readonly env?: Readonly<Record<string, string>>;
110
+ }
111
+ /**
112
+ * Injectable seams for {@link resolveExecutionEnv}.
113
+ *
114
+ * EXPORTED FOR TESTS ONLY — lets the selector matrix test simulate
115
+ * "VM requested + available" (a mocked `isAvailable` returning `true` + a mocked
116
+ * `createGondolin` returning a fake env) and "VM requested + unavailable"
117
+ * (`isAvailable` returning `false`) WITHOUT touching the module graph or launching
118
+ * a real QEMU VM. In production both default to the real loader probe + the real
119
+ * VM factory.
120
+ *
121
+ * @internal
122
+ */
123
+ export interface ResolveExecutionEnvSeams {
124
+ /**
125
+ * The availability probe. Defaults to the real
126
+ * {@link import('./gondolin-loader.js').isGondolinAvailable} (package + `/dev/kvm`
127
+ * + QEMU AND-gate).
128
+ */
129
+ readonly isAvailable?: () => Promise<boolean>;
130
+ /**
131
+ * The VM-backed env factory. Defaults to the real
132
+ * {@link import('./pi-gondolin-env.js').createGondolinExecutionEnv}.
133
+ */
134
+ readonly createGondolin?: (opts: CreateGondolinExecutionEnvOptions) => Promise<PiExecutionEnv>;
135
+ }
136
+ /**
137
+ * Thrown by {@link resolveExecutionEnv} when `backend: 'gondolin'` is requested,
138
+ * the VM is reported available, but no {@link ResolveExecutionEnvOptions.seededCopyDir}
139
+ * was supplied — a VM cannot boot without a disposable seeded-copy mount, and
140
+ * silently degrading to the in-process fallback here would HIDE a caller bug
141
+ * (the caller asked for the VM and the infra IS present). This is the ONE
142
+ * non-degrading failure: it signals a misconfiguration, not missing infra.
143
+ */
144
+ export declare class ExecutionEnvConfigError extends Error {
145
+ /** Machine-readable code. */
146
+ readonly code = "E_EXECUTION_ENV_CONFIG";
147
+ constructor(message: string);
148
+ }
149
+ /**
150
+ * Resolve the {@link PiExecutionEnv} a single self-improvement run should use,
151
+ * preferring the Gondolin micro-VM when requested AND available and SILENTLY
152
+ * DEGRADING to the in-process {@link import('./pi-execution-env.js').GuardedExecutionEnv}
153
+ * otherwise.
154
+ *
155
+ * Selection matrix:
156
+ *
157
+ * | `backend` | VM available? | Result |
158
+ * |----------------|---------------|-----------------------------------------|
159
+ * | `'gondolin'` | yes | `createGondolinExecutionEnv` (micro-VM) |
160
+ * | `'gondolin'` | no | `createGuardedExecutionEnv` (degrade) |
161
+ * | `'in-process'` | (not probed) | `createGuardedExecutionEnv` |
162
+ *
163
+ * The availability check (`package + /dev/kvm + QEMU`) is performed ONLY when
164
+ * `backend === 'gondolin'`, so an `'in-process'` request never probes the host or
165
+ * touches the optional package. Degradation NEVER throws — the one exception is a
166
+ * misconfiguration (`gondolin` requested + available but no `seededCopyDir`), which
167
+ * is a caller bug surfaced as {@link ExecutionEnvConfigError} rather than a hidden
168
+ * fallback.
169
+ *
170
+ * @param opts - The backend preference + the always-required guard/workspaceRoot
171
+ * fallback inputs + the VM-only mount/egress inputs.
172
+ * @param seams - Test-only overrides for the availability probe + VM factory
173
+ * (defaults are the real loader probe + the real VM factory). Production callers
174
+ * pass nothing.
175
+ * @returns A {@link PiExecutionEnv} — VM-backed when the sandbox booted, in-process
176
+ * guarded otherwise. The loop cannot tell the backends apart.
177
+ * @throws {ExecutionEnvConfigError} When the VM is requested AND available but no
178
+ * `seededCopyDir` was supplied.
179
+ *
180
+ * @example
181
+ * ```ts
182
+ * // Prefer the VM; degrades to the guarded env in CI (no /dev/kvm / QEMU).
183
+ * const env = await resolveExecutionEnv({
184
+ * backend: 'gondolin',
185
+ * guard, // enforce-mode ToolGuard (the fallback)
186
+ * workspaceRoot: projectRoot, // the fallback's confinement root
187
+ * seededCopyDir: snapshotDir, // the VM's only RW mount (disposable copy)
188
+ * });
189
+ * // ... drive Pi's loop over `env` ...
190
+ * await env.cleanup();
191
+ * ```
192
+ */
193
+ export declare function resolveExecutionEnv(opts: ResolveExecutionEnvOptions, seams?: ResolveExecutionEnvSeams): Promise<PiExecutionEnv>;
194
+ //# sourceMappingURL=resolve-execution-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-execution-env.d.ts","sourceRoot":"","sources":["../../../src/llm/pi/resolve-execution-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAA6B,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EACL,KAAK,iCAAiC,EAEvC,MAAM,sBAAsB,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,YAAY,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,iCAAiC,CAAC,cAAc,CAAC,CAAC;IAC1E;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACjD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,iCAAiC,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CAChG;AAED;;;;;;;GAOG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,4BAA4B;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,0BAA0B,EAChC,KAAK,GAAE,wBAA6B,GACnC,OAAO,CAAC,cAAc,CAAC,CAyBzB"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Per-run {@link PiExecutionEnv} selector + CI process-isolation fallback
3
+ * (T11910 · T11888-C · P5 Gondolin · epic T11599).
4
+ *
5
+ * The self-improvement loop wants ONE swap point that picks the strongest
6
+ * available confinement backend for a run and SILENTLY DEGRADES when the stronger
7
+ * one is unavailable — never erroring, never coupling the caller to whether a VM
8
+ * booted. That is this module:
9
+ *
10
+ * - When `backend: 'gondolin'` is requested AND the Gondolin sandbox is available
11
+ * (the optional `@earendil-works/gondolin` package loads AND `/dev/kvm` exists
12
+ * AND a working `qemu-system-x86_64` is on `PATH` — the AND-gate of
13
+ * {@link import('./gondolin-loader.js').isGondolinAvailable}), the selector boots
14
+ * a micro-VM-backed {@link import('./pi-gondolin-env.js').GondolinExecutionEnv}
15
+ * (confinement = the VM boundary itself; guest has ZERO host authority).
16
+ * - OTHERWISE — `backend: 'in-process'`, OR `'gondolin'` requested on a box where
17
+ * the package / `/dev/kvm` / QEMU is absent (the CI + most-developer-machines
18
+ * case) — it returns the always-available in-process deny-first
19
+ * {@link import('./pi-execution-env.js').GuardedExecutionEnv} (`ToolGuard` +
20
+ * workspace boundary). The loop runs IDENTICALLY over either backend (the
21
+ * `PiExecutionEnv` contract is byte-for-byte identical), just without VM
22
+ * isolation in the fallback.
23
+ *
24
+ * So in CI — gondolin uninstalled AND `/dev/kvm`/QEMU usually absent —
25
+ * `isGondolinAvailable()` is `false`, the selector returns the in-process env, and
26
+ * the suite stays green with ZERO VM infra. The degradation is structural: a box
27
+ * that requested the VM but lacks the infra gets the guarded fallback, not an
28
+ * error.
29
+ *
30
+ * Optional-dep discipline (D11142): this module imports ONLY sibling Pi modules
31
+ * (`./gondolin-loader.js`, `./pi-gondolin-env.js`, `./pi-execution-env.js`). It has
32
+ * NO `import type` from `@earendil-works/gondolin` — the gondolin package is loaded
33
+ * lazily (and ONLY when chosen) inside `createGondolinExecutionEnv`. `core` builds
34
+ * + all non-gondolin tests pass with gondolin ABSENT, and this module is
35
+ * import-time side-effect-free (no top-level VM boot, no host probe).
36
+ *
37
+ * Scope (T11888-C): this is the SELECTOR ONLY. It does NOT wire the
38
+ * `pi-agent-adapter.ts` env seam (a separate follow-up) — it is the single
39
+ * function the loop calls to obtain a per-run env.
40
+ *
41
+ * @epic T11599
42
+ * @task T11910
43
+ * @see ./gondolin-loader.js — the optional-dep availability probe (`isGondolinAvailable`)
44
+ * @see ./pi-gondolin-env.js — the VM-backed backend booted when available
45
+ * @see ./pi-execution-env.js — the in-process `GuardedExecutionEnv` fallback
46
+ */
47
+ import { isGondolinAvailable as realIsGondolinAvailable } from './gondolin-loader.js';
48
+ import { createGuardedExecutionEnv } from './pi-execution-env.js';
49
+ import { createGondolinExecutionEnv as realCreateGondolinExecutionEnv, } from './pi-gondolin-env.js';
50
+ /**
51
+ * Thrown by {@link resolveExecutionEnv} when `backend: 'gondolin'` is requested,
52
+ * the VM is reported available, but no {@link ResolveExecutionEnvOptions.seededCopyDir}
53
+ * was supplied — a VM cannot boot without a disposable seeded-copy mount, and
54
+ * silently degrading to the in-process fallback here would HIDE a caller bug
55
+ * (the caller asked for the VM and the infra IS present). This is the ONE
56
+ * non-degrading failure: it signals a misconfiguration, not missing infra.
57
+ */
58
+ export class ExecutionEnvConfigError extends Error {
59
+ /** Machine-readable code. */
60
+ code = 'E_EXECUTION_ENV_CONFIG';
61
+ constructor(message) {
62
+ super(message);
63
+ this.name = 'ExecutionEnvConfigError';
64
+ }
65
+ }
66
+ /**
67
+ * Resolve the {@link PiExecutionEnv} a single self-improvement run should use,
68
+ * preferring the Gondolin micro-VM when requested AND available and SILENTLY
69
+ * DEGRADING to the in-process {@link import('./pi-execution-env.js').GuardedExecutionEnv}
70
+ * otherwise.
71
+ *
72
+ * Selection matrix:
73
+ *
74
+ * | `backend` | VM available? | Result |
75
+ * |----------------|---------------|-----------------------------------------|
76
+ * | `'gondolin'` | yes | `createGondolinExecutionEnv` (micro-VM) |
77
+ * | `'gondolin'` | no | `createGuardedExecutionEnv` (degrade) |
78
+ * | `'in-process'` | (not probed) | `createGuardedExecutionEnv` |
79
+ *
80
+ * The availability check (`package + /dev/kvm + QEMU`) is performed ONLY when
81
+ * `backend === 'gondolin'`, so an `'in-process'` request never probes the host or
82
+ * touches the optional package. Degradation NEVER throws — the one exception is a
83
+ * misconfiguration (`gondolin` requested + available but no `seededCopyDir`), which
84
+ * is a caller bug surfaced as {@link ExecutionEnvConfigError} rather than a hidden
85
+ * fallback.
86
+ *
87
+ * @param opts - The backend preference + the always-required guard/workspaceRoot
88
+ * fallback inputs + the VM-only mount/egress inputs.
89
+ * @param seams - Test-only overrides for the availability probe + VM factory
90
+ * (defaults are the real loader probe + the real VM factory). Production callers
91
+ * pass nothing.
92
+ * @returns A {@link PiExecutionEnv} — VM-backed when the sandbox booted, in-process
93
+ * guarded otherwise. The loop cannot tell the backends apart.
94
+ * @throws {ExecutionEnvConfigError} When the VM is requested AND available but no
95
+ * `seededCopyDir` was supplied.
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * // Prefer the VM; degrades to the guarded env in CI (no /dev/kvm / QEMU).
100
+ * const env = await resolveExecutionEnv({
101
+ * backend: 'gondolin',
102
+ * guard, // enforce-mode ToolGuard (the fallback)
103
+ * workspaceRoot: projectRoot, // the fallback's confinement root
104
+ * seededCopyDir: snapshotDir, // the VM's only RW mount (disposable copy)
105
+ * });
106
+ * // ... drive Pi's loop over `env` ...
107
+ * await env.cleanup();
108
+ * ```
109
+ */
110
+ export async function resolveExecutionEnv(opts, seams = {}) {
111
+ const isAvailable = seams.isAvailable ?? realIsGondolinAvailable;
112
+ const createGondolin = seams.createGondolin ?? realCreateGondolinExecutionEnv;
113
+ if (opts.backend === 'gondolin' && (await isAvailable())) {
114
+ if (opts.seededCopyDir === undefined) {
115
+ throw new ExecutionEnvConfigError('backend "gondolin" is available but no seededCopyDir was supplied; ' +
116
+ 'a VM requires a disposable seeded-copy mount (VACUUM INTO snapshot) — ' +
117
+ 'live tasks.db/brain.db are NEVER mounted');
118
+ }
119
+ return createGondolin({
120
+ seededCopyDir: opts.seededCopyDir,
121
+ ...(opts.allowedHosts !== undefined ? { allowedHosts: opts.allowedHosts } : {}),
122
+ ...(opts.vaultSecrets !== undefined ? { vaultSecrets: opts.vaultSecrets } : {}),
123
+ ...(opts.memory !== undefined ? { memory: opts.memory } : {}),
124
+ ...(opts.env !== undefined ? { env: opts.env } : {}),
125
+ });
126
+ }
127
+ // Degrade (or honour `'in-process'`): the always-available in-process env. This
128
+ // is the CI / most-developer-machines path — no VM probe touched the host when
129
+ // backend was `'in-process'`; when it was `'gondolin'` the probe returned false.
130
+ return createGuardedExecutionEnv({ guard: opts.guard, workspaceRoot: opts.workspaceRoot });
131
+ }
132
+ //# sourceMappingURL=resolve-execution-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-execution-env.js","sourceRoot":"","sources":["../../../src/llm/pi/resolve-execution-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAGH,OAAO,EAAE,mBAAmB,IAAI,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,yBAAyB,EAAuB,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAEL,0BAA0B,IAAI,8BAA8B,GAC7D,MAAM,sBAAsB,CAAC;AA2F9B;;;;;;;GAOG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,6BAA6B;IACpB,IAAI,GAAG,wBAAwB,CAAC;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAgC,EAChC,QAAkC,EAAE;IAEpC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,uBAAuB,CAAC;IACjE,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,IAAI,8BAA8B,CAAC;IAE9E,IAAI,IAAI,CAAC,OAAO,KAAK,UAAU,IAAI,CAAC,MAAM,WAAW,EAAE,CAAC,EAAE,CAAC;QACzD,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,IAAI,uBAAuB,CAC/B,qEAAqE;gBACnE,wEAAwE;gBACxE,0CAA0C,CAC7C,CAAC;QACJ,CAAC;QACD,OAAO,cAAc,CAAC;YACpB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,GAAG,CAAC,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,GAAG,CAAC,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;IAED,gFAAgF;IAChF,+EAA+E;IAC/E,iFAAiF;IACjF,OAAO,yBAAyB,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;AAC7F,CAAC"}