@telora/daemon 0.22.289 → 0.22.293

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 (348) hide show
  1. package/README.md +2 -2
  2. package/build-info.json +2 -2
  3. package/dist/backends/agent-backend.d.ts +2 -0
  4. package/dist/backends/agent-backend.d.ts.map +1 -1
  5. package/dist/backends/availability.d.ts +14 -0
  6. package/dist/backends/availability.d.ts.map +1 -1
  7. package/dist/backends/availability.js +37 -0
  8. package/dist/backends/availability.js.map +1 -1
  9. package/dist/backends/claude/claude-backend.d.ts.map +1 -1
  10. package/dist/backends/claude/claude-backend.js +2 -0
  11. package/dist/backends/claude/claude-backend.js.map +1 -1
  12. package/dist/backends/codex/codex-backend.d.ts.map +1 -1
  13. package/dist/backends/codex/codex-backend.js +2 -0
  14. package/dist/backends/codex/codex-backend.js.map +1 -1
  15. package/dist/backends/index.d.ts +1 -1
  16. package/dist/backends/index.d.ts.map +1 -1
  17. package/dist/backends/index.js +2 -17
  18. package/dist/backends/index.js.map +1 -1
  19. package/dist/cli/connect/config-write.d.ts.map +1 -1
  20. package/dist/cli/connect/config-write.js +2 -1
  21. package/dist/cli/connect/config-write.js.map +1 -1
  22. package/dist/cli/status-commands.d.ts +7 -0
  23. package/dist/cli/status-commands.d.ts.map +1 -1
  24. package/dist/cli/status-commands.js +17 -0
  25. package/dist/cli/status-commands.js.map +1 -1
  26. package/dist/completion/completion-event/event.d.ts +1 -0
  27. package/dist/completion/completion-event/event.d.ts.map +1 -1
  28. package/dist/completion/completion-event/event.js +1 -0
  29. package/dist/completion/completion-event/event.js.map +1 -1
  30. package/dist/completion/review-exit/review-census-record.d.ts +4 -2
  31. package/dist/completion/review-exit/review-census-record.d.ts.map +1 -1
  32. package/dist/completion/review-exit/review-census-record.js +11 -3
  33. package/dist/completion/review-exit/review-census-record.js.map +1 -1
  34. package/dist/completion/review-exit/review-exit-deps.js +1 -1
  35. package/dist/completion/review-exit/review-exit-phase.d.ts +9 -0
  36. package/dist/completion/review-exit/review-exit-phase.d.ts.map +1 -1
  37. package/dist/completion/review-exit/review-exit-phase.js +1 -1
  38. package/dist/completion/review-exit/review-exit-phase.js.map +1 -1
  39. package/dist/completion/review-exit-holds/commit-verdict-release.d.ts.map +1 -1
  40. package/dist/completion/review-exit-holds/commit-verdict-release.js +2 -1
  41. package/dist/completion/review-exit-holds/commit-verdict-release.js.map +1 -1
  42. package/dist/completion/review-exit-holds/review-exit-verdict-gate.d.ts +1 -0
  43. package/dist/completion/review-exit-holds/review-exit-verdict-gate.d.ts.map +1 -1
  44. package/dist/completion/review-exit-holds/review-exit-verdict-gate.js +1 -0
  45. package/dist/completion/review-exit-holds/review-exit-verdict-gate.js.map +1 -1
  46. package/dist/completion/team-exit/team-completion.d.ts.map +1 -1
  47. package/dist/completion/team-exit/team-completion.js +3 -1
  48. package/dist/completion/team-exit/team-completion.js.map +1 -1
  49. package/dist/completion/team-liveness/liveness-firing.js +3 -3
  50. package/dist/completion/team-liveness/team-liveness-phase.d.ts +6 -1
  51. package/dist/completion/team-liveness/team-liveness-phase.d.ts.map +1 -1
  52. package/dist/completion/team-liveness/team-liveness-phase.js.map +1 -1
  53. package/dist/completion/team-outcome/apply-close.d.ts.map +1 -1
  54. package/dist/completion/team-outcome/apply-close.js +4 -1
  55. package/dist/completion/team-outcome/apply-close.js.map +1 -1
  56. package/dist/completion/team-outcome/apply-turn.d.ts.map +1 -1
  57. package/dist/completion/team-outcome/apply-turn.js +3 -1
  58. package/dist/completion/team-outcome/apply-turn.js.map +1 -1
  59. package/dist/completion/team-outcome/apply.d.ts.map +1 -1
  60. package/dist/completion/team-outcome/apply.js +3 -1
  61. package/dist/completion/team-outcome/apply.js.map +1 -1
  62. package/dist/completion/team-outcome/decide-shared.d.ts.map +1 -1
  63. package/dist/completion/team-outcome/decide-shared.js +3 -2
  64. package/dist/completion/team-outcome/decide-shared.js.map +1 -1
  65. package/dist/completion/team-outcome/exit-pipeline-state.d.ts.map +1 -1
  66. package/dist/completion/team-outcome/exit-pipeline-state.js +2 -1
  67. package/dist/completion/team-outcome/exit-pipeline-state.js.map +1 -1
  68. package/dist/completion/team-outcome/team-outcome.d.ts.map +1 -1
  69. package/dist/completion/team-outcome/team-outcome.js +3 -1
  70. package/dist/completion/team-outcome/team-outcome.js.map +1 -1
  71. package/dist/composition/execution-migrations-context.d.ts.map +1 -1
  72. package/dist/composition/execution-migrations-context.js +2 -0
  73. package/dist/composition/execution-migrations-context.js.map +1 -1
  74. package/dist/composition/execution-process-context.js +1 -1
  75. package/dist/composition/execution-spawn-context.d.ts.map +1 -1
  76. package/dist/composition/execution-spawn-context.js +3 -1
  77. package/dist/composition/execution-spawn-context.js.map +1 -1
  78. package/dist/composition/execution-spawn-process-context.d.ts.map +1 -1
  79. package/dist/composition/execution-spawn-process-context.js +3 -2
  80. package/dist/composition/execution-spawn-process-context.js.map +1 -1
  81. package/dist/composition/focus-activity-live-sources.d.ts +4 -0
  82. package/dist/composition/focus-activity-live-sources.d.ts.map +1 -0
  83. package/dist/composition/focus-activity-live-sources.js +68 -0
  84. package/dist/composition/focus-activity-live-sources.js.map +1 -0
  85. package/dist/composition/runtime-delivery-advance-context.d.ts +6 -1
  86. package/dist/composition/runtime-delivery-advance-context.d.ts.map +1 -1
  87. package/dist/composition/runtime-delivery-advance-context.js +14 -3
  88. package/dist/composition/runtime-delivery-advance-context.js.map +1 -1
  89. package/dist/composition/runtime-heartbeat-context.d.ts.map +1 -1
  90. package/dist/composition/runtime-heartbeat-context.js +3 -1
  91. package/dist/composition/runtime-heartbeat-context.js.map +1 -1
  92. package/dist/composition/team-lifecycle-context.d.ts.map +1 -1
  93. package/dist/composition/team-lifecycle-context.js +3 -1
  94. package/dist/composition/team-lifecycle-context.js.map +1 -1
  95. package/dist/composition/team-liveness-phase-sources.d.ts.map +1 -1
  96. package/dist/composition/team-liveness-phase-sources.js +1 -0
  97. package/dist/composition/team-liveness-phase-sources.js.map +1 -1
  98. package/dist/composition/verification-context.d.ts.map +1 -1
  99. package/dist/composition/verification-context.js +4 -1
  100. package/dist/composition/verification-context.js.map +1 -1
  101. package/dist/composition/verify-probe-context.d.ts +7 -0
  102. package/dist/composition/verify-probe-context.d.ts.map +1 -1
  103. package/dist/composition/verify-probe-context.js +55 -3
  104. package/dist/composition/verify-probe-context.js.map +1 -1
  105. package/dist/config/config.d.ts.map +1 -1
  106. package/dist/config/config.js +4 -3
  107. package/dist/config/config.js.map +1 -1
  108. package/dist/config/session-cap.d.ts +89 -0
  109. package/dist/config/session-cap.d.ts.map +1 -0
  110. package/dist/config/session-cap.js +176 -0
  111. package/dist/config/session-cap.js.map +1 -0
  112. package/dist/daemon-state/awaiting-slot.d.ts +8 -2
  113. package/dist/daemon-state/awaiting-slot.d.ts.map +1 -1
  114. package/dist/daemon-state/awaiting-slot.js +21 -8
  115. package/dist/daemon-state/awaiting-slot.js.map +1 -1
  116. package/dist/daemon-state/engine-readiness.d.ts +73 -0
  117. package/dist/daemon-state/engine-readiness.d.ts.map +1 -0
  118. package/dist/daemon-state/engine-readiness.js +191 -0
  119. package/dist/daemon-state/engine-readiness.js.map +1 -0
  120. package/dist/daemon-state/focus-progress-clock.d.ts +34 -0
  121. package/dist/daemon-state/focus-progress-clock.d.ts.map +1 -0
  122. package/dist/daemon-state/focus-progress-clock.js +167 -0
  123. package/dist/daemon-state/focus-progress-clock.js.map +1 -0
  124. package/dist/daemon-state/focus-team-state.d.ts +32 -9
  125. package/dist/daemon-state/focus-team-state.d.ts.map +1 -1
  126. package/dist/daemon-state/focus-team-state.js +50 -9
  127. package/dist/daemon-state/focus-team-state.js.map +1 -1
  128. package/dist/daemon-state/provider-window.d.ts.map +1 -1
  129. package/dist/daemon-state/provider-window.js +5 -1
  130. package/dist/daemon-state/provider-window.js.map +1 -1
  131. package/dist/daemon-state/review-park-record.d.ts +36 -0
  132. package/dist/daemon-state/review-park-record.d.ts.map +1 -0
  133. package/dist/daemon-state/review-park-record.js +27 -0
  134. package/dist/daemon-state/review-park-record.js.map +1 -0
  135. package/dist/daemon-state/worker-pidfile.d.ts.map +1 -1
  136. package/dist/daemon-state/worker-pidfile.js +3 -1
  137. package/dist/daemon-state/worker-pidfile.js.map +1 -1
  138. package/dist/delivery/commit-verdict-hold.d.ts.map +1 -1
  139. package/dist/delivery/commit-verdict-hold.js +3 -1
  140. package/dist/delivery/commit-verdict-hold.js.map +1 -1
  141. package/dist/directive/directive-queue.js +1 -1
  142. package/dist/focus/focus-activity-held.d.ts +37 -0
  143. package/dist/focus/focus-activity-held.d.ts.map +1 -0
  144. package/dist/focus/focus-activity-held.js +89 -0
  145. package/dist/focus/focus-activity-held.js.map +1 -0
  146. package/dist/focus/focus-activity-poll-facts.d.ts +39 -0
  147. package/dist/focus/focus-activity-poll-facts.d.ts.map +1 -0
  148. package/dist/focus/focus-activity-poll-facts.js +110 -0
  149. package/dist/focus/focus-activity-poll-facts.js.map +1 -0
  150. package/dist/focus/focus-activity-producers.d.ts +43 -0
  151. package/dist/focus/focus-activity-producers.d.ts.map +1 -0
  152. package/dist/focus/focus-activity-producers.js +130 -0
  153. package/dist/focus/focus-activity-producers.js.map +1 -0
  154. package/dist/focus/focus-activity-record.d.ts +58 -0
  155. package/dist/focus/focus-activity-record.d.ts.map +1 -0
  156. package/dist/focus/focus-activity-record.js +141 -0
  157. package/dist/focus/focus-activity-record.js.map +1 -0
  158. package/dist/focus/focus-activity-sources.d.ts +99 -0
  159. package/dist/focus/focus-activity-sources.d.ts.map +1 -0
  160. package/dist/focus/focus-activity-sources.js +45 -0
  161. package/dist/focus/focus-activity-sources.js.map +1 -0
  162. package/dist/focus/focus-executor.js +1 -1
  163. package/dist/focus/focus-executor.js.map +1 -1
  164. package/dist/focus/focus-poller-auto-advance.d.ts.map +1 -1
  165. package/dist/focus/focus-poller-auto-advance.js +2 -0
  166. package/dist/focus/focus-poller-auto-advance.js.map +1 -1
  167. package/dist/focus/heartbeat-metadata.d.ts.map +1 -1
  168. package/dist/focus/heartbeat-metadata.js +6 -0
  169. package/dist/focus/heartbeat-metadata.js.map +1 -1
  170. package/dist/focus/heartbeat.d.ts +3 -0
  171. package/dist/focus/heartbeat.d.ts.map +1 -1
  172. package/dist/focus/heartbeat.js +31 -31
  173. package/dist/focus/heartbeat.js.map +1 -1
  174. package/dist/focus/pending-review-approved-head.d.ts.map +1 -1
  175. package/dist/focus/pending-review-approved-head.js +4 -2
  176. package/dist/focus/pending-review-approved-head.js.map +1 -1
  177. package/dist/focus/unchanged-reviewed-head.d.ts.map +1 -1
  178. package/dist/focus/unchanged-reviewed-head.js +4 -2
  179. package/dist/focus/unchanged-reviewed-head.js.map +1 -1
  180. package/dist/index.js +1 -1
  181. package/dist/queries/deliveries/deliveries.d.ts +4 -0
  182. package/dist/queries/deliveries/deliveries.d.ts.map +1 -1
  183. package/dist/queries/deliveries/deliveries.js +6 -0
  184. package/dist/queries/deliveries/deliveries.js.map +1 -1
  185. package/dist/queries/deliveries/issues.d.ts +3 -0
  186. package/dist/queries/deliveries/issues.d.ts.map +1 -1
  187. package/dist/queries/deliveries/issues.js +10 -2
  188. package/dist/queries/deliveries/issues.js.map +1 -1
  189. package/dist/queries/delivery-gate-state/delivery-gate-holds.d.ts +27 -1
  190. package/dist/queries/delivery-gate-state/delivery-gate-holds.d.ts.map +1 -1
  191. package/dist/queries/delivery-gate-state/delivery-gate-state.d.ts +3 -1
  192. package/dist/queries/delivery-gate-state/delivery-gate-state.d.ts.map +1 -1
  193. package/dist/queries/delivery-gate-state/delivery-gate-state.js.map +1 -1
  194. package/dist/queries/focuses/focus-discovery.d.ts.map +1 -1
  195. package/dist/queries/focuses/focus-discovery.js +2 -0
  196. package/dist/queries/focuses/focus-discovery.js.map +1 -1
  197. package/dist/queries/focuses/focuses.d.ts.map +1 -1
  198. package/dist/queries/focuses/focuses.js +2 -0
  199. package/dist/queries/focuses/focuses.js.map +1 -1
  200. package/dist/queries/sessions/daemon-connection.d.ts.map +1 -1
  201. package/dist/queries/sessions/daemon-connection.js +1 -0
  202. package/dist/queries/sessions/daemon-connection.js.map +1 -1
  203. package/dist/queries/workflow-transitions/workflows.d.ts.map +1 -1
  204. package/dist/queries/workflow-transitions/workflows.js +1 -0
  205. package/dist/queries/workflow-transitions/workflows.js.map +1 -1
  206. package/dist/shell/config-hot-reload.d.ts +11 -0
  207. package/dist/shell/config-hot-reload.d.ts.map +1 -1
  208. package/dist/shell/config-hot-reload.js +12 -0
  209. package/dist/shell/config-hot-reload.js.map +1 -1
  210. package/dist/shell/unified-engine-lifecycle.d.ts +8 -1
  211. package/dist/shell/unified-engine-lifecycle.d.ts.map +1 -1
  212. package/dist/shell/unified-engine-lifecycle.js +44 -24
  213. package/dist/shell/unified-engine-lifecycle.js.map +1 -1
  214. package/dist/shell/unified-init.d.ts +5 -1
  215. package/dist/shell/unified-init.d.ts.map +1 -1
  216. package/dist/shell/unified-init.js +2 -2
  217. package/dist/shell/unified-init.js.map +1 -1
  218. package/dist/shell/unified-shell-config.d.ts +2 -1
  219. package/dist/shell/unified-shell-config.d.ts.map +1 -1
  220. package/dist/shell/unified-shell-config.js +9 -3
  221. package/dist/shell/unified-shell-config.js.map +1 -1
  222. package/dist/shell/unified-shell-status.d.ts +11 -1
  223. package/dist/shell/unified-shell-status.d.ts.map +1 -1
  224. package/dist/shell/unified-shell-status.js +15 -1
  225. package/dist/shell/unified-shell-status.js.map +1 -1
  226. package/dist/shell/unified-shell.d.ts.map +1 -1
  227. package/dist/shell/unified-shell.js +25 -5
  228. package/dist/shell/unified-shell.js.map +1 -1
  229. package/dist/spawn/codex-auth.d.ts +32 -0
  230. package/dist/spawn/codex-auth.d.ts.map +1 -0
  231. package/dist/spawn/codex-auth.js +55 -0
  232. package/dist/spawn/codex-auth.js.map +1 -0
  233. package/dist/spawn/helpers.d.ts.map +1 -1
  234. package/dist/spawn/helpers.js +19 -3
  235. package/dist/spawn/helpers.js.map +1 -1
  236. package/dist/spawn/model-reached.d.ts +36 -0
  237. package/dist/spawn/model-reached.d.ts.map +1 -0
  238. package/dist/spawn/model-reached.js +43 -0
  239. package/dist/spawn/model-reached.js.map +1 -0
  240. package/dist/spawn/next-spawn-cooldown.d.ts +21 -2
  241. package/dist/spawn/next-spawn-cooldown.d.ts.map +1 -1
  242. package/dist/spawn/next-spawn-cooldown.js +65 -7
  243. package/dist/spawn/next-spawn-cooldown.js.map +1 -1
  244. package/dist/spawn/process-spawn.d.ts.map +1 -1
  245. package/dist/spawn/process-spawn.js +8 -5
  246. package/dist/spawn/process-spawn.js.map +1 -1
  247. package/dist/spawn/review-hold-park.d.ts +12 -1
  248. package/dist/spawn/review-hold-park.d.ts.map +1 -1
  249. package/dist/spawn/review-hold-park.js +25 -9
  250. package/dist/spawn/review-hold-park.js.map +1 -1
  251. package/dist/spawn/spawn-decision.d.ts.map +1 -1
  252. package/dist/spawn/spawn-decision.js +4 -0
  253. package/dist/spawn/spawn-decision.js.map +1 -1
  254. package/dist/spawn/team-working-delivery.d.ts +76 -0
  255. package/dist/spawn/team-working-delivery.d.ts.map +1 -0
  256. package/dist/spawn/team-working-delivery.js +76 -0
  257. package/dist/spawn/team-working-delivery.js.map +1 -0
  258. package/dist/spawn/worktree-session.d.ts +15 -0
  259. package/dist/spawn/worktree-session.d.ts.map +1 -1
  260. package/dist/spawn/worktree-session.js +25 -2
  261. package/dist/spawn/worktree-session.js.map +1 -1
  262. package/dist/supervision/spawn-cooldown-window.d.ts +15 -0
  263. package/dist/supervision/spawn-cooldown-window.d.ts.map +1 -0
  264. package/dist/supervision/spawn-cooldown-window.js +46 -0
  265. package/dist/supervision/spawn-cooldown-window.js.map +1 -0
  266. package/dist/supervision/spawn-cooldown.d.ts +3 -2
  267. package/dist/supervision/spawn-cooldown.d.ts.map +1 -1
  268. package/dist/supervision/spawn-cooldown.js +6 -1
  269. package/dist/supervision/spawn-cooldown.js.map +1 -1
  270. package/dist/supervision/stop-registry.d.ts +1 -0
  271. package/dist/supervision/stop-registry.d.ts.map +1 -1
  272. package/dist/supervision/stop-rows-spawn.d.ts +8 -0
  273. package/dist/supervision/stop-rows-spawn.d.ts.map +1 -1
  274. package/dist/supervision/stop-rows-spawn.js +28 -1
  275. package/dist/supervision/stop-rows-spawn.js.map +1 -1
  276. package/dist/testing/fake-npm-registry.d.ts +31 -0
  277. package/dist/testing/fake-npm-registry.d.ts.map +1 -0
  278. package/dist/testing/fake-npm-registry.js +127 -0
  279. package/dist/testing/fake-npm-registry.js.map +1 -0
  280. package/dist/testing/fixtures/approved-head-inert-deps.d.ts.map +1 -1
  281. package/dist/testing/fixtures/approved-head-inert-deps.js +4 -2
  282. package/dist/testing/fixtures/approved-head-inert-deps.js.map +1 -1
  283. package/dist/testing/fixtures/codex-stream-session.d.ts +4 -0
  284. package/dist/testing/fixtures/codex-stream-session.d.ts.map +1 -1
  285. package/dist/testing/fixtures/codex-stream-session.js +21 -5
  286. package/dist/testing/fixtures/codex-stream-session.js.map +1 -1
  287. package/dist/testing/fixtures/completion-event-deps.js +1 -1
  288. package/dist/testing/fixtures/index.js +1 -1
  289. package/dist/testing/fixtures/process-close-context.d.ts.map +1 -1
  290. package/dist/testing/fixtures/process-close-context.js +2 -0
  291. package/dist/testing/fixtures/process-close-context.js.map +1 -1
  292. package/dist/testing/fixtures/recording-api-client.js +1 -1
  293. package/dist/testing/fixtures/review-exit-deps.js +1 -1
  294. package/dist/testing/fixtures/session-wire.d.ts.map +1 -1
  295. package/dist/testing/fixtures/session-wire.js +2 -1
  296. package/dist/testing/fixtures/session-wire.js.map +1 -1
  297. package/dist/testing/fixtures/verification-deps.d.ts.map +1 -1
  298. package/dist/testing/fixtures/verification-deps.js +4 -0
  299. package/dist/testing/fixtures/verification-deps.js.map +1 -1
  300. package/dist/types/config.d.ts +30 -0
  301. package/dist/types/config.d.ts.map +1 -1
  302. package/dist/types/focus-team-state.d.ts +28 -2
  303. package/dist/types/focus-team-state.d.ts.map +1 -1
  304. package/dist/types/focus-team-state.js.map +1 -1
  305. package/dist/types/index.js +1 -1
  306. package/dist/verify/deterministic-gate/verification-checkout.d.ts +8 -4
  307. package/dist/verify/deterministic-gate/verification-checkout.d.ts.map +1 -1
  308. package/dist/verify/deterministic-gate/verification-checkout.js +50 -13
  309. package/dist/verify/deterministic-gate/verification-checkout.js.map +1 -1
  310. package/dist/verify/deterministic-gate/verification-deterministic.d.ts.map +1 -1
  311. package/dist/verify/deterministic-gate/verification-deterministic.js +3 -1
  312. package/dist/verify/deterministic-gate/verification-deterministic.js.map +1 -1
  313. package/dist/verify/engine/verification-deps.d.ts +7 -0
  314. package/dist/verify/engine/verification-deps.d.ts.map +1 -1
  315. package/dist/verify/engine/verification-deps.js +1 -1
  316. package/dist/verify/engine/verification-engine.d.ts.map +1 -1
  317. package/dist/verify/engine/verification-engine.js +107 -8
  318. package/dist/verify/engine/verification-engine.js.map +1 -1
  319. package/dist/verify/gate-config/verification-config.js +1 -1
  320. package/dist/verify/gate-verdicts/commit-verdict-record.js +1 -1
  321. package/dist/verify/gate-verdicts/gate-run-registry.d.ts +74 -3
  322. package/dist/verify/gate-verdicts/gate-run-registry.d.ts.map +1 -1
  323. package/dist/verify/gate-verdicts/gate-run-registry.js +41 -20
  324. package/dist/verify/gate-verdicts/gate-run-registry.js.map +1 -1
  325. package/dist/verify/install-probe/in-repo-publish.d.ts +154 -0
  326. package/dist/verify/install-probe/in-repo-publish.d.ts.map +1 -0
  327. package/dist/verify/install-probe/in-repo-publish.js +183 -0
  328. package/dist/verify/install-probe/in-repo-publish.js.map +1 -0
  329. package/dist/verify/install-probe/install-probe-tick.d.ts +23 -2
  330. package/dist/verify/install-probe/install-probe-tick.d.ts.map +1 -1
  331. package/dist/verify/install-probe/install-probe-tick.js +84 -12
  332. package/dist/verify/install-probe/install-probe-tick.js.map +1 -1
  333. package/dist/verify/install-probe/install-probe.d.ts +16 -0
  334. package/dist/verify/install-probe/install-probe.d.ts.map +1 -1
  335. package/dist/verify/install-probe/install-probe.js +35 -19
  336. package/dist/verify/install-probe/install-probe.js.map +1 -1
  337. package/dist/verify/install-probe/npm-unresolved.d.ts +37 -0
  338. package/dist/verify/install-probe/npm-unresolved.d.ts.map +1 -0
  339. package/dist/verify/install-probe/npm-unresolved.js +63 -0
  340. package/dist/verify/install-probe/npm-unresolved.js.map +1 -0
  341. package/dist/verify/run-selection/default-on-guards.d.ts.map +1 -1
  342. package/dist/verify/run-selection/default-on-guards.js +1 -19
  343. package/dist/verify/run-selection/default-on-guards.js.map +1 -1
  344. package/dist/worktree/verify-interlock.d.ts +23 -2
  345. package/dist/worktree/verify-interlock.d.ts.map +1 -1
  346. package/dist/worktree/verify-interlock.js +79 -2
  347. package/dist/worktree/verify-interlock.js.map +1 -1
  348. package/package.json +3 -3
