lorenz 0.1.5 → 0.1.7

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 (301) hide show
  1. package/README.md +83 -20
  2. package/RELEASE-MANIFEST.json +6 -1
  3. package/node_modules/@lorenz/agent-sdk/dist/index.d.ts +1 -0
  4. package/node_modules/@lorenz/agent-sdk/dist/index.d.ts.map +1 -1
  5. package/node_modules/@lorenz/agent-sdk/dist/index.js +1 -0
  6. package/node_modules/@lorenz/agent-sdk/dist/index.js.map +1 -1
  7. package/node_modules/@lorenz/agent-sdk/dist/module.d.ts +38 -0
  8. package/node_modules/@lorenz/agent-sdk/dist/module.d.ts.map +1 -0
  9. package/node_modules/@lorenz/agent-sdk/dist/module.js +41 -0
  10. package/node_modules/@lorenz/agent-sdk/dist/module.js.map +1 -0
  11. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.d.ts +30 -0
  12. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.d.ts.map +1 -0
  13. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.js +63 -0
  14. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.js.map +1 -0
  15. package/node_modules/@lorenz/cli/dist/daemon.d.ts +42 -19
  16. package/node_modules/@lorenz/cli/dist/daemon.d.ts.map +1 -1
  17. package/node_modules/@lorenz/cli/dist/daemon.js +74 -28
  18. package/node_modules/@lorenz/cli/dist/daemon.js.map +1 -1
  19. package/node_modules/@lorenz/cli/dist/daemonLock.d.ts +59 -0
  20. package/node_modules/@lorenz/cli/dist/daemonLock.d.ts.map +1 -0
  21. package/node_modules/@lorenz/cli/dist/daemonLock.js +304 -0
  22. package/node_modules/@lorenz/cli/dist/daemonLock.js.map +1 -0
  23. package/node_modules/@lorenz/cli/dist/daemonStatus.d.ts +16 -0
  24. package/node_modules/@lorenz/cli/dist/daemonStatus.d.ts.map +1 -0
  25. package/node_modules/@lorenz/cli/dist/daemonStatus.js +21 -0
  26. package/node_modules/@lorenz/cli/dist/daemonStatus.js.map +1 -0
  27. package/node_modules/@lorenz/cli/dist/doctor.d.ts +6 -0
  28. package/node_modules/@lorenz/cli/dist/doctor.d.ts.map +1 -1
  29. package/node_modules/@lorenz/cli/dist/doctor.js +38 -1
  30. package/node_modules/@lorenz/cli/dist/doctor.js.map +1 -1
  31. package/node_modules/@lorenz/cli/dist/extensionLoader.d.ts +126 -0
  32. package/node_modules/@lorenz/cli/dist/extensionLoader.d.ts.map +1 -0
  33. package/node_modules/@lorenz/cli/dist/extensionLoader.js +187 -0
  34. package/node_modules/@lorenz/cli/dist/extensionLoader.js.map +1 -0
  35. package/node_modules/@lorenz/cli/dist/flags-manifest.d.ts +42 -0
  36. package/node_modules/@lorenz/cli/dist/flags-manifest.d.ts.map +1 -0
  37. package/node_modules/@lorenz/cli/dist/flags-manifest.js +67 -0
  38. package/node_modules/@lorenz/cli/dist/flags-manifest.js.map +1 -0
  39. package/node_modules/@lorenz/cli/dist/index.d.ts +6 -0
  40. package/node_modules/@lorenz/cli/dist/index.d.ts.map +1 -1
  41. package/node_modules/@lorenz/cli/dist/index.js +4 -0
  42. package/node_modules/@lorenz/cli/dist/index.js.map +1 -1
  43. package/node_modules/@lorenz/cli/dist/leadershipStore.d.ts +42 -0
  44. package/node_modules/@lorenz/cli/dist/leadershipStore.d.ts.map +1 -0
  45. package/node_modules/@lorenz/cli/dist/leadershipStore.js +2 -0
  46. package/node_modules/@lorenz/cli/dist/leadershipStore.js.map +1 -0
  47. package/node_modules/@lorenz/cli/dist/main.d.ts +11 -7
  48. package/node_modules/@lorenz/cli/dist/main.d.ts.map +1 -1
  49. package/node_modules/@lorenz/cli/dist/main.js +58 -8
  50. package/node_modules/@lorenz/cli/dist/main.js.map +1 -1
  51. package/node_modules/@lorenz/cli/dist/toolLoader.d.ts +28 -0
  52. package/node_modules/@lorenz/cli/dist/toolLoader.d.ts.map +1 -0
  53. package/node_modules/@lorenz/cli/dist/toolLoader.js +62 -0
  54. package/node_modules/@lorenz/cli/dist/toolLoader.js.map +1 -0
  55. package/node_modules/@lorenz/cli/dist/trackerLoader.d.ts +24 -0
  56. package/node_modules/@lorenz/cli/dist/trackerLoader.d.ts.map +1 -0
  57. package/node_modules/@lorenz/cli/dist/trackerLoader.js +34 -0
  58. package/node_modules/@lorenz/cli/dist/trackerLoader.js.map +1 -0
  59. package/node_modules/@lorenz/cli/dist/workerDriverLoader.d.ts +15 -55
  60. package/node_modules/@lorenz/cli/dist/workerDriverLoader.d.ts.map +1 -1
  61. package/node_modules/@lorenz/cli/dist/workerDriverLoader.js +26 -203
  62. package/node_modules/@lorenz/cli/dist/workerDriverLoader.js.map +1 -1
  63. package/node_modules/@lorenz/cli/package.json +1 -0
  64. package/node_modules/@lorenz/config/dist/index.d.ts +1 -1
  65. package/node_modules/@lorenz/config/dist/index.d.ts.map +1 -1
  66. package/node_modules/@lorenz/config/dist/index.js +1 -1
  67. package/node_modules/@lorenz/config/dist/index.js.map +1 -1
  68. package/node_modules/@lorenz/config/dist/parse.d.ts +17 -0
  69. package/node_modules/@lorenz/config/dist/parse.d.ts.map +1 -1
  70. package/node_modules/@lorenz/config/dist/parse.js +107 -11
  71. package/node_modules/@lorenz/config/dist/parse.js.map +1 -1
  72. package/node_modules/@lorenz/config/dist/schemas.d.ts +0 -2
  73. package/node_modules/@lorenz/config/dist/schemas.d.ts.map +1 -1
  74. package/node_modules/@lorenz/config/dist/schemas.js +5 -1
  75. package/node_modules/@lorenz/config/dist/schemas.js.map +1 -1
  76. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.d.ts +55 -21
  77. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.d.ts.map +1 -1
  78. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.js +187 -82
  79. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.js.map +1 -1
  80. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.d.ts +6 -4
  81. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.d.ts.map +1 -1
  82. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.js +9 -6
  83. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.js.map +1 -1
  84. package/node_modules/@lorenz/dispatch-coordinator/dist/index.d.ts +1 -1
  85. package/node_modules/@lorenz/dispatch-coordinator/dist/index.d.ts.map +1 -1
  86. package/node_modules/@lorenz/dispatch-coordinator/dist/index.js +5 -6
  87. package/node_modules/@lorenz/dispatch-coordinator/dist/index.js.map +1 -1
  88. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.d.ts +7 -5
  89. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.d.ts.map +1 -1
  90. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.js +12 -10
  91. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.js.map +1 -1
  92. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.d.ts +11 -10
  93. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.d.ts.map +1 -1
  94. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.js +15 -22
  95. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.js.map +1 -1
  96. package/node_modules/@lorenz/dispatch-coordinator/dist/types.d.ts +16 -15
  97. package/node_modules/@lorenz/dispatch-coordinator/dist/types.d.ts.map +1 -1
  98. package/node_modules/@lorenz/dispatch-coordinator/dist/types.js +6 -7
  99. package/node_modules/@lorenz/dispatch-coordinator/dist/types.js.map +1 -1
  100. package/node_modules/@lorenz/domain/dist/index.d.ts +75 -9
  101. package/node_modules/@lorenz/domain/dist/index.d.ts.map +1 -1
  102. package/node_modules/@lorenz/domain/dist/index.js +40 -0
  103. package/node_modules/@lorenz/domain/dist/index.js.map +1 -1
  104. package/node_modules/@lorenz/flags/dist/coerce.d.ts +12 -0
  105. package/node_modules/@lorenz/flags/dist/coerce.d.ts.map +1 -0
  106. package/node_modules/@lorenz/flags/dist/coerce.js +44 -0
  107. package/node_modules/@lorenz/flags/dist/coerce.js.map +1 -0
  108. package/node_modules/@lorenz/flags/dist/default.d.ts +6 -0
  109. package/node_modules/@lorenz/flags/dist/default.d.ts.map +1 -0
  110. package/node_modules/@lorenz/flags/dist/default.js +22 -0
  111. package/node_modules/@lorenz/flags/dist/default.js.map +1 -0
  112. package/node_modules/@lorenz/flags/dist/deprecations.d.ts +20 -0
  113. package/node_modules/@lorenz/flags/dist/deprecations.d.ts.map +1 -0
  114. package/node_modules/@lorenz/flags/dist/deprecations.js +42 -0
  115. package/node_modules/@lorenz/flags/dist/deprecations.js.map +1 -0
  116. package/node_modules/@lorenz/flags/dist/env.d.ts +17 -0
  117. package/node_modules/@lorenz/flags/dist/env.d.ts.map +1 -0
  118. package/node_modules/@lorenz/flags/dist/env.js +90 -0
  119. package/node_modules/@lorenz/flags/dist/env.js.map +1 -0
  120. package/node_modules/@lorenz/flags/dist/errors.d.ts +22 -0
  121. package/node_modules/@lorenz/flags/dist/errors.d.ts.map +1 -0
  122. package/node_modules/@lorenz/flags/dist/errors.js +61 -0
  123. package/node_modules/@lorenz/flags/dist/errors.js.map +1 -0
  124. package/node_modules/@lorenz/flags/dist/index.d.ts +8 -0
  125. package/node_modules/@lorenz/flags/dist/index.d.ts.map +1 -0
  126. package/node_modules/@lorenz/flags/dist/index.js +11 -0
  127. package/node_modules/@lorenz/flags/dist/index.js.map +1 -0
  128. package/node_modules/@lorenz/flags/dist/keys.d.ts +6 -0
  129. package/node_modules/@lorenz/flags/dist/keys.d.ts.map +1 -0
  130. package/node_modules/@lorenz/flags/dist/keys.js +15 -0
  131. package/node_modules/@lorenz/flags/dist/keys.js.map +1 -0
  132. package/node_modules/@lorenz/flags/dist/layers.d.ts +14 -0
  133. package/node_modules/@lorenz/flags/dist/layers.d.ts.map +1 -0
  134. package/node_modules/@lorenz/flags/dist/layers.js +107 -0
  135. package/node_modules/@lorenz/flags/dist/layers.js.map +1 -0
  136. package/node_modules/@lorenz/flags/dist/manifest.d.ts +71 -0
  137. package/node_modules/@lorenz/flags/dist/manifest.d.ts.map +1 -0
  138. package/node_modules/@lorenz/flags/dist/manifest.js +137 -0
  139. package/node_modules/@lorenz/flags/dist/manifest.js.map +1 -0
  140. package/node_modules/@lorenz/flags/dist/resolve.d.ts +8 -0
  141. package/node_modules/@lorenz/flags/dist/resolve.d.ts.map +1 -0
  142. package/node_modules/@lorenz/flags/dist/resolve.js +178 -0
  143. package/node_modules/@lorenz/flags/dist/resolve.js.map +1 -0
  144. package/node_modules/@lorenz/flags/dist/testing.d.ts +19 -0
  145. package/node_modules/@lorenz/flags/dist/testing.d.ts.map +1 -0
  146. package/node_modules/@lorenz/flags/dist/testing.js +68 -0
  147. package/node_modules/@lorenz/flags/dist/testing.js.map +1 -0
  148. package/node_modules/@lorenz/flags/dist/types.d.ts +93 -0
  149. package/node_modules/@lorenz/flags/dist/types.d.ts.map +1 -0
  150. package/node_modules/@lorenz/flags/dist/types.js +2 -0
  151. package/node_modules/@lorenz/flags/dist/types.js.map +1 -0
  152. package/node_modules/@lorenz/flags/package.json +16 -0
  153. package/node_modules/@lorenz/jira-tracker/dist/index.d.ts +1 -0
  154. package/node_modules/@lorenz/jira-tracker/dist/index.d.ts.map +1 -1
  155. package/node_modules/@lorenz/jira-tracker/dist/index.js +1 -0
  156. package/node_modules/@lorenz/jira-tracker/dist/index.js.map +1 -1
  157. package/node_modules/@lorenz/jira-tracker/dist/provider.d.ts.map +1 -1
  158. package/node_modules/@lorenz/jira-tracker/dist/provider.js +3 -36
  159. package/node_modules/@lorenz/jira-tracker/dist/provider.js.map +1 -1
  160. package/node_modules/@lorenz/jira-tracker/dist/register.d.ts +5 -3
  161. package/node_modules/@lorenz/jira-tracker/dist/register.d.ts.map +1 -1
  162. package/node_modules/@lorenz/jira-tracker/dist/register.js +9 -3
  163. package/node_modules/@lorenz/jira-tracker/dist/register.js.map +1 -1
  164. package/node_modules/@lorenz/jira-tracker/dist/tools.d.ts +18 -0
  165. package/node_modules/@lorenz/jira-tracker/dist/tools.d.ts.map +1 -0
  166. package/node_modules/@lorenz/{tracker-sdk/dist/toolPack.js → jira-tracker/dist/tools.js} +76 -78
  167. package/node_modules/@lorenz/jira-tracker/dist/tools.js.map +1 -0
  168. package/node_modules/@lorenz/jira-tracker/package.json +1 -0
  169. package/node_modules/@lorenz/linear-tracker/dist/provider.d.ts.map +1 -1
  170. package/node_modules/@lorenz/linear-tracker/dist/provider.js +0 -2
  171. package/node_modules/@lorenz/linear-tracker/dist/provider.js.map +1 -1
  172. package/node_modules/@lorenz/local-tracker/dist/provider.d.ts.map +1 -1
  173. package/node_modules/@lorenz/local-tracker/dist/provider.js +0 -2
  174. package/node_modules/@lorenz/local-tracker/dist/provider.js.map +1 -1
  175. package/node_modules/@lorenz/mcp/dist/agentEndpoint.d.ts +16 -3
  176. package/node_modules/@lorenz/mcp/dist/agentEndpoint.d.ts.map +1 -1
  177. package/node_modules/@lorenz/mcp/dist/agentEndpoint.js +105 -17
  178. package/node_modules/@lorenz/mcp/dist/agentEndpoint.js.map +1 -1
  179. package/node_modules/@lorenz/mcp/dist/auth.d.ts +88 -0
  180. package/node_modules/@lorenz/mcp/dist/auth.d.ts.map +1 -1
  181. package/node_modules/@lorenz/mcp/dist/auth.js +53 -0
  182. package/node_modules/@lorenz/mcp/dist/auth.js.map +1 -1
  183. package/node_modules/@lorenz/mcp/dist/index.d.ts +3 -2
  184. package/node_modules/@lorenz/mcp/dist/index.d.ts.map +1 -1
  185. package/node_modules/@lorenz/mcp/dist/index.js +1 -1
  186. package/node_modules/@lorenz/mcp/dist/index.js.map +1 -1
  187. package/node_modules/@lorenz/mcp/dist/server.d.ts +22 -0
  188. package/node_modules/@lorenz/mcp/dist/server.d.ts.map +1 -1
  189. package/node_modules/@lorenz/mcp/dist/server.js +85 -12
  190. package/node_modules/@lorenz/mcp/dist/server.js.map +1 -1
  191. package/node_modules/@lorenz/mcp/dist/tools.d.ts.map +1 -1
  192. package/node_modules/@lorenz/mcp/dist/tools.js +5 -8
  193. package/node_modules/@lorenz/mcp/dist/tools.js.map +1 -1
  194. package/node_modules/@lorenz/orchestrator/dist/claimStore.d.ts +157 -0
  195. package/node_modules/@lorenz/orchestrator/dist/claimStore.d.ts.map +1 -0
  196. package/node_modules/@lorenz/orchestrator/dist/claimStore.js +621 -0
  197. package/node_modules/@lorenz/orchestrator/dist/claimStore.js.map +1 -0
  198. package/node_modules/@lorenz/orchestrator/dist/codec.d.ts +38 -0
  199. package/node_modules/@lorenz/orchestrator/dist/codec.d.ts.map +1 -0
  200. package/node_modules/@lorenz/orchestrator/dist/codec.js +176 -0
  201. package/node_modules/@lorenz/orchestrator/dist/codec.js.map +1 -0
  202. package/node_modules/@lorenz/orchestrator/dist/index.d.ts +55 -51
  203. package/node_modules/@lorenz/orchestrator/dist/index.d.ts.map +1 -1
  204. package/node_modules/@lorenz/orchestrator/dist/index.js +285 -45
  205. package/node_modules/@lorenz/orchestrator/dist/index.js.map +1 -1
  206. package/node_modules/@lorenz/orchestrator/dist/sqlite.d.ts +34 -0
  207. package/node_modules/@lorenz/orchestrator/dist/sqlite.d.ts.map +1 -0
  208. package/node_modules/@lorenz/orchestrator/dist/sqlite.js +142 -0
  209. package/node_modules/@lorenz/orchestrator/dist/sqlite.js.map +1 -0
  210. package/node_modules/@lorenz/orchestrator/dist/state.d.ts +47 -0
  211. package/node_modules/@lorenz/orchestrator/dist/state.d.ts.map +1 -0
  212. package/node_modules/@lorenz/orchestrator/dist/state.js +15 -0
  213. package/node_modules/@lorenz/orchestrator/dist/state.js.map +1 -0
  214. package/node_modules/@lorenz/orchestrator/dist/turso.d.ts +28 -0
  215. package/node_modules/@lorenz/orchestrator/dist/turso.d.ts.map +1 -0
  216. package/node_modules/@lorenz/orchestrator/dist/turso.js +125 -0
  217. package/node_modules/@lorenz/orchestrator/dist/turso.js.map +1 -0
  218. package/node_modules/@lorenz/orchestrator/package.json +6 -2
  219. package/node_modules/@lorenz/presenter/dist/index.d.ts +14 -0
  220. package/node_modules/@lorenz/presenter/dist/index.d.ts.map +1 -1
  221. package/node_modules/@lorenz/presenter/dist/index.js +18 -0
  222. package/node_modules/@lorenz/presenter/dist/index.js.map +1 -1
  223. package/node_modules/@lorenz/projections/dist/index.d.ts.map +1 -1
  224. package/node_modules/@lorenz/projections/dist/index.js +1 -0
  225. package/node_modules/@lorenz/projections/dist/index.js.map +1 -1
  226. package/node_modules/@lorenz/runtime/dist/index.d.ts +27 -8
  227. package/node_modules/@lorenz/runtime/dist/index.d.ts.map +1 -1
  228. package/node_modules/@lorenz/runtime/dist/index.js +422 -98
  229. package/node_modules/@lorenz/runtime/dist/index.js.map +1 -1
  230. package/node_modules/@lorenz/runtime-events/dist/index.d.ts +14 -0
  231. package/node_modules/@lorenz/runtime-events/dist/index.d.ts.map +1 -1
  232. package/node_modules/@lorenz/slack-tracker/dist/client.d.ts +0 -7
  233. package/node_modules/@lorenz/slack-tracker/dist/client.d.ts.map +1 -1
  234. package/node_modules/@lorenz/slack-tracker/dist/client.js +4 -5
  235. package/node_modules/@lorenz/slack-tracker/dist/client.js.map +1 -1
  236. package/node_modules/@lorenz/slack-tracker/dist/index.d.ts +0 -1
  237. package/node_modules/@lorenz/slack-tracker/dist/index.d.ts.map +1 -1
  238. package/node_modules/@lorenz/slack-tracker/dist/index.js +0 -1
  239. package/node_modules/@lorenz/slack-tracker/dist/index.js.map +1 -1
  240. package/node_modules/@lorenz/slack-tracker/dist/provider.d.ts.map +1 -1
  241. package/node_modules/@lorenz/slack-tracker/dist/provider.js +0 -2
  242. package/node_modules/@lorenz/slack-tracker/dist/provider.js.map +1 -1
  243. package/node_modules/@lorenz/ssh/dist/index.d.ts +2 -0
  244. package/node_modules/@lorenz/ssh/dist/index.d.ts.map +1 -1
  245. package/node_modules/@lorenz/ssh/dist/index.js +2 -1
  246. package/node_modules/@lorenz/ssh/dist/index.js.map +1 -1
  247. package/node_modules/@lorenz/tool-sdk/dist/index.d.ts +1 -0
  248. package/node_modules/@lorenz/tool-sdk/dist/index.d.ts.map +1 -1
  249. package/node_modules/@lorenz/tool-sdk/dist/index.js +1 -0
  250. package/node_modules/@lorenz/tool-sdk/dist/index.js.map +1 -1
  251. package/node_modules/@lorenz/tool-sdk/dist/module.d.ts +38 -0
  252. package/node_modules/@lorenz/tool-sdk/dist/module.d.ts.map +1 -0
  253. package/node_modules/@lorenz/tool-sdk/dist/module.js +42 -0
  254. package/node_modules/@lorenz/tool-sdk/dist/module.js.map +1 -0
  255. package/node_modules/@lorenz/tracker-sdk/dist/index.d.ts +2 -2
  256. package/node_modules/@lorenz/tracker-sdk/dist/index.d.ts.map +1 -1
  257. package/node_modules/@lorenz/tracker-sdk/dist/index.js +1 -1
  258. package/node_modules/@lorenz/tracker-sdk/dist/index.js.map +1 -1
  259. package/node_modules/@lorenz/tracker-sdk/dist/module.d.ts +37 -0
  260. package/node_modules/@lorenz/tracker-sdk/dist/module.d.ts.map +1 -0
  261. package/node_modules/@lorenz/tracker-sdk/dist/module.js +38 -0
  262. package/node_modules/@lorenz/tracker-sdk/dist/module.js.map +1 -0
  263. package/node_modules/@lorenz/tracker-sdk/dist/provider.d.ts +11 -55
  264. package/node_modules/@lorenz/tracker-sdk/dist/provider.d.ts.map +1 -1
  265. package/node_modules/@lorenz/tracker-sdk/package.json +1 -2
  266. package/node_modules/@lorenz/worker-host-pool/dist/index.d.ts +34 -6
  267. package/node_modules/@lorenz/worker-host-pool/dist/index.d.ts.map +1 -1
  268. package/node_modules/@lorenz/worker-host-pool/dist/index.js +110 -143
  269. package/node_modules/@lorenz/worker-host-pool/dist/index.js.map +1 -1
  270. package/node_modules/@lorenz/worker-sdk/dist/index.d.ts +1 -0
  271. package/node_modules/@lorenz/worker-sdk/dist/index.d.ts.map +1 -1
  272. package/node_modules/@lorenz/worker-sdk/dist/index.js +1 -0
  273. package/node_modules/@lorenz/worker-sdk/dist/index.js.map +1 -1
  274. package/node_modules/@lorenz/worker-sdk/dist/local.d.ts +74 -0
  275. package/node_modules/@lorenz/worker-sdk/dist/local.d.ts.map +1 -0
  276. package/node_modules/@lorenz/worker-sdk/dist/local.js +112 -0
  277. package/node_modules/@lorenz/worker-sdk/dist/local.js.map +1 -0
  278. package/node_modules/@lorenz/worker-sdk/dist/module.d.ts +8 -16
  279. package/node_modules/@lorenz/worker-sdk/dist/module.d.ts.map +1 -1
  280. package/node_modules/@lorenz/worker-sdk/dist/module.js +15 -35
  281. package/node_modules/@lorenz/worker-sdk/dist/module.js.map +1 -1
  282. package/node_modules/@lorenz/workflow/dist/index.d.ts +11 -0
  283. package/node_modules/@lorenz/workflow/dist/index.d.ts.map +1 -1
  284. package/node_modules/@lorenz/workflow/dist/index.js +3 -0
  285. package/node_modules/@lorenz/workflow/dist/index.js.map +1 -1
  286. package/package.json +4 -1
  287. package/node_modules/@lorenz/linear-tracker/dist/toolOps.d.ts +0 -8
  288. package/node_modules/@lorenz/linear-tracker/dist/toolOps.d.ts.map +0 -1
  289. package/node_modules/@lorenz/linear-tracker/dist/toolOps.js +0 -251
  290. package/node_modules/@lorenz/linear-tracker/dist/toolOps.js.map +0 -1
  291. package/node_modules/@lorenz/local-tracker/dist/toolOps.d.ts +0 -9
  292. package/node_modules/@lorenz/local-tracker/dist/toolOps.d.ts.map +0 -1
  293. package/node_modules/@lorenz/local-tracker/dist/toolOps.js +0 -86
  294. package/node_modules/@lorenz/local-tracker/dist/toolOps.js.map +0 -1
  295. package/node_modules/@lorenz/slack-tracker/dist/toolOps.d.ts +0 -13
  296. package/node_modules/@lorenz/slack-tracker/dist/toolOps.d.ts.map +0 -1
  297. package/node_modules/@lorenz/slack-tracker/dist/toolOps.js +0 -76
  298. package/node_modules/@lorenz/slack-tracker/dist/toolOps.js.map +0 -1
  299. package/node_modules/@lorenz/tracker-sdk/dist/toolPack.d.ts +0 -10
  300. package/node_modules/@lorenz/tracker-sdk/dist/toolPack.d.ts.map +0 -1
  301. package/node_modules/@lorenz/tracker-sdk/dist/toolPack.js.map +0 -1
