@methodts/runtime 0.1.0

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 (537) hide show
  1. package/dist/__fixtures__/executor-fixtures.d.ts +10 -0
  2. package/dist/__fixtures__/executor-fixtures.d.ts.map +1 -0
  3. package/dist/__fixtures__/executor-fixtures.js +36 -0
  4. package/dist/__fixtures__/executor-fixtures.js.map +1 -0
  5. package/dist/architecture.test.d.ts +2 -0
  6. package/dist/architecture.test.d.ts.map +1 -0
  7. package/dist/architecture.test.js +143 -0
  8. package/dist/architecture.test.js.map +1 -0
  9. package/dist/config/cost-governor-config.d.ts +40 -0
  10. package/dist/config/cost-governor-config.d.ts.map +1 -0
  11. package/dist/config/cost-governor-config.js +48 -0
  12. package/dist/config/cost-governor-config.js.map +1 -0
  13. package/dist/config/index.d.ts +7 -0
  14. package/dist/config/index.d.ts.map +1 -0
  15. package/dist/config/index.js +6 -0
  16. package/dist/config/index.js.map +1 -0
  17. package/dist/config/sessions-config.d.ts +29 -0
  18. package/dist/config/sessions-config.d.ts.map +1 -0
  19. package/dist/config/sessions-config.js +37 -0
  20. package/dist/config/sessions-config.js.map +1 -0
  21. package/dist/config/strategies-config.d.ts +38 -0
  22. package/dist/config/strategies-config.d.ts.map +1 -0
  23. package/dist/config/strategies-config.js +41 -0
  24. package/dist/config/strategies-config.js.map +1 -0
  25. package/dist/cost-governor/backpressure-queue.d.ts +20 -0
  26. package/dist/cost-governor/backpressure-queue.d.ts.map +1 -0
  27. package/dist/cost-governor/backpressure-queue.js +78 -0
  28. package/dist/cost-governor/backpressure-queue.js.map +1 -0
  29. package/dist/cost-governor/backpressure-queue.test.d.ts +2 -0
  30. package/dist/cost-governor/backpressure-queue.test.d.ts.map +1 -0
  31. package/dist/cost-governor/backpressure-queue.test.js +48 -0
  32. package/dist/cost-governor/backpressure-queue.test.js.map +1 -0
  33. package/dist/cost-governor/cost-events.d.ts +65 -0
  34. package/dist/cost-governor/cost-events.d.ts.map +1 -0
  35. package/dist/cost-governor/cost-events.js +48 -0
  36. package/dist/cost-governor/cost-events.js.map +1 -0
  37. package/dist/cost-governor/cost-governor-app-id.test.d.ts +19 -0
  38. package/dist/cost-governor/cost-governor-app-id.test.d.ts.map +1 -0
  39. package/dist/cost-governor/cost-governor-app-id.test.js +201 -0
  40. package/dist/cost-governor/cost-governor-app-id.test.js.map +1 -0
  41. package/dist/cost-governor/cost-oracle-impl.d.ts +19 -0
  42. package/dist/cost-governor/cost-oracle-impl.d.ts.map +1 -0
  43. package/dist/cost-governor/cost-oracle-impl.js +52 -0
  44. package/dist/cost-governor/cost-oracle-impl.js.map +1 -0
  45. package/dist/cost-governor/estimator.d.ts +22 -0
  46. package/dist/cost-governor/estimator.d.ts.map +1 -0
  47. package/dist/cost-governor/estimator.js +119 -0
  48. package/dist/cost-governor/estimator.js.map +1 -0
  49. package/dist/cost-governor/estimator.test.d.ts +2 -0
  50. package/dist/cost-governor/estimator.test.d.ts.map +1 -0
  51. package/dist/cost-governor/estimator.test.js +141 -0
  52. package/dist/cost-governor/estimator.test.js.map +1 -0
  53. package/dist/cost-governor/index.d.ts +75 -0
  54. package/dist/cost-governor/index.d.ts.map +1 -0
  55. package/dist/cost-governor/index.js +120 -0
  56. package/dist/cost-governor/index.js.map +1 -0
  57. package/dist/cost-governor/observations-store.d.ts +49 -0
  58. package/dist/cost-governor/observations-store.d.ts.map +1 -0
  59. package/dist/cost-governor/observations-store.js +179 -0
  60. package/dist/cost-governor/observations-store.js.map +1 -0
  61. package/dist/cost-governor/observations-store.test.d.ts +2 -0
  62. package/dist/cost-governor/observations-store.test.d.ts.map +1 -0
  63. package/dist/cost-governor/observations-store.test.js +191 -0
  64. package/dist/cost-governor/observations-store.test.js.map +1 -0
  65. package/dist/cost-governor/percentile.d.ts +17 -0
  66. package/dist/cost-governor/percentile.d.ts.map +1 -0
  67. package/dist/cost-governor/percentile.js +33 -0
  68. package/dist/cost-governor/percentile.js.map +1 -0
  69. package/dist/cost-governor/percentile.test.d.ts +2 -0
  70. package/dist/cost-governor/percentile.test.d.ts.map +1 -0
  71. package/dist/cost-governor/percentile.test.js +46 -0
  72. package/dist/cost-governor/percentile.test.js.map +1 -0
  73. package/dist/cost-governor/rate-governor-impl.d.ts +73 -0
  74. package/dist/cost-governor/rate-governor-impl.d.ts.map +1 -0
  75. package/dist/cost-governor/rate-governor-impl.js +148 -0
  76. package/dist/cost-governor/rate-governor-impl.js.map +1 -0
  77. package/dist/cost-governor/signature-builder.d.ts +22 -0
  78. package/dist/cost-governor/signature-builder.d.ts.map +1 -0
  79. package/dist/cost-governor/signature-builder.js +43 -0
  80. package/dist/cost-governor/signature-builder.js.map +1 -0
  81. package/dist/cost-governor/signature-builder.test.d.ts +2 -0
  82. package/dist/cost-governor/signature-builder.test.d.ts.map +1 -0
  83. package/dist/cost-governor/signature-builder.test.js +58 -0
  84. package/dist/cost-governor/signature-builder.test.js.map +1 -0
  85. package/dist/cost-governor/token-bucket.d.ts +57 -0
  86. package/dist/cost-governor/token-bucket.d.ts.map +1 -0
  87. package/dist/cost-governor/token-bucket.js +109 -0
  88. package/dist/cost-governor/token-bucket.js.map +1 -0
  89. package/dist/cost-governor/token-bucket.test.d.ts +2 -0
  90. package/dist/cost-governor/token-bucket.test.d.ts.map +1 -0
  91. package/dist/cost-governor/token-bucket.test.js +67 -0
  92. package/dist/cost-governor/token-bucket.test.js.map +1 -0
  93. package/dist/dlq/cortex-dlq-observer.d.ts +22 -0
  94. package/dist/dlq/cortex-dlq-observer.d.ts.map +1 -0
  95. package/dist/dlq/cortex-dlq-observer.js +29 -0
  96. package/dist/dlq/cortex-dlq-observer.js.map +1 -0
  97. package/dist/dlq/dlq-observer.test.d.ts +8 -0
  98. package/dist/dlq/dlq-observer.test.d.ts.map +1 -0
  99. package/dist/dlq/dlq-observer.test.js +103 -0
  100. package/dist/dlq/dlq-observer.test.js.map +1 -0
  101. package/dist/dlq/index.d.ts +6 -0
  102. package/dist/dlq/index.d.ts.map +1 -0
  103. package/dist/dlq/index.js +6 -0
  104. package/dist/dlq/index.js.map +1 -0
  105. package/dist/event-bus/adapters.d.ts +50 -0
  106. package/dist/event-bus/adapters.d.ts.map +1 -0
  107. package/dist/event-bus/adapters.js +51 -0
  108. package/dist/event-bus/adapters.js.map +1 -0
  109. package/dist/event-bus/adapters.test.d.ts +5 -0
  110. package/dist/event-bus/adapters.test.d.ts.map +1 -0
  111. package/dist/event-bus/adapters.test.js +73 -0
  112. package/dist/event-bus/adapters.test.js.map +1 -0
  113. package/dist/event-bus/agent-event-adapter.d.ts +22 -0
  114. package/dist/event-bus/agent-event-adapter.d.ts.map +1 -0
  115. package/dist/event-bus/agent-event-adapter.js +49 -0
  116. package/dist/event-bus/agent-event-adapter.js.map +1 -0
  117. package/dist/event-bus/agent-event-adapter.test.d.ts +5 -0
  118. package/dist/event-bus/agent-event-adapter.test.d.ts.map +1 -0
  119. package/dist/event-bus/agent-event-adapter.test.js +170 -0
  120. package/dist/event-bus/agent-event-adapter.test.js.map +1 -0
  121. package/dist/event-bus/channel-sink.d.ts +71 -0
  122. package/dist/event-bus/channel-sink.d.ts.map +1 -0
  123. package/dist/event-bus/channel-sink.js +159 -0
  124. package/dist/event-bus/channel-sink.js.map +1 -0
  125. package/dist/event-bus/channel-sink.test.d.ts +5 -0
  126. package/dist/event-bus/channel-sink.test.d.ts.map +1 -0
  127. package/dist/event-bus/channel-sink.test.js +234 -0
  128. package/dist/event-bus/channel-sink.test.js.map +1 -0
  129. package/dist/event-bus/event-types.snapshot.test.d.ts +27 -0
  130. package/dist/event-bus/event-types.snapshot.test.d.ts.map +1 -0
  131. package/dist/event-bus/event-types.snapshot.test.js +165 -0
  132. package/dist/event-bus/event-types.snapshot.test.js.map +1 -0
  133. package/dist/event-bus/genesis-sink.d.ts +55 -0
  134. package/dist/event-bus/genesis-sink.d.ts.map +1 -0
  135. package/dist/event-bus/genesis-sink.js +141 -0
  136. package/dist/event-bus/genesis-sink.js.map +1 -0
  137. package/dist/event-bus/genesis-sink.test.d.ts +5 -0
  138. package/dist/event-bus/genesis-sink.test.d.ts.map +1 -0
  139. package/dist/event-bus/genesis-sink.test.js +160 -0
  140. package/dist/event-bus/genesis-sink.test.js.map +1 -0
  141. package/dist/event-bus/in-memory-event-bus.d.ts +60 -0
  142. package/dist/event-bus/in-memory-event-bus.d.ts.map +1 -0
  143. package/dist/event-bus/in-memory-event-bus.js +274 -0
  144. package/dist/event-bus/in-memory-event-bus.js.map +1 -0
  145. package/dist/event-bus/in-memory-event-bus.test.d.ts +5 -0
  146. package/dist/event-bus/in-memory-event-bus.test.d.ts.map +1 -0
  147. package/dist/event-bus/in-memory-event-bus.test.js +457 -0
  148. package/dist/event-bus/in-memory-event-bus.test.js.map +1 -0
  149. package/dist/event-bus/index.d.ts +22 -0
  150. package/dist/event-bus/index.d.ts.map +1 -0
  151. package/dist/event-bus/index.js +17 -0
  152. package/dist/event-bus/index.js.map +1 -0
  153. package/dist/event-bus/persistence-sink.d.ts +74 -0
  154. package/dist/event-bus/persistence-sink.d.ts.map +1 -0
  155. package/dist/event-bus/persistence-sink.js +193 -0
  156. package/dist/event-bus/persistence-sink.js.map +1 -0
  157. package/dist/event-bus/persistence-sink.test.d.ts +6 -0
  158. package/dist/event-bus/persistence-sink.test.d.ts.map +1 -0
  159. package/dist/event-bus/persistence-sink.test.js +319 -0
  160. package/dist/event-bus/persistence-sink.test.js.map +1 -0
  161. package/dist/event-bus/session-checkpoint-sink.d.ts +91 -0
  162. package/dist/event-bus/session-checkpoint-sink.d.ts.map +1 -0
  163. package/dist/event-bus/session-checkpoint-sink.js +107 -0
  164. package/dist/event-bus/session-checkpoint-sink.js.map +1 -0
  165. package/dist/event-bus/session-checkpoint-sink.test.d.ts +5 -0
  166. package/dist/event-bus/session-checkpoint-sink.test.d.ts.map +1 -0
  167. package/dist/event-bus/session-checkpoint-sink.test.js +215 -0
  168. package/dist/event-bus/session-checkpoint-sink.test.js.map +1 -0
  169. package/dist/event-bus/webhook-connector.d.ts +59 -0
  170. package/dist/event-bus/webhook-connector.d.ts.map +1 -0
  171. package/dist/event-bus/webhook-connector.js +191 -0
  172. package/dist/event-bus/webhook-connector.js.map +1 -0
  173. package/dist/event-bus/webhook-connector.test.d.ts +5 -0
  174. package/dist/event-bus/webhook-connector.test.d.ts.map +1 -0
  175. package/dist/event-bus/webhook-connector.test.js +214 -0
  176. package/dist/event-bus/webhook-connector.test.js.map +1 -0
  177. package/dist/executors/cortex-job-backed-executor.d.ts +137 -0
  178. package/dist/executors/cortex-job-backed-executor.d.ts.map +1 -0
  179. package/dist/executors/cortex-job-backed-executor.js +441 -0
  180. package/dist/executors/cortex-job-backed-executor.js.map +1 -0
  181. package/dist/executors/cortex-job-backed-executor.test.d.ts +13 -0
  182. package/dist/executors/cortex-job-backed-executor.test.d.ts.map +1 -0
  183. package/dist/executors/cortex-job-backed-executor.test.js +303 -0
  184. package/dist/executors/cortex-job-backed-executor.test.js.map +1 -0
  185. package/dist/executors/index.d.ts +9 -0
  186. package/dist/executors/index.d.ts.map +1 -0
  187. package/dist/executors/index.js +9 -0
  188. package/dist/executors/index.js.map +1 -0
  189. package/dist/index.d.ts +2 -0
  190. package/dist/index.d.ts.map +1 -0
  191. package/dist/index.js +13 -0
  192. package/dist/index.js.map +1 -0
  193. package/dist/ports/checkpoint-sink.d.ts +69 -0
  194. package/dist/ports/checkpoint-sink.d.ts.map +1 -0
  195. package/dist/ports/checkpoint-sink.js +16 -0
  196. package/dist/ports/checkpoint-sink.js.map +1 -0
  197. package/dist/ports/checkpoint.d.ts +68 -0
  198. package/dist/ports/checkpoint.d.ts.map +1 -0
  199. package/dist/ports/checkpoint.js +14 -0
  200. package/dist/ports/checkpoint.js.map +1 -0
  201. package/dist/ports/continuation-envelope-cross-app.test.d.ts +10 -0
  202. package/dist/ports/continuation-envelope-cross-app.test.d.ts.map +1 -0
  203. package/dist/ports/continuation-envelope-cross-app.test.js +95 -0
  204. package/dist/ports/continuation-envelope-cross-app.test.js.map +1 -0
  205. package/dist/ports/continuation-envelope.d.ts +199 -0
  206. package/dist/ports/continuation-envelope.d.ts.map +1 -0
  207. package/dist/ports/continuation-envelope.js +69 -0
  208. package/dist/ports/continuation-envelope.js.map +1 -0
  209. package/dist/ports/conversation.d.ts +64 -0
  210. package/dist/ports/conversation.d.ts.map +1 -0
  211. package/dist/ports/conversation.js +19 -0
  212. package/dist/ports/conversation.js.map +1 -0
  213. package/dist/ports/cost-oracle.d.ts +26 -0
  214. package/dist/ports/cost-oracle.d.ts.map +1 -0
  215. package/dist/ports/cost-oracle.js +9 -0
  216. package/dist/ports/cost-oracle.js.map +1 -0
  217. package/dist/ports/cross-app-invoker.d.ts +198 -0
  218. package/dist/ports/cross-app-invoker.d.ts.map +1 -0
  219. package/dist/ports/cross-app-invoker.js +157 -0
  220. package/dist/ports/cross-app-invoker.js.map +1 -0
  221. package/dist/ports/dlq-observer.d.ts +40 -0
  222. package/dist/ports/dlq-observer.d.ts.map +1 -0
  223. package/dist/ports/dlq-observer.js +20 -0
  224. package/dist/ports/dlq-observer.js.map +1 -0
  225. package/dist/ports/event-bus.d.ts +169 -0
  226. package/dist/ports/event-bus.d.ts.map +1 -0
  227. package/dist/ports/event-bus.js +20 -0
  228. package/dist/ports/event-bus.js.map +1 -0
  229. package/dist/ports/event-reader.d.ts +21 -0
  230. package/dist/ports/event-reader.d.ts.map +1 -0
  231. package/dist/ports/event-reader.js +12 -0
  232. package/dist/ports/event-reader.js.map +1 -0
  233. package/dist/ports/event-rotator.d.ts +39 -0
  234. package/dist/ports/event-rotator.d.ts.map +1 -0
  235. package/dist/ports/event-rotator.js +15 -0
  236. package/dist/ports/event-rotator.js.map +1 -0
  237. package/dist/ports/file-system.d.ts +48 -0
  238. package/dist/ports/file-system.d.ts.map +1 -0
  239. package/dist/ports/file-system.js +10 -0
  240. package/dist/ports/file-system.js.map +1 -0
  241. package/dist/ports/historical-observations.d.ts +39 -0
  242. package/dist/ports/historical-observations.d.ts.map +1 -0
  243. package/dist/ports/historical-observations.js +12 -0
  244. package/dist/ports/historical-observations.js.map +1 -0
  245. package/dist/ports/in-memory-source.d.ts +46 -0
  246. package/dist/ports/in-memory-source.d.ts.map +1 -0
  247. package/dist/ports/in-memory-source.js +69 -0
  248. package/dist/ports/in-memory-source.js.map +1 -0
  249. package/dist/ports/index.d.ts +32 -0
  250. package/dist/ports/index.d.ts.map +1 -0
  251. package/dist/ports/index.js +10 -0
  252. package/dist/ports/index.js.map +1 -0
  253. package/dist/ports/job-backed-executor.d.ts +139 -0
  254. package/dist/ports/job-backed-executor.d.ts.map +1 -0
  255. package/dist/ports/job-backed-executor.js +56 -0
  256. package/dist/ports/job-backed-executor.js.map +1 -0
  257. package/dist/ports/methodology-source.d.ts +95 -0
  258. package/dist/ports/methodology-source.d.ts.map +1 -0
  259. package/dist/ports/methodology-source.js +26 -0
  260. package/dist/ports/methodology-source.js.map +1 -0
  261. package/dist/ports/native-session-discovery.d.ts +20 -0
  262. package/dist/ports/native-session-discovery.d.ts.map +1 -0
  263. package/dist/ports/native-session-discovery.js +13 -0
  264. package/dist/ports/native-session-discovery.js.map +1 -0
  265. package/dist/ports/projection-store.d.ts +48 -0
  266. package/dist/ports/projection-store.d.ts.map +1 -0
  267. package/dist/ports/projection-store.js +17 -0
  268. package/dist/ports/projection-store.js.map +1 -0
  269. package/dist/ports/projection.d.ts +29 -0
  270. package/dist/ports/projection.d.ts.map +1 -0
  271. package/dist/ports/projection.js +13 -0
  272. package/dist/ports/projection.js.map +1 -0
  273. package/dist/ports/rate-governor.d.ts +17 -0
  274. package/dist/ports/rate-governor.d.ts.map +1 -0
  275. package/dist/ports/rate-governor.js +11 -0
  276. package/dist/ports/rate-governor.js.map +1 -0
  277. package/dist/ports/schedule-client.d.ts +29 -0
  278. package/dist/ports/schedule-client.d.ts.map +1 -0
  279. package/dist/ports/schedule-client.js +2 -0
  280. package/dist/ports/schedule-client.js.map +1 -0
  281. package/dist/ports/session-pool.d.ts +162 -0
  282. package/dist/ports/session-pool.d.ts.map +1 -0
  283. package/dist/ports/session-pool.js +21 -0
  284. package/dist/ports/session-pool.js.map +1 -0
  285. package/dist/ports/session-store-errors.d.ts +22 -0
  286. package/dist/ports/session-store-errors.d.ts.map +1 -0
  287. package/dist/ports/session-store-errors.js +29 -0
  288. package/dist/ports/session-store-errors.js.map +1 -0
  289. package/dist/ports/session-store-types.d.ts +132 -0
  290. package/dist/ports/session-store-types.d.ts.map +1 -0
  291. package/dist/ports/session-store-types.js +14 -0
  292. package/dist/ports/session-store-types.js.map +1 -0
  293. package/dist/ports/session-store.d.ts +69 -0
  294. package/dist/ports/session-store.d.ts.map +1 -0
  295. package/dist/ports/session-store.js +23 -0
  296. package/dist/ports/session-store.js.map +1 -0
  297. package/dist/ports/yaml-loader.d.ts +15 -0
  298. package/dist/ports/yaml-loader.d.ts.map +1 -0
  299. package/dist/ports/yaml-loader.js +13 -0
  300. package/dist/ports/yaml-loader.js.map +1 -0
  301. package/dist/scheduling/index.d.ts +6 -0
  302. package/dist/scheduling/index.d.ts.map +1 -0
  303. package/dist/scheduling/index.js +6 -0
  304. package/dist/scheduling/index.js.map +1 -0
  305. package/dist/scheduling/scheduled-pact.d.ts +97 -0
  306. package/dist/scheduling/scheduled-pact.d.ts.map +1 -0
  307. package/dist/scheduling/scheduled-pact.js +89 -0
  308. package/dist/scheduling/scheduled-pact.js.map +1 -0
  309. package/dist/sessions/__tests__/cognitive-modules.test.d.ts +10 -0
  310. package/dist/sessions/__tests__/cognitive-modules.test.d.ts.map +1 -0
  311. package/dist/sessions/__tests__/cognitive-modules.test.js +535 -0
  312. package/dist/sessions/__tests__/cognitive-modules.test.js.map +1 -0
  313. package/dist/sessions/__tests__/cognitive-provider.test.d.ts +13 -0
  314. package/dist/sessions/__tests__/cognitive-provider.test.d.ts.map +1 -0
  315. package/dist/sessions/__tests__/cognitive-provider.test.js +331 -0
  316. package/dist/sessions/__tests__/cognitive-provider.test.js.map +1 -0
  317. package/dist/sessions/__tests__/cognitive-sink.test.d.ts +19 -0
  318. package/dist/sessions/__tests__/cognitive-sink.test.d.ts.map +1 -0
  319. package/dist/sessions/__tests__/cognitive-sink.test.js +334 -0
  320. package/dist/sessions/__tests__/cognitive-sink.test.js.map +1 -0
  321. package/dist/sessions/__tests__/runtime-tools.test.d.ts +2 -0
  322. package/dist/sessions/__tests__/runtime-tools.test.d.ts.map +1 -0
  323. package/dist/sessions/__tests__/runtime-tools.test.js +83 -0
  324. package/dist/sessions/__tests__/runtime-tools.test.js.map +1 -0
  325. package/dist/sessions/auto-retro.d.ts +29 -0
  326. package/dist/sessions/auto-retro.d.ts.map +1 -0
  327. package/dist/sessions/auto-retro.js +181 -0
  328. package/dist/sessions/auto-retro.js.map +1 -0
  329. package/dist/sessions/auto-retro.test.d.ts +2 -0
  330. package/dist/sessions/auto-retro.test.d.ts.map +1 -0
  331. package/dist/sessions/auto-retro.test.js +361 -0
  332. package/dist/sessions/auto-retro.test.js.map +1 -0
  333. package/dist/sessions/channels.d.ts +55 -0
  334. package/dist/sessions/channels.d.ts.map +1 -0
  335. package/dist/sessions/channels.js +118 -0
  336. package/dist/sessions/channels.js.map +1 -0
  337. package/dist/sessions/channels.test.d.ts +2 -0
  338. package/dist/sessions/channels.test.d.ts.map +1 -0
  339. package/dist/sessions/channels.test.js +285 -0
  340. package/dist/sessions/channels.test.js.map +1 -0
  341. package/dist/sessions/cognitive-modules.d.ts +100 -0
  342. package/dist/sessions/cognitive-modules.d.ts.map +1 -0
  343. package/dist/sessions/cognitive-modules.js +458 -0
  344. package/dist/sessions/cognitive-modules.js.map +1 -0
  345. package/dist/sessions/cognitive-provider.d.ts +42 -0
  346. package/dist/sessions/cognitive-provider.d.ts.map +1 -0
  347. package/dist/sessions/cognitive-provider.js +208 -0
  348. package/dist/sessions/cognitive-provider.js.map +1 -0
  349. package/dist/sessions/cognitive-sink.d.ts +73 -0
  350. package/dist/sessions/cognitive-sink.d.ts.map +1 -0
  351. package/dist/sessions/cognitive-sink.js +154 -0
  352. package/dist/sessions/cognitive-sink.js.map +1 -0
  353. package/dist/sessions/diagnostics.d.ts +70 -0
  354. package/dist/sessions/diagnostics.d.ts.map +1 -0
  355. package/dist/sessions/diagnostics.js +129 -0
  356. package/dist/sessions/diagnostics.js.map +1 -0
  357. package/dist/sessions/diagnostics.test.d.ts +2 -0
  358. package/dist/sessions/diagnostics.test.d.ts.map +1 -0
  359. package/dist/sessions/diagnostics.test.js +135 -0
  360. package/dist/sessions/diagnostics.test.js.map +1 -0
  361. package/dist/sessions/index.d.ts +32 -0
  362. package/dist/sessions/index.d.ts.map +1 -0
  363. package/dist/sessions/index.js +33 -0
  364. package/dist/sessions/index.js.map +1 -0
  365. package/dist/sessions/pool.d.ts +218 -0
  366. package/dist/sessions/pool.d.ts.map +1 -0
  367. package/dist/sessions/pool.js +991 -0
  368. package/dist/sessions/pool.js.map +1 -0
  369. package/dist/sessions/pool.test.d.ts +2 -0
  370. package/dist/sessions/pool.test.d.ts.map +1 -0
  371. package/dist/sessions/pool.test.js +633 -0
  372. package/dist/sessions/pool.test.js.map +1 -0
  373. package/dist/sessions/print-session.d.ts +142 -0
  374. package/dist/sessions/print-session.d.ts.map +1 -0
  375. package/dist/sessions/print-session.js +325 -0
  376. package/dist/sessions/print-session.js.map +1 -0
  377. package/dist/sessions/print-session.test.d.ts +2 -0
  378. package/dist/sessions/print-session.test.d.ts.map +1 -0
  379. package/dist/sessions/print-session.test.js +418 -0
  380. package/dist/sessions/print-session.test.js.map +1 -0
  381. package/dist/sessions/runtime-tools.d.ts +22 -0
  382. package/dist/sessions/runtime-tools.d.ts.map +1 -0
  383. package/dist/sessions/runtime-tools.js +162 -0
  384. package/dist/sessions/runtime-tools.js.map +1 -0
  385. package/dist/sessions/scope-hook.d.ts +77 -0
  386. package/dist/sessions/scope-hook.d.ts.map +1 -0
  387. package/dist/sessions/scope-hook.js +323 -0
  388. package/dist/sessions/scope-hook.js.map +1 -0
  389. package/dist/sessions/scope-hook.test.d.ts +2 -0
  390. package/dist/sessions/scope-hook.test.d.ts.map +1 -0
  391. package/dist/sessions/scope-hook.test.js +249 -0
  392. package/dist/sessions/scope-hook.test.js.map +1 -0
  393. package/dist/sessions/session-store/checkpoint-sink-impl.d.ts +16 -0
  394. package/dist/sessions/session-store/checkpoint-sink-impl.d.ts.map +1 -0
  395. package/dist/sessions/session-store/checkpoint-sink-impl.js +191 -0
  396. package/dist/sessions/session-store/checkpoint-sink-impl.js.map +1 -0
  397. package/dist/sessions/session-store/checkpoint-sink-impl.test.d.ts +5 -0
  398. package/dist/sessions/session-store/checkpoint-sink-impl.test.d.ts.map +1 -0
  399. package/dist/sessions/session-store/checkpoint-sink-impl.test.js +137 -0
  400. package/dist/sessions/session-store/checkpoint-sink-impl.test.js.map +1 -0
  401. package/dist/sessions/session-store/conformance.d.ts +59 -0
  402. package/dist/sessions/session-store/conformance.d.ts.map +1 -0
  403. package/dist/sessions/session-store/conformance.js +172 -0
  404. package/dist/sessions/session-store/conformance.js.map +1 -0
  405. package/dist/sessions/session-store/conformance.test.d.ts +7 -0
  406. package/dist/sessions/session-store/conformance.test.d.ts.map +1 -0
  407. package/dist/sessions/session-store/conformance.test.js +22 -0
  408. package/dist/sessions/session-store/conformance.test.js.map +1 -0
  409. package/dist/sessions/session-store/in-memory-session-store.d.ts +23 -0
  410. package/dist/sessions/session-store/in-memory-session-store.d.ts.map +1 -0
  411. package/dist/sessions/session-store/in-memory-session-store.js +197 -0
  412. package/dist/sessions/session-store/in-memory-session-store.js.map +1 -0
  413. package/dist/sessions/session-store/in-memory-session-store.test.d.ts +6 -0
  414. package/dist/sessions/session-store/in-memory-session-store.test.d.ts.map +1 -0
  415. package/dist/sessions/session-store/in-memory-session-store.test.js +183 -0
  416. package/dist/sessions/session-store/in-memory-session-store.test.js.map +1 -0
  417. package/dist/sessions/session-store/index.d.ts +20 -0
  418. package/dist/sessions/session-store/index.d.ts.map +1 -0
  419. package/dist/sessions/session-store/index.js +15 -0
  420. package/dist/sessions/session-store/index.js.map +1 -0
  421. package/dist/sessions/session-store/resume.d.ts +88 -0
  422. package/dist/sessions/session-store/resume.d.ts.map +1 -0
  423. package/dist/sessions/session-store/resume.js +96 -0
  424. package/dist/sessions/session-store/resume.js.map +1 -0
  425. package/dist/sessions/session-store/resume.test.d.ts +5 -0
  426. package/dist/sessions/session-store/resume.test.d.ts.map +1 -0
  427. package/dist/sessions/session-store/resume.test.js +119 -0
  428. package/dist/sessions/session-store/resume.test.js.map +1 -0
  429. package/dist/sessions/spawn-queue.d.ts +28 -0
  430. package/dist/sessions/spawn-queue.d.ts.map +1 -0
  431. package/dist/sessions/spawn-queue.js +63 -0
  432. package/dist/sessions/spawn-queue.js.map +1 -0
  433. package/dist/sessions/spawn-queue.test.d.ts +2 -0
  434. package/dist/sessions/spawn-queue.test.d.ts.map +1 -0
  435. package/dist/sessions/spawn-queue.test.js +65 -0
  436. package/dist/sessions/spawn-queue.test.js.map +1 -0
  437. package/dist/sessions/types.d.ts +16 -0
  438. package/dist/sessions/types.d.ts.map +1 -0
  439. package/dist/sessions/types.js +11 -0
  440. package/dist/sessions/types.js.map +1 -0
  441. package/dist/sessions/worktree-stale.test.d.ts +2 -0
  442. package/dist/sessions/worktree-stale.test.d.ts.map +1 -0
  443. package/dist/sessions/worktree-stale.test.js +468 -0
  444. package/dist/sessions/worktree-stale.test.js.map +1 -0
  445. package/dist/strategy/artifact-store.d.ts +12 -0
  446. package/dist/strategy/artifact-store.d.ts.map +1 -0
  447. package/dist/strategy/artifact-store.js +12 -0
  448. package/dist/strategy/artifact-store.js.map +1 -0
  449. package/dist/strategy/artifact-store.test.d.ts +2 -0
  450. package/dist/strategy/artifact-store.test.d.ts.map +1 -0
  451. package/dist/strategy/artifact-store.test.js +170 -0
  452. package/dist/strategy/artifact-store.test.js.map +1 -0
  453. package/dist/strategy/context-load-executor.d.ts +23 -0
  454. package/dist/strategy/context-load-executor.d.ts.map +1 -0
  455. package/dist/strategy/context-load-executor.js +87 -0
  456. package/dist/strategy/context-load-executor.js.map +1 -0
  457. package/dist/strategy/context-load-executor.test.d.ts +16 -0
  458. package/dist/strategy/context-load-executor.test.d.ts.map +1 -0
  459. package/dist/strategy/context-load-executor.test.js +158 -0
  460. package/dist/strategy/context-load-executor.test.js.map +1 -0
  461. package/dist/strategy/cortex-cross-app-invoker.stub.d.ts +65 -0
  462. package/dist/strategy/cortex-cross-app-invoker.stub.d.ts.map +1 -0
  463. package/dist/strategy/cortex-cross-app-invoker.stub.js +68 -0
  464. package/dist/strategy/cortex-cross-app-invoker.stub.js.map +1 -0
  465. package/dist/strategy/cross-app-node-executor.d.ts +54 -0
  466. package/dist/strategy/cross-app-node-executor.d.ts.map +1 -0
  467. package/dist/strategy/cross-app-node-executor.js +98 -0
  468. package/dist/strategy/cross-app-node-executor.js.map +1 -0
  469. package/dist/strategy/cross-app-node-executor.test.d.ts +13 -0
  470. package/dist/strategy/cross-app-node-executor.test.d.ts.map +1 -0
  471. package/dist/strategy/cross-app-node-executor.test.js +160 -0
  472. package/dist/strategy/cross-app-node-executor.test.js.map +1 -0
  473. package/dist/strategy/gates.d.ts +13 -0
  474. package/dist/strategy/gates.d.ts.map +1 -0
  475. package/dist/strategy/gates.js +13 -0
  476. package/dist/strategy/gates.js.map +1 -0
  477. package/dist/strategy/gates.test.d.ts +2 -0
  478. package/dist/strategy/gates.test.d.ts.map +1 -0
  479. package/dist/strategy/gates.test.js +299 -0
  480. package/dist/strategy/gates.test.js.map +1 -0
  481. package/dist/strategy/human-approval-resolver.d.ts +23 -0
  482. package/dist/strategy/human-approval-resolver.d.ts.map +1 -0
  483. package/dist/strategy/human-approval-resolver.js +94 -0
  484. package/dist/strategy/human-approval-resolver.js.map +1 -0
  485. package/dist/strategy/human-approval-resolver.test.d.ts +16 -0
  486. package/dist/strategy/human-approval-resolver.test.d.ts.map +1 -0
  487. package/dist/strategy/human-approval-resolver.test.js +200 -0
  488. package/dist/strategy/human-approval-resolver.test.js.map +1 -0
  489. package/dist/strategy/in-process-cross-app-invoker.d.ts +105 -0
  490. package/dist/strategy/in-process-cross-app-invoker.d.ts.map +1 -0
  491. package/dist/strategy/in-process-cross-app-invoker.js +206 -0
  492. package/dist/strategy/in-process-cross-app-invoker.js.map +1 -0
  493. package/dist/strategy/in-process-cross-app-invoker.test.d.ts +15 -0
  494. package/dist/strategy/in-process-cross-app-invoker.test.d.ts.map +1 -0
  495. package/dist/strategy/in-process-cross-app-invoker.test.js +190 -0
  496. package/dist/strategy/in-process-cross-app-invoker.test.js.map +1 -0
  497. package/dist/strategy/index.d.ts +29 -0
  498. package/dist/strategy/index.d.ts.map +1 -0
  499. package/dist/strategy/index.js +29 -0
  500. package/dist/strategy/index.js.map +1 -0
  501. package/dist/strategy/pacta-strategy.d.ts +97 -0
  502. package/dist/strategy/pacta-strategy.d.ts.map +1 -0
  503. package/dist/strategy/pacta-strategy.js +117 -0
  504. package/dist/strategy/pacta-strategy.js.map +1 -0
  505. package/dist/strategy/pacta-strategy.test.d.ts +2 -0
  506. package/dist/strategy/pacta-strategy.test.d.ts.map +1 -0
  507. package/dist/strategy/pacta-strategy.test.js +234 -0
  508. package/dist/strategy/pacta-strategy.test.js.map +1 -0
  509. package/dist/strategy/retro-generator.d.ts +18 -0
  510. package/dist/strategy/retro-generator.d.ts.map +1 -0
  511. package/dist/strategy/retro-generator.js +22 -0
  512. package/dist/strategy/retro-generator.js.map +1 -0
  513. package/dist/strategy/retro-writer.d.ts +25 -0
  514. package/dist/strategy/retro-writer.d.ts.map +1 -0
  515. package/dist/strategy/retro-writer.js +65 -0
  516. package/dist/strategy/retro-writer.js.map +1 -0
  517. package/dist/strategy/strategy-executor.d.ts +39 -0
  518. package/dist/strategy/strategy-executor.d.ts.map +1 -0
  519. package/dist/strategy/strategy-executor.js +253 -0
  520. package/dist/strategy/strategy-executor.js.map +1 -0
  521. package/dist/strategy/strategy-executor.test.d.ts +8 -0
  522. package/dist/strategy/strategy-executor.test.d.ts.map +1 -0
  523. package/dist/strategy/strategy-executor.test.js +1301 -0
  524. package/dist/strategy/strategy-executor.test.js.map +1 -0
  525. package/dist/strategy/strategy-parser.d.ts +30 -0
  526. package/dist/strategy/strategy-parser.d.ts.map +1 -0
  527. package/dist/strategy/strategy-parser.js +30 -0
  528. package/dist/strategy/strategy-parser.js.map +1 -0
  529. package/dist/strategy/sub-strategy-source.d.ts +27 -0
  530. package/dist/strategy/sub-strategy-source.d.ts.map +1 -0
  531. package/dist/strategy/sub-strategy-source.js +77 -0
  532. package/dist/strategy/sub-strategy-source.js.map +1 -0
  533. package/dist/strategy/types.d.ts +12 -0
  534. package/dist/strategy/types.d.ts.map +1 -0
  535. package/dist/strategy/types.js +9 -0
  536. package/dist/strategy/types.js.map +1 -0
  537. package/package.json +87 -0