@@ -1,26 +1,39 @@
1
1
  // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
2
  // Pinned by: packages/daemon/src/focus/awaiting-slot.test.ts,
3
+ // packages/daemon/src/focus/focus-activity-producers.test.ts,
3
4
  // packages/daemon/src/focus/heartbeat-team-liveness-phases.test.ts
4
5
  // PINNED-BY-END
6
+ /** focusId -> epoch ms the pass FIRST left it waiting in the current unbroken run of passes. */
5
7
  const awaitingSlotByPass = {
6
- ready: new Set(),
7
- pending: new Set(),
8
+ ready: new Map(),
9
+ pending: new Map(),
8
10
  };
9
- /** Replace one pass's awaiting-slot set with the focuses it left waiting this run (empty clears it). */
10
- export function setAwaitingSlotFocuses(pass, focusIds) {
11
- awaitingSlotByPass[pass] = new Set(focusIds);
11
+ /**
12
+ * Replace one pass's awaiting-slot set with the focuses it left waiting this run
13
+ * (empty clears it). A focus still waiting keeps the time it was first recorded,
14
+ * so the published `since` names when the wait began, not the latest pass.
15
+ */
16
+ export function setAwaitingSlotFocuses(pass, focusIds, now = Date.now()) {
17
+ const prior = awaitingSlotByPass[pass];
18
+ awaitingSlotByPass[pass] = new Map([...focusIds].map((id) => [id, prior.get(id) ?? now]));
12
19
  }
13
20
  /** Every focus some pass left waiting for a slot (the union of both passes, deduplicated). */
14
21
  export function getAwaitingSlotFocusIds() {
15
- return [...new Set([...awaitingSlotByPass.ready, ...awaitingSlotByPass.pending])];
22
+ return [...new Set([...awaitingSlotByPass.ready.keys(), ...awaitingSlotByPass.pending.keys()])];
16
23
  }
17
24
  /** Whether some pass left this focus waiting for a slot on its latest run. */
18
25
  export function isAwaitingSlot(focusId) {
19
26
  return awaitingSlotByPass.ready.has(focusId) || awaitingSlotByPass.pending.has(focusId);
20
27
  }
28
+ /** When the focus's current wait for a slot began (the earlier of the two passes), or null when it is not waiting. */
29
+ export function awaitingSlotSince(focusId) {
30
+ const times = [awaitingSlotByPass.ready.get(focusId), awaitingSlotByPass.pending.get(focusId)]
31
+ .filter((t) => t !== undefined);
32
+ return times.length > 0 ? Math.min(...times) : null;
33
+ }
21
34
  /** Test-only: clear both passes' sets so state never leaks across tests. */
22
35
  export function __resetAwaitingSlotForTesting() {
23
- awaitingSlotByPass.ready = new Set();
24
- awaitingSlotByPass.pending = new Set();
36
+ awaitingSlotByPass.ready = new Map();
37
+ awaitingSlotByPass.pending = new Map();
25
38
  }
26
39
  //# sourceMappingURL=awaiting-slot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"awaiting-slot.js","sourceRoot":"","sources":["../../src/daemon-state/awaiting-slot.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,8DAA8D;AAC9D,qEAAqE;AACrE,gBAAgB;AA8BhB,MAAM,kBAAkB,GAA2C;IACjE,KAAK,EAAE,IAAI,GAAG,EAAE;IAChB,OAAO,EAAE,IAAI,GAAG,EAAE;CACnB,CAAC;AAEF,wGAAwG;AACxG,MAAM,UAAU,sBAAsB,CAAC,IAAe,EAAE,QAA0B;IAChF,kBAAkB,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,uBAAuB;IACrC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC1F,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,6BAA6B;IAC3C,kBAAkB,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;IACrC,kBAAkB,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"awaiting-slot.js","sourceRoot":"","sources":["../../src/daemon-state/awaiting-slot.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,8DAA8D;AAC9D,gEAAgE;AAChE,qEAAqE;AACrE,gBAAgB;AA8BhB,gGAAgG;AAChG,MAAM,kBAAkB,GAAmD;IACzE,KAAK,EAAE,IAAI,GAAG,EAAE;IAChB,OAAO,EAAE,IAAI,GAAG,EAAE;CACnB,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAe,EAAE,QAA0B,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;IAC1G,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACvC,kBAAkB,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,uBAAuB;IACrC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAClG,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC1F,CAAC;AAED,sHAAsH;AACtH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,KAAK,GAAG,CAAC,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;SAC3F,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IAC/C,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,6BAA6B;IAC3C,kBAAkB,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;IACrC,kBAAkB,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;AACzC,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * How long a not-ready engine holds its spawns before it is re-probed (and, if
3
+ * no re-probe runs, before one spawn is let through to try it). Five minutes:
4
+ * a host that was fixed (installed, logged in) resumes within one wait, and a
5
+ * host that was not costs one probe -- not one failed lead -- per wait.
6
+ */
7
+ export declare const ENGINE_REPROBE_MS: number;
8
+ /** The persisted record's file name, under the global state dir. */
9
+ export declare const ENGINE_READINESS_FILE = "engine-readiness.json";
10
+ /** What a not-ready engine lacks: its CLI binary, or its login. */
11
+ export type EngineMissing = 'binary' | 'login';
12
+ /** What last set an engine's readiness. */
13
+ export type EngineReadinessSource = 'probe' | 'spawn_enoent' | 'auth_failure';
14
+ /** One engine's readiness on this host. */
15
+ export interface EngineReadiness {
16
+ engineId: string;
17
+ ready: boolean;
18
+ /** What is missing when not ready; null when ready. */
19
+ missing: EngineMissing | null;
20
+ /** Names the missing binary or login (and how to fix it); null when ready. */
21
+ detail: string | null;
22
+ source: EngineReadinessSource;
23
+ /** When the engine entered its current readiness, epoch ms. */
24
+ sinceMs: number;
25
+ /** When a not-ready engine is next re-probed, epoch ms; null when ready. */
26
+ nextProbeAtMs: number | null;
27
+ /** Whether the gap holds spawns on the engine (see WHICH GAPS HOLD); false when ready. */
28
+ holdsSpawns: boolean;
29
+ }
30
+ /** The persisted file's shape. */
31
+ export interface PersistedEngineReadiness {
32
+ host: string;
33
+ updatedAt: string;
34
+ engines: EngineReadiness[];
35
+ }
36
+ /** A probe result, as backends' probeAvailability returns it. */
37
+ export interface EngineProbeResult {
38
+ available: boolean;
39
+ detail?: string;
40
+ missing?: EngineMissing;
41
+ }
42
+ /** Record what a probe found for an engine. A not-ready engine is re-probed after ENGINE_REPROBE_MS. */
43
+ export declare function recordEngineProbe(engineId: string, probe: EngineProbeResult, nowMs?: number): EngineReadiness;
44
+ /**
45
+ * Mark an engine not ready from a failed start or a failed authentication. Its
46
+ * spawns are held until a re-probe finds it ready or ENGINE_REPROBE_MS elapses.
47
+ */
48
+ export declare function markEngineNotReady(engineId: string, why: {
49
+ missing: EngineMissing;
50
+ detail: string;
51
+ source: Exclude<EngineReadinessSource, 'probe'>;
52
+ }, nowMs?: number): EngineReadiness;
53
+ /**
54
+ * The instant a not-ready engine's hold on its spawns ends, or null when it
55
+ * holds none: the engine is ready, unknown (never probed -- a spawn is its
56
+ * probe), reported without a hold, or its wait has elapsed.
57
+ */
58
+ export declare function engineNotReadyUntilMs(engineId: string, nowMs?: number): number | null;
59
+ /** True when any engine's readiness holds spawns now (the spawn gates resolve a route only then). */
60
+ export declare function anyEngineSpawnHold(nowMs?: number): boolean;
61
+ /** The engines whose re-probe is due: recorded not ready, with the wait elapsed. */
62
+ export declare function enginesDueForReprobe(nowMs?: number): string[];
63
+ /** Every engine's current readiness, in engine-id order. */
64
+ export declare function engineReadinessSnapshot(): EngineReadiness[];
65
+ /** Read the record the running daemon persisted, or null when there is none (or it is unreadable). */
66
+ export declare function readPersistedEngineReadiness(): PersistedEngineReadiness | null;
67
+ /** One engine's readiness line, as the startup log and `telora-daemon status` print it. */
68
+ export declare function formatEngineReadinessLine(record: Pick<EngineReadiness, 'engineId' | 'ready' | 'missing' | 'detail' | 'holdsSpawns'>): string;
69
+ /** Every engine's readiness line. */
70
+ export declare function formatEngineReadinessLines(engines: ReadonlyArray<Pick<EngineReadiness, 'engineId' | 'ready' | 'missing' | 'detail' | 'holdsSpawns'>>): string[];
71
+ /** Test-only: forget every record, as a daemon re-exec starts with none. */
72
+ export declare function __resetEngineReadinessForTests(): void;
73
+ //# sourceMappingURL=engine-readiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-readiness.d.ts","sourceRoot":"","sources":["../../src/daemon-state/engine-readiness.ts"],"names":[],"mappings":"AAmDA;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAa,CAAC;AAE5C,oEAAoE;AACpE,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,mEAAmE;AACnE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/C,2CAA2C;AAC3C,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,cAAc,GAAG,cAAc,CAAC;AAE9E,2CAA2C;AAC3C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,uDAAuD;IACvD,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9B,8EAA8E;IAC9E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,0FAA0F;IAC1F,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,kCAAkC;AAClC,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAsCD,wGAAwG;AACxG,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,GAAE,MAAmB,GAAG,eAAe,CAmBzH;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAA;CAAE,EAChG,KAAK,GAAE,MAAmB,GACzB,eAAe,CAejB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,MAAmB,GAAG,MAAM,GAAG,IAAI,CAIjG;AAED,qGAAqG;AACrG,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,MAAmB,GAAG,OAAO,CAGtE;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAAC,KAAK,GAAE,MAAmB,GAAG,MAAM,EAAE,CAIzE;AAED,4DAA4D;AAC5D,wBAAgB,uBAAuB,IAAI,eAAe,EAAE,CAE3D;AAED,sGAAsG;AACtG,wBAAgB,4BAA4B,IAAI,wBAAwB,GAAG,IAAI,CAU9E;AAED,2FAA2F;AAC3F,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,aAAa,CAAC,GAAG,MAAM,CAK5I;AAED,qCAAqC;AACrC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,aAAa,CAAC,CAAC,GAAG,MAAM,EAAE,CAE/J;AAED,4EAA4E;AAC5E,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
@@ -0,0 +1,191 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/daemon-state/engine-readiness.test.ts,
3
+ // packages/daemon/src/integration/engine-readiness-runtime.test.ts,
4
+ // packages/daemon/src/integration/model-reached-review-exit-effects.test.ts,
5
+ // packages/daemon/src/shell/unified-shell-status.test.ts, packages/daemon/src/spawn/codex-auth.test.ts,
6
+ // packages/daemon/src/spawn/engine-not-ready-gate.test.ts, packages/daemon/src/spawn/model-reached.test.ts
7
+ // PINNED-BY-END
8
+ /**
9
+ * Per-host engine readiness: can this host START each engine the daemon may
10
+ * spawn (claude, codex), and can that engine AUTHENTICATE?
11
+ *
12
+ * Readiness is HOST STATE. An engine whose binary is missing, or which is not
13
+ * logged in, is not a team failure, not a review and not an escalation (the
14
+ * standing ruling: config gaps are state, never escalations). Without this
15
+ * record a missing binary drew a failed lead on every poll, and nothing a human
16
+ * looks at said the host could not run the engine.
17
+ *
18
+ * So:
19
+ * - A probe (backends/availability.ts, the backends' own probeAvailability)
20
+ * seeds the record at startup and re-reads a not-ready engine.
21
+ * - A failed start (ENOENT, spawn/process-spawn.ts) or a failed authentication
22
+ * (a Codex 401, spawn/codex-auth.ts) marks the engine not ready.
23
+ * - While an engine is not ready AND the gap holds spawns, no lead is spawned
24
+ * on it (the `engine_not_ready` stop row, read by the spawn gates) until a
25
+ * re-probe finds it ready or ENGINE_REPROBE_MS elapses. A re-probe that finds
26
+ * it ready clears the record -- installing or logging in needs no restart.
27
+ *
28
+ * WHICH GAPS HOLD. A missing binary always does: nothing can start it. A missing
29
+ * login does only once a spawn has OBSERVED the authentication fail. The host
30
+ * probe reads the host's own login (~/.codex/auth.json, ~/.claude.json, the
31
+ * daemon's env) and cannot see a key the per-spawn environment supplies
32
+ * (spawn/spawn-environment.ts fetchBackendEnvExtras), so a probe that finds only
33
+ * the login missing is REPORTED -- status and the startup log say so -- but
34
+ * holds nothing (spawn/process-spawn.ts gateLocalModelBackendSpawn makes the
35
+ * same call for the same reason).
36
+ *
37
+ * The record is persisted under the global state dir so the separate
38
+ * `telora-daemon status` process can read what the running daemon knows.
39
+ *
40
+ * History: docs/daemon/history-team-lifecycle.md (daemon-state/engine-readiness.ts).
41
+ */
42
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
43
+ import { hostname } from 'node:os';
44
+ import { join } from 'node:path';
45
+ import { resolveGlobalStateDir } from './daemon-process.js';
46
+ import { createLogger } from '../log/daemon-log.js';
47
+ const log = createLogger({ module: 'engine-readiness' });
48
+ /**
49
+ * How long a not-ready engine holds its spawns before it is re-probed (and, if
50
+ * no re-probe runs, before one spawn is let through to try it). Five minutes:
51
+ * a host that was fixed (installed, logged in) resumes within one wait, and a
52
+ * host that was not costs one probe -- not one failed lead -- per wait.
53
+ */
54
+ export const ENGINE_REPROBE_MS = 5 * 60_000;
55
+ /** The persisted record's file name, under the global state dir. */
56
+ export const ENGINE_READINESS_FILE = 'engine-readiness.json';
57
+ const records = new Map();
58
+ function statePath() {
59
+ return join(resolveGlobalStateDir(), ENGINE_READINESS_FILE);
60
+ }
61
+ /** Write the record for `telora-daemon status`. Best-effort: a failed write never breaks a spawn. */
62
+ function persist(nowMs) {
63
+ try {
64
+ const dir = resolveGlobalStateDir();
65
+ if (!existsSync(dir))
66
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
67
+ const body = {
68
+ host: hostname(),
69
+ updatedAt: new Date(nowMs).toISOString(),
70
+ engines: [...records.values()],
71
+ };
72
+ const path = statePath();
73
+ const tmp = `${path}.tmp`;
74
+ writeFileSync(tmp, `${JSON.stringify(body, null, 2)}\n`, { mode: 0o600 });
75
+ renameSync(tmp, path);
76
+ }
77
+ catch (err) {
78
+ log.warn(`[engine] could not persist engine readiness: ${err.message}`);
79
+ }
80
+ }
81
+ function set(next, nowMs) {
82
+ const prev = records.get(next.engineId);
83
+ records.set(next.engineId, next);
84
+ // A change of readiness is logged as it happens; the first reading is printed
85
+ // by the startup report (shell/unified-shell-status.ts reportEngineReadiness).
86
+ if (prev && (prev.ready !== next.ready || prev.missing !== next.missing)) {
87
+ log.info(formatEngineReadinessLine(next));
88
+ }
89
+ persist(nowMs);
90
+ }
91
+ /** Record what a probe found for an engine. A not-ready engine is re-probed after ENGINE_REPROBE_MS. */
92
+ export function recordEngineProbe(engineId, probe, nowMs = Date.now()) {
93
+ const prev = records.get(engineId);
94
+ const ready = probe.available;
95
+ const missing = ready ? null : (probe.missing ?? 'binary');
96
+ const unchanged = prev !== undefined && prev.ready === ready && prev.missing === missing;
97
+ // A login the probe cannot find holds spawns only when a spawn already saw it fail.
98
+ const holdsSpawns = !ready && (missing === 'binary' || (unchanged && prev.holdsSpawns));
99
+ const next = {
100
+ engineId,
101
+ ready,
102
+ missing,
103
+ detail: ready ? null : (unchanged && prev.detail ? prev.detail : (probe.detail ?? `${engineId} is not ready on ${hostname()}`)),
104
+ source: unchanged ? prev.source : 'probe',
105
+ sinceMs: unchanged ? prev.sinceMs : nowMs,
106
+ nextProbeAtMs: ready ? null : nowMs + ENGINE_REPROBE_MS,
107
+ holdsSpawns,
108
+ };
109
+ set(next, nowMs);
110
+ return next;
111
+ }
112
+ /**
113
+ * Mark an engine not ready from a failed start or a failed authentication. Its
114
+ * spawns are held until a re-probe finds it ready or ENGINE_REPROBE_MS elapses.
115
+ */
116
+ export function markEngineNotReady(engineId, why, nowMs = Date.now()) {
117
+ const prev = records.get(engineId);
118
+ const unchanged = prev !== undefined && !prev.ready && prev.missing === why.missing;
119
+ const next = {
120
+ engineId,
121
+ ready: false,
122
+ missing: why.missing,
123
+ detail: why.detail,
124
+ source: why.source,
125
+ sinceMs: unchanged ? prev.sinceMs : nowMs,
126
+ nextProbeAtMs: nowMs + ENGINE_REPROBE_MS,
127
+ holdsSpawns: true,
128
+ };
129
+ set(next, nowMs);
130
+ return next;
131
+ }
132
+ /**
133
+ * The instant a not-ready engine's hold on its spawns ends, or null when it
134
+ * holds none: the engine is ready, unknown (never probed -- a spawn is its
135
+ * probe), reported without a hold, or its wait has elapsed.
136
+ */
137
+ export function engineNotReadyUntilMs(engineId, nowMs = Date.now()) {
138
+ const record = records.get(engineId);
139
+ if (!record || record.ready || !record.holdsSpawns || record.nextProbeAtMs === null)
140
+ return null;
141
+ return record.nextProbeAtMs > nowMs ? record.nextProbeAtMs : null;
142
+ }
143
+ /** True when any engine's readiness holds spawns now (the spawn gates resolve a route only then). */
144
+ export function anyEngineSpawnHold(nowMs = Date.now()) {
145
+ for (const record of records.values())
146
+ if (engineNotReadyUntilMs(record.engineId, nowMs) !== null)
147
+ return true;
148
+ return false;
149
+ }
150
+ /** The engines whose re-probe is due: recorded not ready, with the wait elapsed. */
151
+ export function enginesDueForReprobe(nowMs = Date.now()) {
152
+ return [...records.values()]
153
+ .filter((r) => !r.ready && r.nextProbeAtMs !== null && r.nextProbeAtMs <= nowMs)
154
+ .map((r) => r.engineId);
155
+ }
156
+ /** Every engine's current readiness, in engine-id order. */
157
+ export function engineReadinessSnapshot() {
158
+ return [...records.values()].sort((a, b) => a.engineId.localeCompare(b.engineId));
159
+ }
160
+ /** Read the record the running daemon persisted, or null when there is none (or it is unreadable). */
161
+ export function readPersistedEngineReadiness() {
162
+ try {
163
+ const path = statePath();
164
+ if (!existsSync(path))
165
+ return null;
166
+ const parsed = JSON.parse(readFileSync(path, 'utf8'));
167
+ if (typeof parsed !== 'object' || parsed === null || !Array.isArray(parsed.engines))
168
+ return null;
169
+ return parsed;
170
+ }
171
+ catch {
172
+ return null;
173
+ }
174
+ }
175
+ /** One engine's readiness line, as the startup log and `telora-daemon status` print it. */
176
+ export function formatEngineReadinessLine(record) {
177
+ if (record.ready)
178
+ return `[engine] ${record.engineId}: ready (starts and authenticates on ${hostname()})`;
179
+ const what = record.missing === 'login' ? 'not logged in' : 'binary not found';
180
+ const hold = record.holdsSpawns ? 'no lead is spawned on it until it re-probes ready' : 'reported only; a per-spawn key may still authenticate it';
181
+ return `[engine] ${record.engineId}: NOT READY on ${hostname()} -- ${what}: ${record.detail ?? 'no detail recorded'} (${hold})`;
182
+ }
183
+ /** Every engine's readiness line. */
184
+ export function formatEngineReadinessLines(engines) {
185
+ return [...engines].sort((a, b) => a.engineId.localeCompare(b.engineId)).map(formatEngineReadinessLine);
186
+ }
187
+ /** Test-only: forget every record, as a daemon re-exec starts with none. */
188
+ export function __resetEngineReadinessForTests() {
189
+ records.clear();
190
+ }
191
+ //# sourceMappingURL=engine-readiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-readiness.js","sourceRoot":"","sources":["../../src/daemon-state/engine-readiness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /** Whether a delivery moving from `from` to `to` is forward progress toward done. The ONE definition. */
2
+ export declare function isForwardDeliveryAdvance(from: string | null | undefined, to: string | null | undefined): boolean;
3
+ /** Record a read of a focus's deliveries; stamps the clock when one advanced forward since the last status known for it. */
4
+ export declare function observeDeliveryProgress(focusId: string, rows: readonly {
5
+ id: string;
6
+ executionStatus?: string | null;
7
+ }[], now: number): void;
8
+ /** Record a read of one delivery's issues; stamps the clock when an issue seen open before is now Done. */
9
+ export declare function observeIssueProgress(focusId: string, deliveryId: string, issues: readonly {
10
+ id: string;
11
+ status: string;
12
+ }[], now: number): void;
13
+ /**
14
+ * A delivery status write LANDED at `now` (the physical writer calls this once
15
+ * its write resolved). Stamps the clock of the focus whose latest read listed
16
+ * the delivery when the move is forward from the last status known for it, and
17
+ * records the written status so the next read does not count the same move
18
+ * again at its later time.
19
+ */
20
+ export declare function recordDeliveryStatusWrite(deliveryId: string, status: string, now: number): void;
21
+ /**
22
+ * An issue status write LANDED at `now` (the issue status writer calls this once
23
+ * its write resolved). Stamps the clock of the focus whose latest read of a
24
+ * delivery's issues listed the issue when the write completed it, and records
25
+ * the written status so the next read does not count it again.
26
+ */
27
+ export declare function recordIssueStatusWrite(issueId: string, status: string, now: number): void;
28
+ /** When the focus's work last moved forward (epoch ms), or null when this process has seen no movement. */
29
+ export declare function readFocusLastProgressAt(focusId: string): number | null;
30
+ /** Forget a focus that is no longer active (the poll stopped listing it). */
31
+ export declare function forgetFocusProgress(focusId: string): void;
32
+ /** Test-only: forget every focus. */
33
+ export declare function __resetFocusProgressClockForTests(): void;
34
+ //# sourceMappingURL=focus-progress-clock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focus-progress-clock.d.ts","sourceRoot":"","sources":["../../src/daemon-state/focus-progress-clock.ts"],"names":[],"mappings":"AAuEA,yGAAyG;AACzG,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAIhH;AAiCD,4HAA4H;AAC5H,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,EAChE,GAAG,EAAE,MAAM,GACV,IAAI,CAUN;AAED,2GAA2G;AAC3G,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,EACjD,GAAG,EAAE,MAAM,GACV,IAAI,CASN;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAQ/F;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CASzF;AAED,2GAA2G;AAC3G,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEtE;AAED,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED,qCAAqC;AACrC,wBAAgB,iCAAiC,IAAI,IAAI,CAExD"}
@@ -0,0 +1,167 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/focus/focus-activity-progress-clock.test.ts,
3
+ // packages/daemon/src/focus/heartbeat-focus-activity.test.ts
4
+ // PINNED-BY-END
5
+ /**
6
+ * The per-focus PROGRESS CLOCK: when a focus's work last moved forward, by the
7
+ * two facts the focus activity record names -- a delivery's execution status
8
+ * advancing FORWARD ({@link isForwardDeliveryAdvance}: queued -> coding ->
9
+ * verify -> done, and verify_failed -> coding) or an issue moving to Done. The
10
+ * record publishes it as every entry's `lastProgressAt`
11
+ * (focus/focus-activity-sources.ts commonFields).
12
+ *
13
+ * Why its own clock: the live team's progress measure
14
+ * (completion/team-progress/team-stillness.ts) is forgotten when the team ends,
15
+ * so the between-sessions entries (idle, cooldown, review_parked, a pending
16
+ * spawn) -- exactly the ones a reader checks for churn -- would publish no
17
+ * progress time at all. This clock is keyed by focus, not by team: a teardown,
18
+ * a respawn or a session ending changes nothing here, so repeated teardowns
19
+ * without progress leave the time standing while the spawn-teardown streak
20
+ * grows beside it.
21
+ *
22
+ * TWO FEEDS, one primary:
23
+ *
24
+ * 1. The daemon's own WRITES, stamped when they land. The physical delivery
25
+ * status writer (queries/deliveries/deliveries.ts updateDeliveryStatus)
26
+ * calls {@link recordDeliveryStatusWrite} once its write resolves, and the
27
+ * issue status writer (queries/deliveries/issues.ts updateIssueStatus)
28
+ * calls {@link recordIssueStatusWrite}: the stamp is the write's own time,
29
+ * not the next poll's.
30
+ * 2. The poll's READS, as RECOVERY (focus/focus-activity-poll-facts.ts), at
31
+ * no extra query: each read of a focus's deliveries and of a delivery's
32
+ * issues is compared with the last status this clock knows for the same
33
+ * rows -- which a landed write has already updated, so the write is not
34
+ * counted twice at the later read time. What the reads catch is movement
35
+ * written ELSEWHERE (an agent closing an issue over MCP, an operator).
36
+ *
37
+ * A write names a delivery or issue, not a focus: it is attributed to the focus
38
+ * whose latest read listed that row. A write to a row no read has listed yet
39
+ * stamps nothing (the first read of it is its baseline). The FIRST read of a
40
+ * focus's deliveries or of a delivery's issues is a baseline, not movement -- a
41
+ * restart or a newly active focus publishes null until something actually
42
+ * moves, never the daemon's boot time dressed up as progress. Only forward
43
+ * edges count: a back-path (verify -> verify_failed, a re-queue) or an issue
44
+ * re-opened is not progress.
45
+ *
46
+ * In memory, per daemon process. Nothing is written to the database.
47
+ *
48
+ * @module daemon-state/focus-progress-clock
49
+ */
50
+ import { DELIVERY_STATUS } from '@telora/daemon-core';
51
+ /**
52
+ * A delivery's position on the main path toward done; a status absent here
53
+ * (draft, planning, paused, cancelled) is off the path, so no move into or out
54
+ * of it is progress. verify_failed sits with queued: its work is owed again, so
55
+ * a re-queue (verify_failed -> queued) is not progress and a restart
56
+ * (verify_failed -> coding) is. Every adjacent forward step here is a declared
57
+ * EXECUTION_STATUS_TRANSITIONS edge (pinned by the progress-clock test); a read
58
+ * may observe a multi-step jump (queued -> verify between two polls), which is
59
+ * forward too.
60
+ */
61
+ const MAIN_PATH_RANK = new Map([
62
+ [DELIVERY_STATUS.QUEUED, 0],
63
+ [DELIVERY_STATUS.VERIFY_FAILED, 0],
64
+ [DELIVERY_STATUS.CODING, 1],
65
+ [DELIVERY_STATUS.VERIFY, 2],
66
+ [DELIVERY_STATUS.DONE, 3],
67
+ ]);
68
+ /** Whether a delivery moving from `from` to `to` is forward progress toward done. The ONE definition. */
69
+ export function isForwardDeliveryAdvance(from, to) {
70
+ const a = MAIN_PATH_RANK.get(from ?? '');
71
+ const b = MAIN_PATH_RANK.get(to ?? '');
72
+ return a !== undefined && b !== undefined && b > a;
73
+ }
74
+ /** An issue reaching one of these has moved to Done. */
75
+ const DONE_ISSUE_STATUSES = new Set(['Done', 'Verified']);
76
+ /** Whether an issue moving from `before` to `after` completed it. */
77
+ function isIssueCompletion(before, after) {
78
+ return before !== undefined && !DONE_ISSUE_STATUSES.has(before) && DONE_ISSUE_STATUSES.has(after);
79
+ }
80
+ const clocks = new Map();
81
+ function clockOf(focusId) {
82
+ let clock = clocks.get(focusId);
83
+ if (!clock) {
84
+ clock = { deliveryStatuses: null, issueStatuses: new Map(), lastProgressAt: null };
85
+ clocks.set(focusId, clock);
86
+ }
87
+ return clock;
88
+ }
89
+ function stamp(clock, now) {
90
+ clock.lastProgressAt = clock.lastProgressAt === null ? now : Math.max(clock.lastProgressAt, now);
91
+ }
92
+ /** Record a read of a focus's deliveries; stamps the clock when one advanced forward since the last status known for it. */
93
+ export function observeDeliveryProgress(focusId, rows, now) {
94
+ const clock = clockOf(focusId);
95
+ const prior = clock.deliveryStatuses;
96
+ const next = new Map(rows.map((d) => [d.id, d.executionStatus ?? null]));
97
+ if (prior) {
98
+ const advanced = [...next].some(([id, status]) => prior.has(id) && isForwardDeliveryAdvance(prior.get(id), status));
99
+ if (advanced)
100
+ stamp(clock, now);
101
+ }
102
+ clock.deliveryStatuses = next;
103
+ for (const deliveryId of clock.issueStatuses.keys())
104
+ if (!next.has(deliveryId))
105
+ clock.issueStatuses.delete(deliveryId);
106
+ }
107
+ /** Record a read of one delivery's issues; stamps the clock when an issue seen open before is now Done. */
108
+ export function observeIssueProgress(focusId, deliveryId, issues, now) {
109
+ const clock = clockOf(focusId);
110
+ const prior = clock.issueStatuses.get(deliveryId);
111
+ const next = new Map(issues.map((i) => [i.id, i.status]));
112
+ if (prior) {
113
+ const completed = [...next].some(([id, status]) => isIssueCompletion(prior.get(id), status));
114
+ if (completed)
115
+ stamp(clock, now);
116
+ }
117
+ clock.issueStatuses.set(deliveryId, next);
118
+ }
119
+ /**
120
+ * A delivery status write LANDED at `now` (the physical writer calls this once
121
+ * its write resolved). Stamps the clock of the focus whose latest read listed
122
+ * the delivery when the move is forward from the last status known for it, and
123
+ * records the written status so the next read does not count the same move
124
+ * again at its later time.
125
+ */
126
+ export function recordDeliveryStatusWrite(deliveryId, status, now) {
127
+ for (const clock of clocks.values()) {
128
+ const statuses = clock.deliveryStatuses;
129
+ if (!statuses?.has(deliveryId))
130
+ continue;
131
+ if (isForwardDeliveryAdvance(statuses.get(deliveryId), status))
132
+ stamp(clock, now);
133
+ statuses.set(deliveryId, status);
134
+ return;
135
+ }
136
+ }
137
+ /**
138
+ * An issue status write LANDED at `now` (the issue status writer calls this once
139
+ * its write resolved). Stamps the clock of the focus whose latest read of a
140
+ * delivery's issues listed the issue when the write completed it, and records
141
+ * the written status so the next read does not count it again.
142
+ */
143
+ export function recordIssueStatusWrite(issueId, status, now) {
144
+ for (const clock of clocks.values()) {
145
+ for (const issues of clock.issueStatuses.values()) {
146
+ if (!issues.has(issueId))
147
+ continue;
148
+ if (isIssueCompletion(issues.get(issueId), status))
149
+ stamp(clock, now);
150
+ issues.set(issueId, status);
151
+ return;
152
+ }
153
+ }
154
+ }
155
+ /** When the focus's work last moved forward (epoch ms), or null when this process has seen no movement. */
156
+ export function readFocusLastProgressAt(focusId) {
157
+ return clocks.get(focusId)?.lastProgressAt ?? null;
158
+ }
159
+ /** Forget a focus that is no longer active (the poll stopped listing it). */
160
+ export function forgetFocusProgress(focusId) {
161
+ clocks.delete(focusId);
162
+ }
163
+ /** Test-only: forget every focus. */
164
+ export function __resetFocusProgressClockForTests() {
165
+ clocks.clear();
166
+ }
167
+ //# sourceMappingURL=focus-progress-clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focus-progress-clock.js","sourceRoot":"","sources":["../../src/daemon-state/focus-progress-clock.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,8 @@
11
11
  * Owner of the `lifecycle` and `activity` sub-records of FocusTeamState (see
12
12
  * types/focus-team-state.ts, TEAM_STATE_OWNERS): every write of phase,