@@ -28,6 +28,7 @@ const POISON_WORKER_ERROR_PREFIXES = [
28
28
  // `hook failed with status N` (no `workspace ` prefix) and stays healthy.
29
29
  "workspace hook failed with status ",
30
30
  ];
31
+ const CLAIM_OWNER_HEARTBEAT_INTERVAL_MS = 10_000;
31
32
  export function classifyWorkerOutcome(error) {
32
33
  const message = error instanceof Error ? error.message : String(error);
33
34
  return POISON_WORKER_ERROR_PREFIXES.some((prefix) => message.startsWith(prefix))
@@ -64,7 +65,21 @@ function mergePollOptions(existing, requested) {
64
65
  waitForRuns: existingIntent.waitForRuns || requestedIntent.waitForRuns,
65
66
  });
66
67
  }
68
+ class ClaimStoreRuntimeError extends Error {
69
+ reason;
70
+ original;
71
+ constructor(reason, original) {
72
+ super(errorMessage(original));
73
+ this.reason = reason;
74
+ this.original = original;
75
+ }
76
+ }
77
+ function throwRuntimeError(error) {
78
+ throw error;
79
+ }
67
80
  class ActiveRunHandle {
81
+ issueId;
82
+ slotIndex;
68
83
  key;
69
84
  runId;
70
85
  activeRuns;
@@ -75,7 +90,10 @@ class ActiveRunHandle {
75
90
  * generic `agent_run_aborted` (which would otherwise classify as healthy).
76
91
  */
77
92
  reason = null;
78
- constructor(key, runId, activeRuns) {
93
+ abandonClaimOnSettlement = false;
94
+ constructor(issueId, slotIndex, key, runId, activeRuns) {
95
+ this.issueId = issueId;
96
+ this.slotIndex = slotIndex;
79
97
  this.key = key;
80
98
  this.runId = runId;
81
99
  this.activeRuns = activeRuns;
@@ -89,9 +107,11 @@ class ActiveRunHandle {
89
107
  abort() {
90
108
  this.controller.abort();
91
109
  }
92
- finishExternally(reason = null) {
110
+ finishExternally(reason = null, options = {}) {
93
111
  if (reason)
94
112
  this.reason = reason;
113
+ if (options.abandonClaimOnSettlement)
114
+ this.abandonClaimOnSettlement = true;
95
115
  this.abort();
96
116
  this.release();
97
117
  }
@@ -126,6 +146,8 @@ export class LorenzRuntime {
126
146
  activePollOptions = null;
127
147
  pendingPollOptions = null;
128
148
  workerPoolDrained = false;
149
+ claimOwnerHeartbeatTimer = null;
150
+ pendingStoppedClaimSettlements = 0;
129
151
  /**
130
152
  * Live tracker push subscription (see {@link RuntimeTrackerClient.watch}), opened once in the
131
153
  * recurring `start()` loop and closed on `stop()`. `undefined` for pull-only trackers and the
@@ -135,11 +157,10 @@ export class LorenzRuntime {
135
157
  changeStream;
136
158
  changeStreamOpening = false;
137
159
  /**
138
- * The reload-surviving coordinator singleton. Built ONCE here: either the
160
+ * The reload-surviving coordinator singleton. Built here from either the
139
161
  * pre-built `input.coordinator` (preferred), or a null-endpoint passthrough
140
- * wrapping a bare `input.workerPool` (the low-churn path that keeps every existing
141
- * workerPool-injecting site byte-identical at the runtime boundary). `undefined`
142
- * when neither is supplied (the static/local path, byte-identical to today).
162
+ * wrapping a bare `input.workerPool`, which keeps the default runtime boundary unchanged.
163
+ * `undefined` when neither is supplied, which uses the static/local path.
143
164
  */
144
165
  coordinator;
145
166
  constructor(input) {
@@ -157,7 +178,7 @@ export class LorenzRuntime {
157
178
  const coordinator = this.coordinator;
158
179
  this.orchestrator =
159
180
  input.orchestrator ??
160
- new Orchestrator(input.workflow.settings, this.clock, undefined,
181
+ new Orchestrator(input.workflow.settings, this.clock, input.claimStore,
161
182
  // The coordinator IS the orchestrator's capacity authority (it satisfies
162
183
  // the CapacityProbe shape directly). It is installed for the orchestrator's
163
184
  // lifetime whenever it exists, but a reload can disable the underlying pool
@@ -208,6 +229,7 @@ export class LorenzRuntime {
208
229
  blocked: orchestration.blocked.map((entry) => ({ ...entry })),
209
230
  usageTotals: orchestration.usageTotals,
210
231
  rateLimits: orchestration.rateLimits,
232
+ claimStore: orchestration.claimStore,
211
233
  logFile: this.workflow.settings.logging.logFile,
212
234
  });
213
235
  }
@@ -246,9 +268,14 @@ export class LorenzRuntime {
246
268
  void this.closeChangeStream();
247
269
  // finishExternally (abort + release) mirrors the other abort sites and clears
248
270
  // isActive, so the resulting agent_run_aborted rejection is treated as a clean
249
- // shutdown in runClaim rather than recorded as a failed run.
250
- for (const handle of [...this.activeRuns.values()])
251
- handle.finishExternally();
271
+ // shutdown in runClaim rather than recorded as a failed run. Durable claims are
272
+ // abandoned only after the runner settles; until then a shared store must still
273
+ // show the slot as owned.
274
+ for (const handle of [...this.activeRuns.values()]) {
275
+ this.markStoppedClaimSettlementPending(handle);
276
+ handle.finishExternally(null, { abandonClaimOnSettlement: true });
277
+ }
278
+ this.stopClaimOwnerHeartbeatIfIdle();
252
279
  this.retryScheduler.stop();
253
280
  this.emit();
254
281
  }
@@ -390,16 +417,16 @@ export class LorenzRuntime {
390
417
  this.appStatus = this.inFlight.size > 0 ? "running" : "polling";
391
418
  this.lastPollAt = this.clock.now().toISOString();
392
419
  this.lastError = null;
393
- this.emit();
394
420
  const dispatched = [];
395
421
  try {
422
+ this.emit();
396
423
  await this.reloadWorkflowIfConfigured();
397
424
  this.validateDispatch(this.workflow.settings);
398
425
  await this.cleanupTerminalWorkspacesOnce();
399
- this.reconcileStalledRuns();
426
+ await this.reconcileStalledRuns();
400
427
  await this.reconcileTrackedIssues();
401
428
  const issues = await this.client.fetchCandidateIssues();
402
- const eligibleIssues = this.orchestrator.eligibleIssues(issues);
429
+ const eligibleIssues = await this.orchestrator.eligibleIssuesAsync(issues);
403
430
  if (!options.dryRun)
404
431
  this.syncRetryTimersForIssues(issues);
405
432
  this.candidates = issues.length;
@@ -416,7 +443,7 @@ export class LorenzRuntime {
416
443
  await Promise.allSettled(dispatched);
417
444
  }
418
445
  this.pollStatus = "idle";
419
- this.appStatus = this.inFlight.size > 0 ? "running" : "idle";
446
+ this.updateAppStatusFromInFlight();
420
447
  this.nextPollAt = new Date(this.clock.now().getTime() + this.workflow.settings.polling.intervalMs).toISOString();
421
448
  }
422
449
  catch (error) {
@@ -436,12 +463,11 @@ export class LorenzRuntime {
436
463
  this.addEvent("dispatch_skipped", `${issue.identifier} missing_before_dispatch`);
437
464
  return [];
438
465
  }
439
- const claim = this.orchestrator.claim(refreshed);
466
+ const claim = await this.orchestrator.claimAsync(refreshed);
440
467
  if (!claim) {
441
468
  this.addEvent("dispatch_skipped", `${refreshed.identifier} stale_before_dispatch`);
442
469
  return [];
443
470
  }
444
- this.syncRetryTimer(refreshed.id);
445
471
  const slotIndex = claim.kind === "running" ? claim.entry.slotIndex : claim.reservation.slotIndex;
446
472
  const key = slotKey(refreshed.id, slotIndex);
447
473
  const runId = `run-${this.nextRunNumber}`;
@@ -449,26 +475,44 @@ export class LorenzRuntime {
449
475
  // The handle is registered for the WHOLE run lifecycle - including the reserved
450
476
  // path's acquire window - so stop()/reconcile abort an in-acquire run (the
451
477
  // signal reaches the pool's FIFO waiter) exactly as they abort a running one.
452
- const handle = new ActiveRunHandle(key, runId, this.activeRuns);
478
+ const handle = new ActiveRunHandle(refreshed.id, slotIndex, key, runId, this.activeRuns);
453
479
  this.activeRuns.set(key, handle);
454
- // On the static/local path the run starts immediately. On the pool-governed
455
- // path run_reserving marks dispatch intent and run_started moves AFTER
456
- // bindReservation (inside runReservedClaim): a capacity-refused dispatch
457
- // never emits a phantom run_started.
458
- if (claim.kind === "running") {
459
- this.addEvent("run_started", `${refreshed.identifier} slot=${slotIndex}`);
480
+ try {
481
+ this.syncRetryTimer(refreshed.id);
482
+ await this.startClaimOwnerHeartbeat();
483
+ // On the static/local path the run starts immediately. On the pool-governed
484
+ // path run_reserving marks dispatch intent and run_started moves AFTER
485
+ // bindReservation (inside runReservedClaim): a capacity-refused dispatch
486
+ // never emits a phantom run_started.
487
+ if (claim.kind === "running") {
488
+ this.addEvent("run_started", `${refreshed.identifier} slot=${slotIndex}`);
489
+ }
490
+ else {
491
+ this.addEvent("run_reserving", `${refreshed.identifier} slot=${slotIndex}`);
492
+ }
493
+ this.input.onIssueDispatched?.(refreshed);
460
494
  }
461
- else {
462
- this.addEvent("run_reserving", `${refreshed.identifier} slot=${slotIndex}`);
495
+ catch (error) {
496
+ try {
497
+ await this.orchestrator.abandonClaimAsync(refreshed.id, slotIndex);
498
+ }
499
+ catch {
500
+ // Preserve the heartbeat failure; if the backend is unavailable, abandon may fail too.
501
+ }
502
+ finally {
503
+ handle.release();
504
+ this.stopClaimOwnerHeartbeatIfIdle();
505
+ }
506
+ throw error;
463
507
  }
464
- this.input.onIssueDispatched?.(refreshed);
465
508
  const run = claim.kind === "running"
466
509
  ? this.runClaim(refreshed, claim.entry.slotIndex, claim.entry.agentKind, runId, claim.entry.workerHost ?? null, handle)
467
510
  : this.runReservedClaim(refreshed, claim.reservation, runId, handle);
468
511
  this.inFlight.add(run);
469
512
  void run.finally(() => {
470
513
  this.inFlight.delete(run);
471
- this.appStatus = this.inFlight.size > 0 ? "running" : "idle";
514
+ this.stopClaimOwnerHeartbeatIfIdle();
515
+ this.updateAppStatusFromInFlight();
472
516
  this.emit();
473
517
  });
474
518
  this.emit();
@@ -484,6 +528,62 @@ export class LorenzRuntime {
484
528
  return null;
485
529
  }
486
530
  }
531
+ async startClaimOwnerHeartbeat() {
532
+ await this.orchestrator.heartbeatClaimOwnerAsync();
533
+ if (this.claimOwnerHeartbeatTimer)
534
+ return;
535
+ this.claimOwnerHeartbeatTimer = this.clock.setTimeout(() => {
536
+ void this.heartbeatClaimOwnerWhileActive();
537
+ }, CLAIM_OWNER_HEARTBEAT_INTERVAL_MS);
538
+ this.claimOwnerHeartbeatTimer.unref?.();
539
+ }
540
+ async heartbeatClaimOwnerWhileActive() {
541
+ this.claimOwnerHeartbeatTimer = null;
542
+ if (this.activeRuns.size === 0 && this.pendingStoppedClaimSettlements === 0)
543
+ return;
544
+ try {
545
+ await this.orchestrator.heartbeatClaimOwnerAsync();
546
+ }
547
+ catch (error) {
548
+ this.handleClaimOwnerHeartbeatFailure(error);
549
+ }
550
+ if (this.activeRuns.size === 0 && this.pendingStoppedClaimSettlements === 0)
551
+ return;
552
+ this.claimOwnerHeartbeatTimer = this.clock.setTimeout(() => {
553
+ void this.heartbeatClaimOwnerWhileActive();
554
+ }, CLAIM_OWNER_HEARTBEAT_INTERVAL_MS);
555
+ this.claimOwnerHeartbeatTimer.unref?.();
556
+ }
557
+ handleClaimOwnerHeartbeatFailure(error) {
558
+ const message = `claim_owner_heartbeat_failed ${errorMessage(error)}`;
559
+ this.stopped = true;
560
+ this.appStatus = "error";
561
+ this.lastError = message;
562
+ for (const handle of [...this.activeRuns.values()]) {
563
+ this.markStoppedClaimSettlementPending(handle);
564
+ handle.finishExternally(null, { abandonClaimOnSettlement: true });
565
+ }
566
+ this.retryScheduler.stop();
567
+ this.addEvent("poll_error", message);
568
+ }
569
+ stopClaimOwnerHeartbeatIfIdle() {
570
+ if (this.activeRuns.size > 0)
571
+ return;
572
+ if (this.pendingStoppedClaimSettlements > 0)
573
+ return;
574
+ this.stopClaimOwnerHeartbeat();
575
+ }
576
+ stopClaimOwnerHeartbeat() {
577
+ if (!this.claimOwnerHeartbeatTimer)
578
+ return;
579
+ this.clock.clearTimeout(this.claimOwnerHeartbeatTimer);
580
+ this.claimOwnerHeartbeatTimer = null;
581
+ }
582
+ updateAppStatusFromInFlight() {
583
+ if (this.appStatus === "error")
584
+ return;
585
+ this.appStatus = this.inFlight.size > 0 ? "running" : "idle";
586
+ }
487
587
  /**
488
588
  * Phase 1 -> negotiation -> phase 2 for a pool-governed (reserved) claim: drive the
489
589
  * coordinator's acquire inside this detached per-run promise (a cold provision never blocks
@@ -498,8 +598,9 @@ export class LorenzRuntime {
498
598
  // production implies a coordinator. An injected probe without one (test
499
599
  // wiring) is treated like an acquire fault: cancel and skip, never strand.
500
600
  this.addEvent("dispatch_skipped", `${issue.identifier} worker_pool_acquire_error coordinator_missing`);
501
- this.orchestrator.cancelReservation(reservation);
502
- handle.release();
601
+ await this.cancelReservationAfterSkippedAcquire(issue, reservation, handle, {
602
+ syncRetryTimer: true,
603
+ });
503
604
  return;
504
605
  }
505
606
  let acquired;
@@ -535,9 +636,9 @@ export class LorenzRuntime {
535
636
  // coordinator already settled any just-bound lease healthy before throwing,
536
637
  // so there is nothing to settle here.
537
638
  this.addEvent("dispatch_skipped", `${issue.identifier} worker_pool_acquire_error ${errorMessage(error)}`);
538
- this.orchestrator.cancelReservation(reservation);
539
- this.syncRetryTimer(issue.id);
540
- handle.release();
639
+ await this.cancelReservationAfterSkippedAcquire(issue, reservation, handle, {
640
+ syncRetryTimer: true,
641
+ });
541
642
  return;
542
643
  }
543
644
  if (acquired.status !== "bound") {
@@ -548,13 +649,51 @@ export class LorenzRuntime {
548
649
  // affinity and attempt counter intact; never record history for a run that
549
650
  // did not start.
550
651
  this.addEvent("dispatch_skipped", `${issue.identifier} worker_host_capacity`);
551
- this.orchestrator.cancelReservation(reservation);
552
- this.syncRetryTimer(issue.id);
553
- handle.release();
652
+ await this.cancelReservationAfterSkippedAcquire(issue, reservation, handle, {
653
+ syncRetryTimer: true,
654
+ });
554
655
  return;
555
656
  }
556
657
  const slot = acquired.slot;
557
- const entry = this.orchestrator.bindReservation(reservation, slot.workerHost);
658
+ let entry;
659
+ try {
660
+ entry = await this.orchestrator.bindReservationAsync(reservation, slot.workerHost);
661
+ }
662
+ catch (error) {
663
+ const bindError = errorMessage(error);
664
+ let releaseErrorMessage = null;
665
+ try {
666
+ await slot.release("healthy");
667
+ }
668
+ catch (releaseError) {
669
+ releaseErrorMessage = errorMessage(releaseError);
670
+ }
671
+ handle.release();
672
+ const bindFailureMessage = `claim_bind_failed ${bindError}`;
673
+ this.markRuntimeError(bindFailureMessage);
674
+ let retrySyncError = null;
675
+ if (handle.abandonClaimOnSettlement) {
676
+ await this.settleStoppedClaim(handle, issue.id, reservation.slotIndex);
677
+ }
678
+ else {
679
+ try {
680
+ await this.orchestrator.abandonClaimAsync(issue.id, reservation.slotIndex);
681
+ retrySyncError = this.syncRetryTimerSafely(issue.id);
682
+ }
683
+ catch {
684
+ // Preserve the bind failure event; if the backend is unavailable, abandon may fail too.
685
+ }
686
+ }
687
+ this.stopClaimOwnerHeartbeatIfIdle();
688
+ this.addEvent("dispatch_skipped", `${issue.identifier} bind_reservation_error ${bindError}`);
689
+ if (releaseErrorMessage) {
690
+ this.addEvent("dispatch_skipped", `${issue.identifier} bind_reservation_release_error ${releaseErrorMessage}`);
691
+ }
692
+ this.addEvent("poll_error", bindFailureMessage);
693
+ if (retrySyncError)
694
+ this.addEvent("poll_error", retrySyncError);
695
+ return;
696
+ }
558
697
  if (!entry) {
559
698
  // The reservation was cancelled/expired during the acquire (cleanup, stop,
560
699
  // or the expiry sweep): release the bound worker back to warm inventory (the
@@ -562,16 +701,60 @@ export class LorenzRuntime {
562
701
  await slot.release("healthy");
563
702
  this.addEvent("dispatch_skipped", `${issue.identifier} reservation_lapsed`);
564
703
  handle.release();
704
+ await this.settleStoppedClaim(handle, issue.id, reservation.slotIndex);
565
705
  return;
566
706
  }
567
707
  this.addEvent("run_started", `${issue.identifier} slot=${reservation.slotIndex}`);
568
708
  await this.runClaim(issue, reservation.slotIndex, reservation.agentKind, runId, slot.workerHost, handle, slot);
569
709
  }
710
+ async cancelReservationAfterSkippedAcquire(issue, reservation, handle, options = {}) {
711
+ let cancelled = false;
712
+ let cancelError;
713
+ try {
714
+ await this.orchestrator.cancelReservationAsync(reservation);
715
+ cancelled = true;
716
+ }
717
+ catch (error) {
718
+ cancelError = error;
719
+ }
720
+ finally {
721
+ handle.release();
722
+ await this.settleStoppedClaim(handle, issue.id, reservation.slotIndex);
723
+ this.stopClaimOwnerHeartbeatIfIdle();
724
+ }
725
+ if (cancelled && options.syncRetryTimer) {
726
+ const retrySyncError = this.syncRetryTimerSafely(issue.id);
727
+ if (retrySyncError)
728
+ this.addEvent("poll_error", retrySyncError);
729
+ }
730
+ if (!cancelError)
731
+ return;
732
+ const message = `claim_cancel_failed ${errorMessage(cancelError)}`;
733
+ if (this.appStatus !== "error") {
734
+ this.appStatus = "error";
735
+ this.lastError = message;
736
+ }
737
+ this.addEvent("poll_error", message);
738
+ }
570
739
  async runClaim(issue, slotIndex, agentKind, runId, workerHost, handle, slot = null) {
571
740
  const startedAt = this.clock.now().toISOString();
572
741
  const effectiveWorkerHost = workerHost;
573
742
  let workerOutcome = "healthy";
574
743
  const heartbeatSlot = slot;
744
+ let claimStoreRuntimeError = null;
745
+ let updateQueue = Promise.resolve();
746
+ const enqueueUpdate = (update) => {
747
+ const next = updateQueue.then(async () => {
748
+ heartbeatSlot?.heartbeat();
749
+ await this.orchestrator.applyUpdateAsync(issue.id, slotIndex, update);
750
+ this.addEvent(update.type, agentUpdateRuntimeMessage(issue.identifier, update));
751
+ this.input.onAgentUpdate?.(issue, update);
752
+ });
753
+ updateQueue = next.catch((error) => {
754
+ claimStoreRuntimeError ??= new ClaimStoreRuntimeError("claim_update_failed", error);
755
+ handle.abort();
756
+ });
757
+ };
575
758
  try {
576
759
  const result = await this.runner({
577
760
  issue,
@@ -588,26 +771,33 @@ export class LorenzRuntime {
588
771
  // path; force the per-slot suffix whenever co-residence is possible.
589
772
  // Single-tenant (default) keeps the bare path.
590
773
  forceSlotSuffix: (this.workflow.settings.worker.workerPool?.slotsPerMachine ?? 1) > 1,
591
- onUpdate: (update) => {
592
- heartbeatSlot?.heartbeat();
593
- this.orchestrator.applyUpdate(issue.id, slotIndex, update);
594
- this.addEvent(update.type, agentUpdateRuntimeMessage(issue.identifier, update));
595
- this.input.onAgentUpdate?.(issue, update);
596
- },
774
+ onUpdate: enqueueUpdate,
597
775
  fetchIssue: async (current) => {
598
776
  const refreshed = await this.client.fetchIssuesByIds([current.id]);
599
777
  return refreshed[0] ?? current;
600
778
  },
601
779
  abortSignal: handle.signal,
602
780
  });
781
+ await updateQueue;
782
+ if (claimStoreRuntimeError)
783
+ throwRuntimeError(claimStoreRuntimeError);
603
784
  if (!handle.isActive)
604
785
  return;
605
786
  const finalIssue = result.finalIssue ?? (await this.fetchIssueOrSelf(issue));
606
787
  if (!handle.isActive)
607
788
  return;
608
- const entry = this.runningEntry(issue.id, slotIndex);
609
- this.orchestrator.finish(issue.id, slotIndex, true, undefined, "continuation");
610
- this.syncRetryTimer(issue.id);
789
+ let finished;
790
+ try {
791
+ finished = await this.orchestrator.finishAsync(issue.id, slotIndex, true, undefined, "continuation");
792
+ }
793
+ catch (error) {
794
+ this.recordClaimStoreFailure("claim_finish_failed", error);
795
+ return;
796
+ }
797
+ if (!finished) {
798
+ this.addEvent("dispatch_skipped", `${issue.identifier} claim_lost_before_finish`);
799
+ return;
800
+ }
611
801
  this.recordHistory(buildRunHistoryEntry({
612
802
  id: runId,
613
803
  issue,
@@ -616,15 +806,30 @@ export class LorenzRuntime {
616
806
  agentKind,
617
807
  outcome: "success",
618
808
  turnCount: result.turnCount,
619
- runningEntry: entry,
809
+ runningEntry: finished,
620
810
  workspacePath: result.workspace,
621
811
  startedAt,
622
812
  endedAt: this.clock.now().toISOString(),
623
813
  durationMs: durationMs(startedAt, this.clock.now().toISOString()),
624
814
  }));
815
+ const retrySyncError = this.syncRetryTimerSafely(issue.id);
625
816
  this.addEvent("run_completed", `${issue.identifier} turns=${result.turnCount}`);
817
+ if (retrySyncError)
818
+ this.addEvent("poll_error", retrySyncError);
626
819
  }
627
820
  catch (error) {
821
+ await updateQueue;
822
+ const runtimeError = error instanceof ClaimStoreRuntimeError ? error : claimStoreRuntimeError;
823
+ if (runtimeError) {
824
+ this.recordClaimStoreFailure(runtimeError.reason, runtimeError.original);
825
+ try {
826
+ await this.orchestrator.abandonClaimAsync(issue.id, slotIndex);
827
+ }
828
+ catch (abandonError) {
829
+ this.recordClaimStoreFailure("claim_abandon_failed", abandonError);
830
+ }
831
+ return;
832
+ }
628
833
  // Classify the worker outcome BEFORE any early return so a run finished
629
834
  // externally (e.g. a stall reconciliation aborted it -> the runner throws
630
835
  // `agent_run_aborted`) still poisons the worker: a stall-finished run is
@@ -636,26 +841,36 @@ export class LorenzRuntime {
636
841
  // run_failed event the TUI renders as a red error banner on Ctrl+C.
637
842
  if (!handle.isActive)
638
843
  return;
639
- const entry = this.runningEntry(issue.id, slotIndex);
640
- if (!handle.isActive)
844
+ let finished;
845
+ try {
846
+ finished = await this.orchestrator.finishAsync(issue.id, slotIndex, true, errorMessage(error), "failure");
847
+ }
848
+ catch (finishError) {
849
+ this.recordClaimStoreFailure("claim_finish_failed", finishError);
850
+ return;
851
+ }
852
+ if (!finished) {
853
+ this.addEvent("dispatch_skipped", `${issue.identifier} claim_lost_before_finish`);
641
854
  return;
642
- this.orchestrator.finish(issue.id, slotIndex, true, errorMessage(error), "failure");
643
- this.syncRetryTimer(issue.id);
855
+ }
644
856
  this.recordHistory(buildRunHistoryEntry({
645
857
  id: runId,
646
858
  issue,
647
859
  slotIndex,
648
860
  agentKind,
649
861
  outcome: "failed",
650
- turnCount: entry?.turnCount ?? 0,
651
- runningEntry: entry,
862
+ turnCount: finished.turnCount,
863
+ runningEntry: finished,
652
864
  startedAt,
653
865
  endedAt: this.clock.now().toISOString(),
654
866
  durationMs: durationMs(startedAt, this.clock.now().toISOString()),
655
867
  error: errorMessage(error),
656
868
  fallbackLastEvent: "turn_failed",
657
869
  }));
870
+ const retrySyncError = this.syncRetryTimerSafely(issue.id);
658
871
  this.addEvent("run_failed", `${issue.identifier} ${errorMessage(error)}`);
872
+ if (retrySyncError)
873
+ this.addEvent("poll_error", retrySyncError);
659
874
  }
660
875
  finally {
661
876
  handle.release();
@@ -680,6 +895,32 @@ export class LorenzRuntime {
680
895
  await slot.release("healthy");
681
896
  }
682
897
  }
898
+ await this.settleStoppedClaim(handle, issue.id, slotIndex);
899
+ }
900
+ }
901
+ markStoppedClaimSettlementPending(handle) {
902
+ if (handle.abandonClaimOnSettlement)
903
+ return;
904
+ this.pendingStoppedClaimSettlements += 1;
905
+ }
906
+ async settleStoppedClaim(handle, issueId, slotIndex) {
907
+ if (!handle.abandonClaimOnSettlement)
908
+ return;
909
+ handle.abandonClaimOnSettlement = false;
910
+ try {
911
+ await this.orchestrator.abandonClaimAsync(issueId, slotIndex);
912
+ }
913
+ catch (error) {
914
+ const message = `claim_abandon_failed ${errorMessage(error)}`;
915
+ if (this.appStatus !== "error") {
916
+ this.appStatus = "error";
917
+ this.lastError = message;
918
+ }
919
+ this.addEvent("poll_error", message);
920
+ }
921
+ finally {
922
+ this.pendingStoppedClaimSettlements = Math.max(0, this.pendingStoppedClaimSettlements - 1);
923
+ this.stopClaimOwnerHeartbeatIfIdle();
683
924
  }
684
925
  }
685
926
  async fetchIssueOrSelf(issue) {
@@ -717,12 +958,14 @@ export class LorenzRuntime {
717
958
  // applied, so dispatch can never use settings that do not match the live pool.
718
959
  //
719
960
  // The coordinator (and its pool) is a reload-surviving singleton: diff
720
- // prev-vs-next worker-pool settings instead of being reconstructed. When the
721
- // reload REMOVES the worker_pool block entirely (next === undefined), reconcile
722
- // to a disabled-equivalent of the prior settings so the live pool drains to
723
- // zero instead of leaking its (paid) workers unmanaged. A present block (even
724
- // one with `enabled: false`) keeps the existing path: reconcile handles the
725
- // disable-and-drain itself.
961
+ // prev-vs-next worker-pool settings instead of being reconstructed. The pool is
962
+ // the single dispatch path, so a parsed config always carries a worker_pool (an
963
+ // absent block defaults to the enabled `local` pool). The
964
+ // `disabledWorkerPoolSettings(prevWorkerPool)` fallback only fires for a settings
965
+ // object built outside parseConfig that genuinely omits the block; reconcile then
966
+ // drains the live pool to zero instead of leaking its (paid) workers. A present
967
+ // block (including an explicit `enabled: false`) reconciles directly: reconcile
968
+ // handles the disable-and-drain itself.
726
969
  if (this.coordinator) {
727
970
  const next = workflow.settings.worker.workerPool ?? disabledWorkerPoolSettings(prevWorkerPool);
728
971
  // Awaited: reconcile is async so the coordinator's injected driverLoader
@@ -747,29 +990,41 @@ export class LorenzRuntime {
747
990
  }
748
991
  }
749
992
  async reconcileTrackedIssues() {
750
- const snapshot = this.orchestrator.snapshot();
993
+ const snapshot = await this.orchestrator.snapshotAsync();
751
994
  const tracked = new Map();
752
995
  // Reserving (in-acquire) slots are tracked host-less so an issue that goes
753
996
  // terminal mid-acquire is still aborted and cleaned up; running/retrying
754
997
  // entries below override with their richer metadata when present.
755
- for (const entry of snapshot.reserving)
998
+ for (const entry of snapshot.reserving) {
999
+ if (!(await this.orchestrator.ownsClaimAsync(entry.issueId, entry.slotIndex)))
1000
+ continue;
756
1001
  tracked.set(entry.issueId, {
1002
+ kind: "claim",
757
1003
  identifier: entry.identifier,
758
1004
  workerHost: null,
759
1005
  workspacePath: null,
760
1006
  });
761
- for (const entry of snapshot.running)
1007
+ }
1008
+ for (const entry of snapshot.running) {
1009
+ if (!(await this.orchestrator.ownsClaimAsync(entry.issue.id, entry.slotIndex)))
1010
+ continue;
762
1011
  tracked.set(entry.issue.id, {
1012
+ kind: "claim",
763
1013
  identifier: entry.issue.identifier,
764
1014
  workerHost: entry.workerHost,
765
1015
  workspacePath: entry.workspacePath,
766
1016
  });
767
- for (const entry of snapshot.retrying)
1017
+ }
1018
+ for (const entry of snapshot.retrying) {
1019
+ if (tracked.has(entry.issueId))
1020
+ continue;
768
1021
  tracked.set(entry.issueId, {
1022
+ kind: "retry",
769
1023
  identifier: entry.identifier,
770
1024
  workerHost: entry.workerHost,
771
1025
  workspacePath: entry.workspacePath,
772
1026
  });
1027
+ }
773
1028
  if (tracked.size === 0)
774
1029
  return;
775
1030
  let refreshed;
@@ -782,18 +1037,25 @@ export class LorenzRuntime {
782
1037
  }
783
1038
  const refreshedIds = new Set(refreshed.map((issue) => issue.id));
784
1039
  for (const issue of refreshed) {
785
- if (issueIsActive(issue, this.workflow.settings) &&
786
- routedToThisWorker(issue, this.workflow.settings) &&
787
- !issueHasOpenBlockers(issue, this.workflow.settings)) {
788
- this.orchestrator.refreshRunningIssue(issue);
1040
+ const meta = tracked.get(issue.id);
1041
+ const active = issueIsActive(issue, this.workflow.settings);
1042
+ const routed = routedToThisWorker(issue, this.workflow.settings);
1043
+ if (active && routed && !issueHasOpenBlockers(issue, this.workflow.settings)) {
1044
+ await this.orchestrator.refreshRunningIssueAsync(issue);
1045
+ continue;
1046
+ }
1047
+ try {
1048
+ await this.orchestrator.cleanupIssueAsync(issue.id);
1049
+ }
1050
+ catch (error) {
1051
+ this.recordClaimStoreFailure("claim_cleanup_failed", error);
789
1052
  continue;
790
1053
  }
791
1054
  this.abortIssueRuns(issue.id);
792
- this.orchestrator.cleanupIssue(issue.id);
793
1055
  this.clearRetryTimer(issue.id);
794
1056
  const reason = reconciliationStopReason(issue, this.workflow.settings);
795
1057
  if (isTerminalState(issue.state, this.workflow.settings.tracker.terminalStates)) {
796
- await this.removeIssueWorkspaces(this.workflow.settings, issue.identifier || tracked.get(issue.id)?.identifier, tracked.get(issue.id)?.workerHost, issue);
1058
+ await this.removeIssueWorkspaces(this.workflow.settings, issue.identifier || meta?.identifier, meta?.workerHost, issue);
797
1059
  this.addEvent("workspace_cleanup", `${issue.identifier} ${reason}`);
798
1060
  }
799
1061
  else {
@@ -803,15 +1065,26 @@ export class LorenzRuntime {
803
1065
  for (const [issueId, meta] of tracked.entries()) {
804
1066
  if (refreshedIds.has(issueId))
805
1067
  continue;
1068
+ try {
1069
+ await this.orchestrator.cleanupIssueAsync(issueId);
1070
+ }
1071
+ catch (error) {
1072
+ this.recordClaimStoreFailure("claim_cleanup_failed", error);
1073
+ continue;
1074
+ }
806
1075
  this.abortIssueRuns(issueId);
807
- this.orchestrator.cleanupIssue(issueId);
808
1076
  this.clearRetryTimer(issueId);
809
1077
  this.addEvent("run_reconciled", `${meta.identifier} missing`);
810
1078
  }
811
1079
  }
812
- reconcileStalledRuns() {
813
- for (const snapshotEntry of this.orchestrator.snapshot().running) {
814
- const currentEntry = this.runningEntry(snapshotEntry.issue.id, snapshotEntry.slotIndex);
1080
+ async reconcileStalledRuns() {
1081
+ // Let already-settled runner and run-claim continuations finish before acting on a stale snapshot.
1082
+ await Promise.resolve();
1083
+ await Promise.resolve();
1084
+ for (const snapshotEntry of (await this.orchestrator.snapshotAsync()).running) {
1085
+ if (!(await this.orchestrator.ownsClaimAsync(snapshotEntry.issue.id, snapshotEntry.slotIndex)))
1086
+ continue;
1087
+ const currentEntry = await this.runningEntry(snapshotEntry.issue.id, snapshotEntry.slotIndex);
815
1088
  if (!currentEntry)
816
1089
  continue;
817
1090
  const effective = settingsForIssueState(this.workflow.settings, currentEntry.issue.state);
@@ -829,11 +1102,22 @@ export class LorenzRuntime {
829
1102
  const activeHandle = this.activeRuns.get(key);
830
1103
  const runId = activeHandle?.runId ?? `stalled-${currentEntry.issue.id}-${currentEntry.slotIndex}`;
831
1104
  const error = `agent_stalled after ${timeoutMs}ms`;
832
- const entry = this.runningEntry(snapshotEntry.issue.id, snapshotEntry.slotIndex);
1105
+ const entry = await this.runningEntry(snapshotEntry.issue.id, snapshotEntry.slotIndex);
833
1106
  if (!entry)
834
1107
  continue;
835
- this.orchestrator.finish(entry.issue.id, entry.slotIndex, true, error, "failure");
836
- this.syncRetryTimer(entry.issue.id);
1108
+ let finished;
1109
+ try {
1110
+ finished = await this.orchestrator.finishAsync(entry.issue.id, entry.slotIndex, true, error, "failure");
1111
+ }
1112
+ catch (finishError) {
1113
+ this.recordClaimStoreFailure("claim_finish_failed", finishError);
1114
+ continue;
1115
+ }
1116
+ if (!finished) {
1117
+ activeHandle?.finishExternally();
1118
+ this.addEvent("dispatch_skipped", `${entry.identifier} claim_lost_before_finish`);
1119
+ continue;
1120
+ }
837
1121
  activeHandle?.finishExternally("stalled");
838
1122
  const endedAt = this.clock.now().toISOString();
839
1123
  this.recordHistory(buildRunHistoryEntry({
@@ -851,13 +1135,14 @@ export class LorenzRuntime {
851
1135
  error,
852
1136
  fallbackLastEvent: "agent_stalled",
853
1137
  }));
1138
+ const retrySyncError = this.syncRetryTimerSafely(entry.issue.id);
854
1139
  this.addEvent("run_stalled", `${entry.identifier} ${error}`);
1140
+ if (retrySyncError)
1141
+ this.addEvent("poll_error", retrySyncError);
855
1142
  }
856
1143
  }
857
- runningEntry(issueId, slotIndex) {
858
- return this.orchestrator
859
- .snapshot()
860
- .running.find((entry) => entry.issue.id === issueId && entry.slotIndex === slotIndex);
1144
+ async runningEntry(issueId, slotIndex) {
1145
+ return (await this.orchestrator.snapshotAsync()).running.find((entry) => entry.issue.id === issueId && entry.slotIndex === slotIndex);
861
1146
  }
862
1147
  // Cleanup is driven by what is actually on disk: list existing per-issue workspace
863
1148
  // directories and look up just those issues, instead of enumerating every terminal
@@ -905,23 +1190,27 @@ export class LorenzRuntime {
905
1190
  return;
906
1191
  }
907
1192
  this.retryScheduler.sync(runtimeRetryEntry(retry), (scheduled) => {
908
- const current = this.orchestrator
909
- .snapshot()
910
- .retrying.find((entry) => entry.issueId === scheduled.issueId);
911
- if (!current ||
912
- current.attempt !== scheduled.attempt ||
913
- current.dueAtIso !== scheduled.dueAtIso) {
914
- return;
1193
+ try {
1194
+ const current = this.orchestrator
1195
+ .snapshot()
1196
+ .retrying.find((entry) => entry.issueId === scheduled.issueId);
1197
+ if (!current ||
1198
+ current.attempt !== scheduled.attempt ||
1199
+ current.dueAtIso !== scheduled.dueAtIso) {
1200
+ return;
1201
+ }
1202
+ this.addEvent("retry_timer_due", `${scheduled.issueIdentifier} attempt=${scheduled.attempt}`);
1203
+ if (this.pollInProgress) {
1204
+ this.queuePendingPoll({}, true);
1205
+ return;
1206
+ }
1207
+ this.pollOnce().catch((error) => {
1208
+ this.recordRetryTimerError(error);
1209
+ });
915
1210
  }
916
- this.addEvent("retry_timer_due", `${scheduled.issueIdentifier} attempt=${scheduled.attempt}`);
917
- if (this.pollInProgress) {
918
- this.queuePendingPoll({}, true);
919
- return;
1211
+ catch (error) {
1212
+ this.recordRetryTimerError(error);
920
1213
  }
921
- this.pollOnce().catch((error) => {
922
- this.lastError = errorMessage(error);
923
- this.addEvent("retry_timer_error", this.lastError);
924
- });
925
1214
  });
926
1215
  }
927
1216
  clearRetryTimer(issueId) {
@@ -939,6 +1228,33 @@ export class LorenzRuntime {
939
1228
  recordHistory(entry) {
940
1229
  this.projection.recordRunHistory(entry);
941
1230
  }
1231
+ recordRetryTimerError(error) {
1232
+ const message = errorMessage(error);
1233
+ this.markRuntimeError(message);
1234
+ this.addEvent("retry_timer_error", message);
1235
+ }
1236
+ recordClaimStoreFailure(reason, error) {
1237
+ const message = `${reason} ${errorMessage(error)}`;
1238
+ this.markRuntimeError(message);
1239
+ this.addEvent("poll_error", message);
1240
+ }
1241
+ syncRetryTimerSafely(issueId) {
1242
+ try {
1243
+ this.syncRetryTimer(issueId);
1244
+ return null;
1245
+ }
1246
+ catch (error) {
1247
+ const message = `retry_timer_sync_failed ${errorMessage(error)}`;
1248
+ this.markRuntimeError(message);
1249
+ return message;
1250
+ }
1251
+ }
1252
+ markRuntimeError(message) {
1253
+ if (this.appStatus !== "error") {
1254
+ this.appStatus = "error";
1255
+ this.lastError = message;
1256
+ }
1257
+ }
942
1258
  addEvent(type, message) {
943
1259
  const event = { type, message, at: this.clock.now().toISOString() };
944
1260
  this.projection.recordEvent(event);
@@ -966,7 +1282,15 @@ export class LorenzRuntime {
966
1282
  return this.input.appendLogEvent(logFile, event);
967
1283
  }
968
1284
  emit() {
969
- const snapshot = this.snapshot();
1285
+ let snapshot;
1286
+ try {
1287
+ snapshot = this.snapshot();
1288
+ }
1289
+ catch (error) {
1290
+ if (this.appStatus === "error")
1291
+ return;
1292
+ throw error;
1293
+ }
970
1294
  for (const listener of this.listeners)
971
1295
  listener(snapshot);
972
1296
  }
@@ -1109,13 +1433,13 @@ function disabledWorkerPoolSettings(prev) {
1109
1433
  /**
1110
1434
  * Wraps a bare {@link WorkerPool} in a null-endpoint passthrough {@link DispatchCoordinator} so the
1111
1435
  * runtime drives every run through the uniform coordinator surface while a bare-pool injection
1112
- * stays byte-identical at the runtime boundary. STEP 1's null manager mints nothing
1113
- * (`perRunEndpoint=false`, every `RunSlot.mcpEndpoint=null`), so this is a 1:1 passthrough over
1436
+ * stays byte-identical at the runtime boundary. The null manager mints nothing
1437
+ * (`perRunClaimEnforcement=false`, every `RunSlot.mcpEndpoint=null`), so this is a passthrough over
1114
1438
  * the pool: `acquireRunSlot` delegates to `pool.acquire`, settle delegates straight to the
1115
1439
  * `WorkerLease`, and `reconcile`/`drain`/`governs`/`canAcquire` forward verbatim. Returns
1116
1440
  * `undefined` when no pool is supplied (the static/local path).
1117
1441
  *
1118
- * `settings` only needs to satisfy the coordinator's constructor; in STEP 1 the coordinator does
1442
+ * `settings` only needs to satisfy the coordinator's constructor; this wrapper does
1119
1443
  * not read it past construction (the pool owns live settings), so the live `worker.workerPool`
1120
1444
  * settings are passed when present and a disabled placeholder otherwise.
1121
1445
  */