@@ -0,0 +1,991 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { randomUUID } from 'node:crypto';
3
+ import { execSync } from 'node:child_process';
4
+ import { join, resolve } from 'node:path';
5
+ import { createPrintSession } from './print-session.js';
6
+ import { createCognitiveSession } from './cognitive-provider.js';
7
+ import { createRuntimeToolProvider } from './runtime-tools.js';
8
+ import { createSessionChannels } from './channels.js';
9
+ import { installScopeHook } from './scope-hook.js';
10
+ import { createAgentEventAdapter } from '../event-bus/agent-event-adapter.js';
11
+ import { CognitiveEventBusSink as CognitiveSink } from './cognitive-sink.js';
12
+ const DEFAULT_MAX_SESSIONS = 10;
13
+ const DEFAULT_MAX_DEPTH = 3;
14
+ const DEFAULT_MAX_AGENTS = 10;
15
+ const DEFAULT_STALE_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
16
+ const DEFAULT_KILL_TIMEOUT_MS = 60 * 60 * 1000; // 60 minutes
17
+ const WORKTREE_DIR = '.claude/worktrees';
18
+ // PRD 007: Fallback nickname word list
19
+ const NICKNAME_WORDS = [
20
+ 'alpha', 'bravo', 'cedar', 'drift', 'ember', 'flux', 'grain', 'haze',
21
+ 'iris', 'jade', 'kite', 'lumen', 'mist', 'nova', 'opal', 'prism',
22
+ 'quartz', 'ridge', 'spark', 'tide', 'umbra', 'vale', 'wave', 'xenon',
23
+ 'yield', 'zinc',
24
+ ];
25
+ // PRD 007: Method short names for methodology-derived nicknames
26
+ const METHOD_SHORT_NAMES = {
27
+ 'M1-COUNCIL': 'council',
28
+ 'M1-IMPL': 'impl',
29
+ 'M1-PLAN': 'plan',
30
+ 'M1-REVIEW': 'review',
31
+ 'M1-MDES': 'mdes',
32
+ 'M2-ORCH': 'orch',
33
+ 'M3-TMP': 'tmp',
34
+ };
35
+ /**
36
+ * Create a session pool that manages multiple Claude Code PTY sessions.
37
+ *
38
+ * The pool enforces a maximum session count and provides a uniform interface
39
+ * for creating, prompting, inspecting, and killing sessions.
40
+ *
41
+ * PRD 006: Sessions now track parent-child chains with budget enforcement.
42
+ */
43
+ export function createPool(options) {
44
+ const maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
45
+ const fsProvider = options?.fsProvider;
46
+ const eventBus = options?.eventBus;
47
+ const cognitiveSink = options?.cognitiveSink;
48
+ const sessions = new Map();
49
+ const sessionMetadata = new Map();
50
+ const sessionWorkdirs = new Map();
51
+ const sessionChains = new Map();
52
+ const sessionChannels = new Map();
53
+ const sessionWorktrees = new Map();
54
+ const sessionStaleConfigs = new Map();
55
+ const sessionStaleFlags = new Map();
56
+ const sessionNicknames = new Map(); // sessionId → nickname
57
+ const sessionPurposes = new Map(); // sessionId → purpose
58
+ const activeNicknames = new Set(); // uniqueness guard
59
+ // PRD 010: Original workdir per session (pre-worktree) for retro placement
60
+ const sessionOriginalWorkdirs = new Map();
61
+ // PRD 012: Per-session diagnostics trackers
62
+ const sessionDiagnostics = new Map();
63
+ // PRD 012 Phase 4: Session mode tracking
64
+ const sessionModes = new Map();
65
+ // PRD 033: Cognitive SSE sink registration — allows promptStream to receive cognitive events
66
+ const cognitiveSSESinks = new Map();
67
+ // OBS-19: Waiting-for-sub-agent state (set externally; PTY auto-detection removed in PRD 028 C-4)
68
+ const sessionWaitingFor = new Map(); // sessionId → what it's waiting for
69
+ // Pool-level counters
70
+ let totalSpawned = 0;
71
+ const startedAt = new Date();
72
+ let nicknameWordIndex = 0;
73
+ const methodNicknameCounts = new Map(); // method-short → next sequence
74
+ /**
75
+ * PRD 007: Generate a unique nickname for a session.
76
+ * Priority: explicit > methodology-derived > fallback word list.
77
+ */
78
+ function generateNickname(explicit, metadata) {
79
+ // 1. Explicit nickname — use if unique
80
+ if (explicit) {
81
+ const candidate = explicit.toLowerCase().replace(/[^a-z0-9-]/g, '');
82
+ if (candidate && !activeNicknames.has(candidate)) {
83
+ return candidate;
84
+ }
85
+ // If collision, append sequence number
86
+ for (let i = 2; i < 100; i++) {
87
+ const suffixed = `${candidate}-${i}`;
88
+ if (!activeNicknames.has(suffixed))
89
+ return suffixed;
90
+ }
91
+ }
92
+ // 2. Methodology-derived: if metadata has methodology_session_id, try to extract method
93
+ if (metadata?.methodology_session_id) {
94
+ const msid = String(metadata.methodology_session_id);
95
+ // Try to match known method patterns
96
+ for (const [methodId, shortName] of Object.entries(METHOD_SHORT_NAMES)) {
97
+ if (msid.includes(methodId) || msid.toLowerCase().includes(shortName)) {
98
+ const count = (methodNicknameCounts.get(shortName) ?? 0) + 1;
99
+ methodNicknameCounts.set(shortName, count);
100
+ const candidate = `${shortName}-${count}`;
101
+ if (!activeNicknames.has(candidate))
102
+ return candidate;
103
+ }
104
+ }
105
+ }
106
+ // 3. Fallback word list
107
+ for (let attempts = 0; attempts < NICKNAME_WORDS.length; attempts++) {
108
+ const candidate = NICKNAME_WORDS[nicknameWordIndex % NICKNAME_WORDS.length];
109
+ nicknameWordIndex++;
110
+ if (!activeNicknames.has(candidate))
111
+ return candidate;
112
+ }
113
+ // Last resort: word + counter
114
+ const base = NICKNAME_WORDS[nicknameWordIndex % NICKNAME_WORDS.length];
115
+ nicknameWordIndex++;
116
+ for (let i = 2; i < 100; i++) {
117
+ const candidate = `${base}-${i}`;
118
+ if (!activeNicknames.has(candidate))
119
+ return candidate;
120
+ }
121
+ // Absolute fallback
122
+ return `agent-${totalSpawned + 1}`;
123
+ }
124
+ function getChain(sessionId) {
125
+ return sessionChains.get(sessionId) ?? {
126
+ parent_session_id: null,
127
+ depth: 0,
128
+ children: [],
129
+ budget: { max_depth: DEFAULT_MAX_DEPTH, max_agents: DEFAULT_MAX_AGENTS, agents_spawned: 0 },
130
+ };
131
+ }
132
+ /**
133
+ * Find the root session of a chain and return its shared budget reference.
134
+ * Budget is tracked at the root — all agents in a chain share the same budget.
135
+ */
136
+ function getRootBudget(sessionId) {
137
+ const chain = sessionChains.get(sessionId);
138
+ if (!chain)
139
+ return null;
140
+ // Walk up to root
141
+ let currentId = sessionId;
142
+ let current = chain;
143
+ while (current.parent_session_id) {
144
+ const parent = sessionChains.get(current.parent_session_id);
145
+ if (!parent)
146
+ break;
147
+ currentId = current.parent_session_id;
148
+ current = parent;
149
+ }
150
+ return current.budget;
151
+ }
152
+ /**
153
+ * PRD 010: Handle session death — previously detached PTY watcher and generated auto-retro.
154
+ * PTY watcher removed in PRD 028 C-4. Function retained for call-site symmetry.
155
+ */
156
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
157
+ function handleSessionDeath(_sessionId, _reason) {
158
+ // PTY watcher removed in PRD 028 C-4. Auto-retro via watcher observations no longer applies.
159
+ // Future: print-mode retro generation can be added here if needed.
160
+ }
161
+ // ── LLM provider resolution for cognitive-agent mode ────────
162
+ async function resolveProvider(providerName, config) {
163
+ switch (providerName ?? 'anthropic') {
164
+ case 'anthropic': {
165
+ const { anthropicProvider } = await import('@methodts/pacta-provider-anthropic');
166
+ return anthropicProvider({ model: config.model, toolProvider: config.toolProvider });
167
+ }
168
+ case 'ollama': {
169
+ const { ollamaProvider } = await import('@methodts/pacta-provider-ollama');
170
+ const provider = ollamaProvider({
171
+ baseUrl: config.baseUrl ?? process.env.OLLAMA_BASE_URL ?? 'http://chobits:11434',
172
+ model: config.model,
173
+ });
174
+ await provider.init();
175
+ return provider;
176
+ }
177
+ default:
178
+ throw new Error(`Unknown LLM provider: ${providerName}`);
179
+ }
180
+ }
181
+ return {
182
+ async create({ workdir, initialPrompt, spawnArgs, metadata, parentSessionId, depth, budget, isolation, timeout_ms, nickname, purpose, persistent, spawn_delay_ms, mode, allowed_paths, scope_mode, session_id, provider_type, cognitive_config, cognitive_patterns, llm_provider, llm_config, experiment_id, run_id }) {
183
+ // Count active (non-dead) sessions toward the limit
184
+ const activeSessions = [...sessions.values()].filter((s) => s.status !== 'dead').length;
185
+ if (activeSessions >= maxSessions) {
186
+ throw new Error(`Session pool full — maximum ${maxSessions} active sessions`);
187
+ }
188
+ // Determine chain properties
189
+ const effectiveDepth = depth ?? 0;
190
+ const effectiveBudget = {
191
+ max_depth: budget?.max_depth ?? DEFAULT_MAX_DEPTH,
192
+ max_agents: budget?.max_agents ?? DEFAULT_MAX_AGENTS,
193
+ agents_spawned: budget?.agents_spawned ?? 0,
194
+ };
195
+ // If this is a child session, inherit and validate budget from parent
196
+ if (parentSessionId) {
197
+ const parentChain = sessionChains.get(parentSessionId);
198
+ if (parentChain) {
199
+ // Use parent's budget as the source of truth (shared budget across chain)
200
+ const rootBudget = getRootBudget(parentSessionId) ?? parentChain.budget;
201
+ // Depth check
202
+ if (effectiveDepth >= rootBudget.max_depth) {
203
+ throw new Error(JSON.stringify({
204
+ error: 'DEPTH_EXCEEDED',
205
+ message: `Depth limit exceeded: depth ${effectiveDepth} >= max_depth ${rootBudget.max_depth}. Cannot spawn deeper.`,
206
+ budget: rootBudget,
207
+ }));
208
+ }
209
+ // Agent count check
210
+ if (rootBudget.agents_spawned >= rootBudget.max_agents) {
211
+ throw new Error(JSON.stringify({
212
+ error: 'BUDGET_EXHAUSTED',
213
+ message: `Agent budget exceeded: ${rootBudget.agents_spawned}/${rootBudget.max_agents} agents spawned. Increase budget or complete existing work.`,
214
+ budget: rootBudget,
215
+ }));
216
+ }
217
+ // Increment the root budget's agent count
218
+ rootBudget.agents_spawned++;
219
+ // Copy current root budget values for the child
220
+ effectiveBudget.max_depth = rootBudget.max_depth;
221
+ effectiveBudget.max_agents = rootBudget.max_agents;
222
+ effectiveBudget.agents_spawned = rootBudget.agents_spawned;
223
+ }
224
+ }
225
+ const sessionId = session_id ?? randomUUID();
226
+ // PRD 007: Generate and register nickname
227
+ const assignedNickname = generateNickname(nickname, metadata);
228
+ activeNicknames.add(assignedNickname);
229
+ // PRD 006 Component 2: Worktree isolation
230
+ const effectiveIsolation = isolation ?? 'shared';
231
+ let worktreePath = null;
232
+ let worktreeBranch = null;
233
+ let effectiveWorkdir = workdir;
234
+ if (effectiveIsolation === 'worktree') {
235
+ worktreeBranch = `worktree-${sessionId.substring(0, 8)}`;
236
+ const worktreeRelDir = join(WORKTREE_DIR, sessionId.substring(0, 8));
237
+ worktreePath = resolve(workdir, worktreeRelDir);
238
+ try {
239
+ execSync(`git worktree add "${worktreeRelDir}" -b "${worktreeBranch}"`, { cwd: workdir, stdio: 'pipe' });
240
+ effectiveWorkdir = worktreePath;
241
+ }
242
+ catch (e) {
243
+ throw new Error(`Worktree creation failed: ${e.message}`);
244
+ }
245
+ }
246
+ const worktreeInfo = {
247
+ isolation: effectiveIsolation,
248
+ worktree_path: worktreePath,
249
+ worktree_branch: worktreeBranch,
250
+ metals_available: effectiveIsolation !== 'worktree',
251
+ };
252
+ // PRD 014: Scope enforcement — determine effective mode and install hook
253
+ const effectiveAllowedPaths = allowed_paths ?? [];
254
+ const envScopeDefault = process.env.SCOPE_ENFORCEMENT_DEFAULT;
255
+ const validatedEnvDefault = (envScopeDefault === 'enforce' || envScopeDefault === 'warn') ? envScopeDefault : 'enforce';
256
+ let effectiveScopeMode = scope_mode ?? validatedEnvDefault;
257
+ if (effectiveAllowedPaths.length > 0) {
258
+ if (effectiveIsolation !== 'worktree' && effectiveScopeMode === 'enforce') {
259
+ // PRD 014: Worktree fallback — can't install hook in shared mode
260
+ console.warn(`[PRD 014] allowed_paths provided without worktree isolation — falling back to mode 'warn'. Pre-commit hook requires isolation: 'worktree'.`);
261
+ effectiveScopeMode = 'warn';
262
+ }
263
+ if (effectiveScopeMode === 'enforce' && worktreePath) {
264
+ // Install pre-commit hook in the worktree
265
+ const hookResult = installScopeHook(worktreePath, sessionId, effectiveAllowedPaths);
266
+ if (hookResult.error) {
267
+ console.warn(`[PRD 014] Scope hook installation warning: ${hookResult.error}`);
268
+ }
269
+ }
270
+ // Store scope constraint in metadata for PTY watcher (Phase 2)
271
+ const existingMetadata = metadata ?? {};
272
+ metadata = {
273
+ ...existingMetadata,
274
+ allowed_paths: effectiveAllowedPaths,
275
+ scope_mode: effectiveScopeMode,
276
+ };
277
+ }
278
+ // PRD 006 Component 4: Stale detection config
279
+ // PRD 011: persistent sessions skip stale detection entirely
280
+ const staleConfig = persistent ? null : {
281
+ stale_timeout_ms: timeout_ms ?? DEFAULT_STALE_TIMEOUT_MS,
282
+ kill_timeout_ms: (timeout_ms ? timeout_ms * 2 : DEFAULT_KILL_TIMEOUT_MS),
283
+ };
284
+ // PRD 033: Determine session mode from provider_type (default: print)
285
+ const effectiveMode = provider_type === 'cognitive-agent' ? 'cognitive-agent' : 'print';
286
+ // PRD 012: Staggered spawn — delay before spawning process
287
+ if (spawn_delay_ms && spawn_delay_ms > 0) {
288
+ await new Promise(r => setTimeout(r, spawn_delay_ms));
289
+ }
290
+ let session;
291
+ // PRD-057 / S2 §6 / C5: if a SessionProviderFactory was supplied at pool
292
+ // construction, delegate the "how does a prompt actually execute" part
293
+ // to the factory. Otherwise fall back to the built-in print + cognitive
294
+ // paths. Both paths set up the cognitive SSE sink in the same way when
295
+ // applicable so `promptStream` behavior is identical.
296
+ if (options?.providerFactory) {
297
+ let sseSink = null;
298
+ if (effectiveMode === 'cognitive-agent') {
299
+ cognitiveSSESinks.set(sessionId, (cb) => { sseSink = cb; });
300
+ }
301
+ const sessionCognitiveSink = (effectiveMode === 'cognitive-agent' && experiment_id && run_id && eventBus)
302
+ ? new CognitiveSink(eventBus, { sessionId, experimentId: experiment_id, runId: run_id })
303
+ : cognitiveSink;
304
+ const factoryOptions = {
305
+ sessionId,
306
+ mode: effectiveMode,
307
+ workdir: effectiveWorkdir,
308
+ allowedTools: spawnArgs,
309
+ allowedPaths: effectiveAllowedPaths,
310
+ metadata,
311
+ onEvent: (event) => {
312
+ // Forward to active SSE stream (if any) and emit cognitive
313
+ // events onto the bus for PRD 041 experiment tracing.
314
+ sseSink?.(event);
315
+ if (eventBus && effectiveMode === 'cognitive-agent') {
316
+ eventBus.emit({
317
+ version: 1,
318
+ domain: 'session',
319
+ type: `session.cognitive.${event.type}`,
320
+ severity: 'info',
321
+ sessionId,
322
+ payload: event,
323
+ source: 'runtime/sessions/pool',
324
+ });
325
+ }
326
+ },
327
+ cognitiveConfig: cognitive_config,
328
+ cognitiveSink: sessionCognitiveSink,
329
+ };
330
+ const handle = await options.providerFactory.createSession(factoryOptions);
331
+ // The factory returns a handle structurally compatible with
332
+ // PtySession; cast once here — every method the pool invokes is
333
+ // guaranteed present by the PtySessionHandle contract.
334
+ session = handle;
335
+ }
336
+ else if (effectiveMode === 'cognitive-agent') {
337
+ // PRD 033: Cognitive agent session — runs reasoning cycle internally
338
+ const { createProviderAdapter } = await import('@methodts/pacta');
339
+ const tools = createRuntimeToolProvider(effectiveWorkdir);
340
+ const model = llm_config?.model ?? (typeof metadata?.model === 'string' ? metadata.model : undefined);
341
+ const agentProvider = await resolveProvider(llm_provider, { model, baseUrl: llm_config?.baseUrl, toolProvider: tools });
342
+ const adapter = createProviderAdapter(agentProvider, {
343
+ pactTemplate: { mode: { type: 'oneshot' }, budget: { maxOutputTokens: 4096 } },
344
+ });
345
+ // Mutable SSE sink — set by promptStream(), cleared on completion.
346
+ // Allows cognitive events to flow to both the event bus and the active SSE stream.
347
+ let sseSink = null;
348
+ cognitiveSSESinks.set(sessionId, (cb) => { sseSink = cb; });
349
+ // PRD 041: Create a per-session CognitiveSink with experiment context so that
350
+ // ExperimentEventSink can route emitted RuntimeEvents to the correct JSONL file.
351
+ // Falls back to the pool-level sink when no experiment context is present.
352
+ const sessionCognitiveSink = (experiment_id && run_id && eventBus)
353
+ ? new CognitiveSink(eventBus, { sessionId, experimentId: experiment_id, runId: run_id })
354
+ : cognitiveSink;
355
+ session = createCognitiveSession({
356
+ id: sessionId,
357
+ workdir: effectiveWorkdir,
358
+ adapter,
359
+ tools,
360
+ cognitiveSink: sessionCognitiveSink,
361
+ config: {
362
+ name: cognitive_config?.name,
363
+ patterns: cognitive_patterns,
364
+ maxCycles: cognitive_config?.maxCycles,
365
+ workspaceCapacity: cognitive_config?.workspaceCapacity,
366
+ confidenceThreshold: cognitive_config?.confidenceThreshold,
367
+ stagnationThreshold: cognitive_config?.stagnationThreshold,
368
+ interventionBudget: cognitive_config?.interventionBudget,
369
+ },
370
+ initialPrompt: initialPrompt ?? undefined,
371
+ onEvent: (event) => {
372
+ // Forward to active SSE stream (if any)
373
+ sseSink?.(event);
374
+ // Route cognitive cycle events through the event bus
375
+ if (eventBus) {
376
+ eventBus.emit({
377
+ version: 1,
378
+ domain: 'session',
379
+ type: `session.cognitive.${event.type}`,
380
+ severity: 'info',
381
+ sessionId,
382
+ payload: event,
383
+ source: 'runtime/sessions/cognitive-provider',
384
+ });
385
+ }
386
+ },
387
+ });
388
+ }
389
+ else {
390
+ // Default: print-mode session (claude --print)
391
+ const DEFAULT_SYSTEM_PROMPT_SUFFIX = [
392
+ 'When producing diagrams, flowcharts, or architecture visualizations, use GlyphJS ui: fenced code blocks instead of ASCII art.',
393
+ 'Available components: ui:flowchart, ui:callout, ui:table, ui:architecture, ui:timeline, ui:graph, ui:sequence, ui:tabs, ui:steps, ui:kpi, ui:mindmap.',
394
+ 'Use proper markdown tables (| col | col |) instead of ASCII-aligned columns.',
395
+ 'Example: ```ui:flowchart\\nnodes:\\n - id: a\\n label: Start\\nedges:\\n - from: a\\n to: b\\n```',
396
+ ].join(' ');
397
+ const userSystemPrompt = typeof metadata?.append_system_prompt === 'string' ? metadata.append_system_prompt : '';
398
+ const effectiveSystemPrompt = userSystemPrompt
399
+ ? `${userSystemPrompt}\n\n${DEFAULT_SYSTEM_PROMPT_SUFFIX}`
400
+ : DEFAULT_SYSTEM_PROMPT_SUFFIX;
401
+ session = createPrintSession({
402
+ id: sessionId,
403
+ workdir: effectiveWorkdir,
404
+ initialPrompt: initialPrompt ?? undefined,
405
+ maxBudgetUsd: typeof metadata?.max_budget_usd === 'number' ? metadata.max_budget_usd : undefined,
406
+ appendSystemPrompt: effectiveSystemPrompt,
407
+ permissionMode: process.env.PRINT_PERMISSION_MODE ?? 'bypassPermissions',
408
+ model: typeof metadata?.model === 'string' ? metadata.model : undefined,
409
+ spawnArgs,
410
+ onEvent: eventBus ? createAgentEventAdapter(eventBus, sessionId, metadata?.project_id ?? 'unknown') : undefined,
411
+ });
412
+ }
413
+ sessions.set(sessionId, session);
414
+ sessionModes.set(sessionId, effectiveMode);
415
+ sessionWorkdirs.set(sessionId, effectiveWorkdir);
416
+ if (metadata) {
417
+ sessionMetadata.set(sessionId, metadata);
418
+ }
419
+ sessionWorktrees.set(sessionId, worktreeInfo);
420
+ if (staleConfig) {
421
+ sessionStaleConfigs.set(sessionId, staleConfig);
422
+ }
423
+ sessionStaleFlags.set(sessionId, false);
424
+ sessionNicknames.set(sessionId, assignedNickname);
425
+ if (purpose) {
426
+ sessionPurposes.set(sessionId, purpose);
427
+ }
428
+ // Record chain info
429
+ const chainInfo = {
430
+ parent_session_id: parentSessionId ?? null,
431
+ depth: effectiveDepth,
432
+ children: [],
433
+ budget: effectiveBudget,
434
+ };
435
+ sessionChains.set(sessionId, chainInfo);
436
+ // Register as child of parent
437
+ if (parentSessionId) {
438
+ const parentChain = sessionChains.get(parentSessionId);
439
+ if (parentChain) {
440
+ parentChain.children.push(sessionId);
441
+ }
442
+ }
443
+ // PRD 008: Create channels (legacy — retained for getChannels() compatibility)
444
+ const channels = createSessionChannels();
445
+ sessionChannels.set(sessionId, channels);
446
+ // PRD 026 Phase 3: session.spawned emitted via eventBus only (appendMessage removed)
447
+ if (eventBus) {
448
+ eventBus.emit({
449
+ version: 1,
450
+ domain: 'session',
451
+ type: 'session.spawned',
452
+ severity: 'info',
453
+ sessionId,
454
+ payload: {
455
+ session_id: sessionId,
456
+ parent_session_id: parentSessionId ?? null,
457
+ depth: effectiveDepth,
458
+ mode: effectiveMode,
459
+ workdir,
460
+ nickname,
461
+ },
462
+ source: 'runtime/sessions/pool',
463
+ });
464
+ }
465
+ // PRD 010: Track original workdir (pre-worktree) for auto-retro placement
466
+ sessionOriginalWorkdirs.set(sessionId, workdir);
467
+ totalSpawned++;
468
+ return { sessionId, nickname: assignedNickname, status: session.status, chain: chainInfo, worktree: worktreeInfo, mode: effectiveMode };
469
+ },
470
+ async prompt(sessionId, prompt, timeoutMs, settleDelayMs) {
471
+ const session = sessions.get(sessionId);
472
+ if (!session) {
473
+ throw new Error(`Session not found: ${sessionId}`);
474
+ }
475
+ if (session.status === 'dead') {
476
+ throw new Error(`Session ${sessionId} is dead — cannot send prompt`);
477
+ }
478
+ const result = await session.sendPrompt(prompt, timeoutMs, settleDelayMs);
479
+ // PRD 012: Record settle overhead for this prompt
480
+ const tracker = sessionDiagnostics.get(sessionId);
481
+ if (tracker && !result.timedOut) {
482
+ tracker.recordPromptCompletion();
483
+ }
484
+ // Read printMetadata in-place after sendPrompt resolves (same tick — no race)
485
+ const printSession = session;
486
+ const metadata = printSession.printMetadata ?? null;
487
+ return { output: result.output, timedOut: result.timedOut, metadata };
488
+ },
489
+ async promptStream(sessionId, prompt, onEvent, timeoutMs) {
490
+ const session = sessions.get(sessionId);
491
+ if (!session) {
492
+ throw new Error(`Session not found: ${sessionId}`);
493
+ }
494
+ if (session.status === 'dead') {
495
+ throw new Error(`Session ${sessionId} is dead — cannot send prompt`);
496
+ }
497
+ // PRD 033: Register SSE sink for cognitive sessions so cycle events flow to SSE
498
+ const setSink = cognitiveSSESinks.get(sessionId);
499
+ if (setSink)
500
+ setSink(onEvent);
501
+ try {
502
+ let result;
503
+ if (typeof session.sendPromptStream === 'function') {
504
+ // Use the streaming path — emits incremental text chunks
505
+ result = await session.sendPromptStream(prompt, (chunk) => {
506
+ onEvent({ type: 'text', content: chunk });
507
+ }, timeoutMs);
508
+ }
509
+ else {
510
+ // Fallback: non-streaming path (subscribes to onOutput for single emit)
511
+ const unsubscribe = session.onOutput((data) => {
512
+ if (data.startsWith('\n[print-mode]'))
513
+ return;
514
+ onEvent({ type: 'text', content: data });
515
+ });
516
+ try {
517
+ result = await session.sendPrompt(prompt, timeoutMs);
518
+ }
519
+ finally {
520
+ unsubscribe();
521
+ }
522
+ }
523
+ // Cognitive sessions emit their own 'done' event via the SSE sink —
524
+ // skip the pool's redundant done to avoid overwriting metadata with nulls.
525
+ const isCognitive = cognitiveSSESinks.has(sessionId);
526
+ if (!isCognitive) {
527
+ // Read printMetadata and map to response shape (same as non-streaming endpoint)
528
+ const printSession = session;
529
+ const raw = printSession.printMetadata ?? null;
530
+ const metadata = raw ? {
531
+ cost_usd: raw.total_cost_usd,
532
+ num_turns: raw.num_turns,
533
+ duration_ms: raw.duration_ms,
534
+ stop_reason: raw.stop_reason,
535
+ input_tokens: raw.usage.input_tokens,
536
+ output_tokens: raw.usage.output_tokens,
537
+ cache_read_tokens: raw.usage.cache_read_input_tokens,
538
+ cache_write_tokens: raw.usage.cache_creation_input_tokens,
539
+ } : null;
540
+ // Send done event with full response + mapped metadata
541
+ onEvent({
542
+ type: 'done',
543
+ output: result.output,
544
+ metadata,
545
+ timed_out: result.timedOut,
546
+ });
547
+ }
548
+ }
549
+ catch (err) {
550
+ onEvent({
551
+ type: 'error',
552
+ error: err.message,
553
+ });
554
+ }
555
+ finally {
556
+ // Clear the cognitive SSE sink to avoid leaking callbacks
557
+ if (setSink)
558
+ setSink(null);
559
+ }
560
+ },
561
+ status(sessionId) {
562
+ const session = sessions.get(sessionId);
563
+ if (!session) {
564
+ throw new Error(`Session not found: ${sessionId}`);
565
+ }
566
+ // OBS-19: Override status to 'waiting' when session is waiting for a sub-agent
567
+ const waitingFor = sessionWaitingFor.get(sessionId) ?? null;
568
+ const effectiveStatus = (waitingFor && session.status === 'ready') ? 'waiting' : session.status;
569
+ // PRD 012: Build diagnostics snapshot with stall classification
570
+ const tracker = sessionDiagnostics.get(sessionId);
571
+ let diagnostics = null;
572
+ if (tracker) {
573
+ diagnostics = tracker.snapshot();
574
+ // Classify stall reason for stale or idle sessions
575
+ const isStale = sessionStaleFlags.get(sessionId) ?? false;
576
+ if (isStale || (effectiveStatus === 'ready' && session.promptCount > 0)) {
577
+ // Check if other sessions are also slow (for resource_contention classification)
578
+ const otherSessionsSlow = [...sessionDiagnostics.entries()].some(([otherId, otherTracker]) => {
579
+ if (otherId === sessionId)
580
+ return false;
581
+ const otherSnap = otherTracker.snapshot();
582
+ return otherSnap.time_to_first_output_ms !== null && otherSnap.time_to_first_output_ms > 10_000;
583
+ });
584
+ diagnostics.stall_reason = tracker.classifyStall(otherSessionsSlow);
585
+ }
586
+ }
587
+ return {
588
+ sessionId,
589
+ nickname: sessionNicknames.get(sessionId) ?? sessionId.substring(0, 8),
590
+ purpose: sessionPurposes.get(sessionId) ?? null,
591
+ status: effectiveStatus,
592
+ queueDepth: session.queueDepth,
593
+ metadata: sessionMetadata.get(sessionId),
594
+ promptCount: session.promptCount,
595
+ lastActivityAt: session.lastActivityAt,
596
+ workdir: sessionWorkdirs.get(sessionId) ?? '',
597
+ chain: getChain(sessionId),
598
+ worktree: sessionWorktrees.get(sessionId) ?? {
599
+ isolation: 'shared', worktree_path: null, worktree_branch: null, metals_available: true,
600
+ },
601
+ stale: sessionStaleFlags.get(sessionId) ?? false,
602
+ waiting_for: waitingFor,
603
+ mode: sessionModes.get(sessionId) ?? 'print',
604
+ diagnostics,
605
+ };
606
+ },
607
+ kill(sessionId, worktreeAction) {
608
+ const session = sessions.get(sessionId);
609
+ if (!session) {
610
+ throw new Error(`Session not found: ${sessionId}`);
611
+ }
612
+ // PRD 010: Detach watcher and generate auto-retro before killing
613
+ handleSessionDeath(sessionId, 'killed');
614
+ session.kill();
615
+ // PRD 006 Component 2: Handle worktree cleanup
616
+ let worktreeCleaned = false;
617
+ const wtInfo = sessionWorktrees.get(sessionId);
618
+ if (wtInfo && wtInfo.isolation === 'worktree' && wtInfo.worktree_path) {
619
+ const action = worktreeAction ?? 'keep';
620
+ const originalWorkdir = resolve(wtInfo.worktree_path, '..', '..', '..');
621
+ if (action === 'discard') {
622
+ try {
623
+ execSync(`git worktree remove "${wtInfo.worktree_path}" --force`, {
624
+ cwd: originalWorkdir, stdio: 'pipe',
625
+ });
626
+ if (wtInfo.worktree_branch) {
627
+ execSync(`git branch -D "${wtInfo.worktree_branch}"`, {
628
+ cwd: originalWorkdir, stdio: 'pipe',
629
+ });
630
+ }
631
+ worktreeCleaned = true;
632
+ }
633
+ catch {
634
+ // Worktree cleanup failure is non-fatal
635
+ }
636
+ }
637
+ else if (action === 'merge') {
638
+ try {
639
+ if (wtInfo.worktree_branch) {
640
+ execSync(`git merge "${wtInfo.worktree_branch}" --no-edit`, {
641
+ cwd: originalWorkdir, stdio: 'pipe',
642
+ });
643
+ }
644
+ execSync(`git worktree remove "${wtInfo.worktree_path}" --force`, {
645
+ cwd: originalWorkdir, stdio: 'pipe',
646
+ });
647
+ worktreeCleaned = true;
648
+ }
649
+ catch {
650
+ // Merge failure is non-fatal — worktree preserved for manual merge
651
+ }
652
+ }
653
+ // action === 'keep': leave worktree on disk
654
+ }
655
+ // PRD 026 Phase 3: session.killed emitted via eventBus only (appendMessage removed)
656
+ if (eventBus) {
657
+ eventBus.emit({
658
+ version: 1,
659
+ domain: 'session',
660
+ type: 'session.killed',
661
+ severity: 'info',
662
+ sessionId,
663
+ payload: {
664
+ session_id: sessionId,
665
+ killed_by: 'api',
666
+ worktree_action: worktreeAction ?? 'keep',
667
+ worktree_cleaned: worktreeCleaned,
668
+ },
669
+ source: 'runtime/sessions/pool',
670
+ });
671
+ }
672
+ return { sessionId: session.id, killed: true, worktree_cleaned: worktreeCleaned };
673
+ },
674
+ list() {
675
+ return [...sessions.entries()].map(([sessionId, session]) => {
676
+ // OBS-19: Override status to 'waiting' when session is waiting for a sub-agent
677
+ const waitingFor = sessionWaitingFor.get(sessionId) ?? null;
678
+ const effectiveStatus = (waitingFor && session.status === 'ready') ? 'waiting' : session.status;
679
+ // PRD 012: Include diagnostics snapshot
680
+ const tracker = sessionDiagnostics.get(sessionId);
681
+ const diagnostics = tracker ? tracker.snapshot() : null;
682
+ return {
683
+ sessionId,
684
+ nickname: sessionNicknames.get(sessionId) ?? sessionId.substring(0, 8),
685
+ purpose: sessionPurposes.get(sessionId) ?? null,
686
+ status: effectiveStatus,
687
+ queueDepth: session.queueDepth,
688
+ metadata: sessionMetadata.get(sessionId),
689
+ promptCount: session.promptCount,
690
+ lastActivityAt: session.lastActivityAt,
691
+ workdir: sessionWorkdirs.get(sessionId) ?? '',
692
+ chain: getChain(sessionId),
693
+ worktree: sessionWorktrees.get(sessionId) ?? {
694
+ isolation: 'shared', worktree_path: null, worktree_branch: null, metals_available: true,
695
+ },
696
+ stale: sessionStaleFlags.get(sessionId) ?? false,
697
+ waiting_for: waitingFor,
698
+ mode: sessionModes.get(sessionId) ?? 'print',
699
+ diagnostics,
700
+ };
701
+ });
702
+ },
703
+ getChannels(sessionId) {
704
+ const channels = sessionChannels.get(sessionId);
705
+ if (!channels) {
706
+ throw new Error(`Session not found: ${sessionId}`);
707
+ }
708
+ return channels;
709
+ },
710
+ getSession(sessionId) {
711
+ const session = sessions.get(sessionId);
712
+ if (!session) {
713
+ throw new Error(`Session not found: ${sessionId}`);
714
+ }
715
+ return session;
716
+ },
717
+ poolStats() {
718
+ const allSessions = [...sessions.values()];
719
+ const active = allSessions.filter((s) => s.status !== 'dead').length;
720
+ const dead = allSessions.filter((s) => s.status === 'dead').length;
721
+ return {
722
+ totalSpawned,
723
+ startedAt,
724
+ maxSessions,
725
+ activeSessions: active,
726
+ deadSessions: dead,
727
+ };
728
+ },
729
+ removeDead(ttlMs) {
730
+ let removed = 0;
731
+ for (const [sessionId, session] of sessions.entries()) {
732
+ if (session.status === 'dead') {
733
+ // Use lastActivityAt as the "died at" timestamp (it's the last activity before death)
734
+ if (Date.now() - session.lastActivityAt.getTime() > ttlMs) {
735
+ const nick = sessionNicknames.get(sessionId);
736
+ if (nick)
737
+ activeNicknames.delete(nick);
738
+ sessions.delete(sessionId);
739
+ sessionMetadata.delete(sessionId);
740
+ sessionWorkdirs.delete(sessionId);
741
+ sessionModes.delete(sessionId);
742
+ sessionChains.delete(sessionId);
743
+ sessionChannels.delete(sessionId);
744
+ sessionWorktrees.delete(sessionId);
745
+ sessionStaleConfigs.delete(sessionId);
746
+ sessionStaleFlags.delete(sessionId);
747
+ sessionNicknames.delete(sessionId);
748
+ sessionPurposes.delete(sessionId);
749
+ sessionOriginalWorkdirs.delete(sessionId);
750
+ sessionWaitingFor.delete(sessionId);
751
+ sessionDiagnostics.delete(sessionId);
752
+ removed++;
753
+ }
754
+ }
755
+ }
756
+ return removed;
757
+ },
758
+ /**
759
+ * PRD 006 Component 4: Check all sessions for staleness.
760
+ * - Sessions inactive > stale_timeout_ms → marked stale, 'stale' event emitted
761
+ * - Sessions inactive > kill_timeout_ms → auto-killed
762
+ * Returns lists of newly-stale and newly-killed session IDs.
763
+ */
764
+ checkStale() {
765
+ const now = Date.now();
766
+ const staleIds = [];
767
+ const killedIds = [];
768
+ for (const [sessionId, session] of sessions.entries()) {
769
+ if (session.status === 'dead')
770
+ continue;
771
+ const config = sessionStaleConfigs.get(sessionId);
772
+ if (!config)
773
+ continue;
774
+ const inactiveMs = now - session.lastActivityAt.getTime();
775
+ const isStale = sessionStaleFlags.get(sessionId) ?? false;
776
+ // Auto-kill: inactive beyond kill timeout
777
+ if (inactiveMs >= config.kill_timeout_ms) {
778
+ handleSessionDeath(sessionId, 'stale');
779
+ session.kill();
780
+ // PRD 026 Phase 3: session.stale emitted via eventBus only (appendMessage removed)
781
+ if (eventBus) {
782
+ eventBus.emit({
783
+ version: 1,
784
+ domain: 'session',
785
+ type: 'session.stale',
786
+ severity: 'warning',
787
+ sessionId,
788
+ payload: {
789
+ session_id: sessionId,
790
+ inactive_ms: inactiveMs,
791
+ action: 'auto_killed',
792
+ },
793
+ source: 'runtime/sessions/pool',
794
+ });
795
+ }
796
+ killedIds.push(sessionId);
797
+ sessionStaleFlags.set(sessionId, true);
798
+ continue;
799
+ }
800
+ // Mark stale: inactive beyond stale timeout (but not yet killed)
801
+ if (inactiveMs >= config.stale_timeout_ms && !isStale) {
802
+ sessionStaleFlags.set(sessionId, true);
803
+ // PRD 026 Phase 3: session.stale emitted via eventBus only (appendMessage removed)
804
+ if (eventBus) {
805
+ eventBus.emit({
806
+ version: 1,
807
+ domain: 'session',
808
+ type: 'session.stale',
809
+ severity: 'warning',
810
+ sessionId,
811
+ payload: {
812
+ session_id: sessionId,
813
+ inactive_ms: inactiveMs,
814
+ action: 'marked_stale',
815
+ kill_in_ms: config.kill_timeout_ms - inactiveMs,
816
+ },
817
+ source: 'runtime/sessions/pool',
818
+ });
819
+ }
820
+ staleIds.push(sessionId);
821
+ }
822
+ }
823
+ return { stale: staleIds, killed: killedIds };
824
+ },
825
+ childPids() {
826
+ const pids = [];
827
+ for (const [, session] of sessions.entries()) {
828
+ if (session.status !== 'dead' && session.pid !== null) {
829
+ pids.push(session.pid);
830
+ }
831
+ }
832
+ return pids;
833
+ },
834
+ setObservationHook(_hook) {
835
+ // PTY watcher removed in PRD 028 C-4. Observation hook is now a no-op.
836
+ },
837
+ restoreSession(snapshot) {
838
+ const sid = snapshot.sessionId;
839
+ // Duplicate restore — silently skip if session already exists
840
+ if (sessions.has(sid)) {
841
+ return;
842
+ }
843
+ // Build a minimal PtySession stub that is compatible with pool operations.
844
+ // The stub does not spawn a process — it is a placeholder for recovered state.
845
+ // Sending a prompt creates a real print session under the hood (recovered mode).
846
+ let status = 'ready';
847
+ let promptCount = snapshot.promptCount;
848
+ let lastActivityAt = new Date();
849
+ let transcript = '';
850
+ const outputSubscribers = new Set();
851
+ const exitCallbacks = [];
852
+ let lastMetadata = null;
853
+ const stubSession = {
854
+ id: sid,
855
+ get pid() { return null; },
856
+ get status() { return status; },
857
+ set status(s) { status = s; },
858
+ get queueDepth() { return 0; },
859
+ get promptCount() { return promptCount; },
860
+ set promptCount(n) { promptCount = n; },
861
+ get lastActivityAt() { return lastActivityAt; },
862
+ set lastActivityAt(d) { lastActivityAt = d; },
863
+ get transcript() { return transcript; },
864
+ onOutput(cb) {
865
+ outputSubscribers.add(cb);
866
+ return () => { outputSubscribers.delete(cb); };
867
+ },
868
+ onExit(cb) {
869
+ exitCallbacks.push(cb);
870
+ },
871
+ sendPrompt(prompt, _timeoutMs, _settleDelayMs) {
872
+ if (status === 'dead') {
873
+ return Promise.reject(new Error(`Session ${sid} is dead — cannot send prompt`));
874
+ }
875
+ // Lazy upgrade: replace stub with real print session on first prompt
876
+ const real = createPrintSession({
877
+ id: sid,
878
+ workdir: snapshot.workdir,
879
+ recovered: true,
880
+ model: typeof snapshot.metadata?.model === 'string' ? snapshot.metadata.model : undefined,
881
+ onEvent: eventBus ? createAgentEventAdapter(eventBus, sid, snapshot.metadata?.project_id ?? 'unknown') : undefined,
882
+ });
883
+ // Migrate subscribers
884
+ for (const sub of outputSubscribers) {
885
+ real.onOutput(sub);
886
+ }
887
+ for (const cb of exitCallbacks) {
888
+ real.onExit(cb);
889
+ }
890
+ // Replace in pool map
891
+ sessions.set(sid, real);
892
+ return real.sendPrompt(prompt, _timeoutMs, _settleDelayMs);
893
+ },
894
+ sendPromptStream(prompt, onChunk, _timeoutMs) {
895
+ if (status === 'dead') {
896
+ return Promise.reject(new Error(`Session ${sid} is dead — cannot send prompt`));
897
+ }
898
+ // Lazy upgrade: replace stub with real print session on first prompt (streaming)
899
+ const real = createPrintSession({
900
+ id: sid,
901
+ workdir: snapshot.workdir,
902
+ recovered: true,
903
+ model: typeof snapshot.metadata?.model === 'string' ? snapshot.metadata.model : undefined,
904
+ onEvent: eventBus ? createAgentEventAdapter(eventBus, sid, snapshot.metadata?.project_id ?? 'unknown') : undefined,
905
+ });
906
+ for (const sub of outputSubscribers) {
907
+ real.onOutput(sub);
908
+ }
909
+ for (const cb of exitCallbacks) {
910
+ real.onExit(cb);
911
+ }
912
+ sessions.set(sid, real);
913
+ if (typeof real.sendPromptStream === 'function') {
914
+ return real.sendPromptStream(prompt, onChunk, _timeoutMs);
915
+ }
916
+ return real.sendPrompt(prompt, _timeoutMs);
917
+ },
918
+ resize(_cols, _rows) { },
919
+ kill() {
920
+ status = 'dead';
921
+ outputSubscribers.clear();
922
+ for (const cb of exitCallbacks) {
923
+ try {
924
+ cb(0);
925
+ }
926
+ catch { /* non-fatal */ }
927
+ }
928
+ },
929
+ interrupt() { return false; },
930
+ get adaptiveSettle() { return null; },
931
+ get printMetadata() { return lastMetadata; },
932
+ };
933
+ // Hydrate all internal Maps
934
+ sessions.set(sid, stubSession);
935
+ sessionWorkdirs.set(sid, snapshot.workdir);
936
+ sessionModes.set(sid, snapshot.mode);
937
+ sessionNicknames.set(sid, snapshot.nickname);
938
+ activeNicknames.add(snapshot.nickname);
939
+ if (snapshot.purpose) {
940
+ sessionPurposes.set(sid, snapshot.purpose);
941
+ }
942
+ if (snapshot.metadata) {
943
+ sessionMetadata.set(sid, snapshot.metadata);
944
+ }
945
+ sessionChains.set(sid, {
946
+ parent_session_id: snapshot.parentSessionId ?? null,
947
+ depth: snapshot.depth,
948
+ children: [],
949
+ budget: { max_depth: DEFAULT_MAX_DEPTH, max_agents: DEFAULT_MAX_AGENTS, agents_spawned: 0 },
950
+ });
951
+ sessionWorktrees.set(sid, {
952
+ isolation: snapshot.isolation,
953
+ worktree_path: null,
954
+ worktree_branch: null,
955
+ metals_available: snapshot.isolation !== 'worktree',
956
+ });
957
+ sessionStaleFlags.set(sid, false);
958
+ sessionChannels.set(sid, createSessionChannels());
959
+ // Note: totalSpawned is NOT incremented — restored sessions don't count as newly spawned.
960
+ },
961
+ cleanupStaleCognitiveSessions() {
962
+ const killed = [];
963
+ for (const [sessionId] of sessions.entries()) {
964
+ if (sessionModes.get(sessionId) === 'cognitive-agent') {
965
+ const session = sessions.get(sessionId);
966
+ if (session && session.status !== 'dead') {
967
+ session.kill();
968
+ killed.push(sessionId);
969
+ if (eventBus) {
970
+ eventBus.emit({
971
+ version: 1,
972
+ domain: 'session',
973
+ type: 'session.killed',
974
+ severity: 'info',
975
+ sessionId,
976
+ payload: {
977
+ session_id: sessionId,
978
+ killed_by: 'startup_recovery',
979
+ reason: 'cognitive sessions are in-memory only and cannot survive a restart',
980
+ },
981
+ source: 'runtime/sessions/pool',
982
+ });
983
+ }
984
+ }
985
+ }
986
+ }
987
+ return { killed };
988
+ },
989
+ };
990
+ }
991
+ //# sourceMappingURL=pool.js.map