13
13
  * shutdownReason, shutdownAttribution, shuttingDownAt, lastActivityAt,
14
- * toolActivityCount and errorResultAt goes through a writer exported here.
14
+ * toolActivityCount, errorResultAt, modelReachedAt and the working delivery goes through a writer
15
+ * exported here.
15
16
  *
16
17
  * The ONE intentional side-table is `slotTokens`. It is deliberately NOT folded
17
18
  * onto the record because its lifecycle must OUTLIVE activeTeams membership: a
@@ -39,6 +40,26 @@ import type { ShutdownAttribution, TeamShutdownReason } from '../types/shutdown-
39
40
  * @param now Epoch ms of the event (default Date.now()).
40
41
  */
41
42
  export declare function recordTeamActivity(focusId: string, now?: number): void;
43
+ /**
44
+ * Record the delivery `team` is working, observed at `observedAt`. Bound to the
45
+ * team OBJECT, not its focus: an observation that resolves after its team left
46
+ * activeTeams (and a replacement took the focus) is dropped, never stamped on the
47
+ * replacement. An observation older than the one already recorded is dropped too
48
+ * (resolutions complete out of order).
49
+ */
50
+ export declare function recordTeamWorkingDelivery(team: FocusTeamState, deliveryId: string, observedAt: number): void;
51
+ /**
52
+ * Seed the delivery a team is spawned to work (spawn/team-working-delivery.ts
53
+ * workingDeliveryAtSpawn), before its first act. Dated at epoch 0, so any
54
+ * observation of the team's own acts supersedes it.
55
+ */
56
+ export declare function seedTeamWorkingDelivery(team: FocusTeamState, deliveryId: string): void;
57
+ /**
58
+ * Record that `team` was spawned with no delivery to work on a focus whose
59
+ * deliveries are all terminal (spawn/team-working-delivery.ts). A delivery its
60
+ * own acts later name supersedes it (the producer reads the delivery first).
61
+ */
62
+ export declare function seedTeamResolvingWithoutDelivery(team: FocusTeamState): void;
42
63
  /**
43
64
  * Epoch ms of the team's last recorded agent event, or null when nothing has
44
65
  * been recorded yet (e.g. a team still initializing before its first event, or
@@ -88,6 +109,8 @@ export declare function setTeamShutdownReason(team: FocusTeamState, reason: Team
88
109
  export declare function setShutdownAttribution(team: FocusTeamState, attribution: ShutdownAttribution): void;
89
110
  /** Count one tool invocation by the pass (inspection evidence for the review-exit gate). */
90
111
  export declare function countToolActivity(team: FocusTeamState): void;
112
+ /** Record that the session's model was reached, at the FIRST output it produced (later outputs keep that instant). */
113
+ export declare function markModelReached(team: FocusTeamState, atMs: number): void;
91
114
  /** Record that the session emitted a terminal-error result at `atMs`. */
92
115
  export declare function stampErrorResult(team: FocusTeamState, atMs: number): void;
93
116
  /**
@@ -153,18 +176,18 @@ export declare function hasActiveTeam(focusId: string): boolean;
153
176
  */
154
177
  export declare function getActiveTeamCount(): number;
155
178
  /**
156
- * Build the per-focus published activity-clock map: focusId -> epoch ms of the
157
- * team's last recorded agent event, for every active team that has recorded at
158
- * least one event. This publishes the SAME in-memory clock the daemon acts on to
159
- * decide a team is still running (getTeamLastActivityAt / recordTeamActivity), so
160
- * every liveness surface can classify from the one clock the daemon trusts
161
- * instead of the separately-flushed agent_sessions.activity_summary.updatedAt.
179
+ * Build the per-focus activity-clock map: focusId -> epoch ms of the team's last
180
+ * recorded agent event, for every active team that has recorded at least one
181
+ * event -- the SAME in-memory clock the daemon acts on to decide a team is still
182
+ * running (getTeamLastActivityAt / recordTeamActivity). The heartbeat feeds it to
183
+ * the clock-divergence health check; it is no longer published as
184
+ * metadata.teamClocks (the focus activity record carries the clock as
185
+ * lastAgentEventAt on its team entries).
162
186
  *
163
187
  * Pull-model, exactly like buildTeamLivenessPhaseMap: recomputed from live activeTeams
164
188
  * each heartbeat, so a torn-down focus drops out of the map on its own. A team
165
189
  * still initializing before its first event (lastActivityAt undefined) is
166
- * omitted -- an absent clock reads as "fall back to activity_summary" downstream,
167
- * never as a frozen-since-epoch team.
190
+ * omitted -- an absent clock is "no event yet", never a frozen-since-epoch team.
168
191
  */
169
192
  export declare function buildTeamClockMap(): Record<string, number>;
170
193
  /**