cloving 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. package/README.md +329 -215
  2. package/dist/src/agent-harness-shell.d.ts +2 -1
  3. package/dist/src/agent-harness-shell.js +8 -5
  4. package/dist/src/authority/command-wait-checks.d.ts +8 -0
  5. package/dist/src/authority/command-wait-checks.js +88 -0
  6. package/dist/src/authority/command-wait-results.d.ts +15 -0
  7. package/dist/src/authority/command-wait-results.js +73 -0
  8. package/dist/src/authority/command-wait-view.d.ts +21 -0
  9. package/dist/src/authority/command-wait-view.js +34 -0
  10. package/dist/src/authority/command-waits.d.ts +39 -0
  11. package/dist/src/authority/command-waits.js +97 -0
  12. package/dist/src/authority/commands.js +22 -1
  13. package/dist/src/authority/dispatch-decision.d.ts +8 -0
  14. package/dist/src/authority/dispatch-decision.js +26 -1
  15. package/dist/src/authority/effect-requests.js +6 -3
  16. package/dist/src/authority/effect-results.js +4 -2
  17. package/dist/src/authority/history-state.d.ts +2 -0
  18. package/dist/src/authority/history-state.js +13 -1
  19. package/dist/src/authority/instants.d.ts +1 -0
  20. package/dist/src/authority/instants.js +21 -0
  21. package/dist/src/authority/reduction-state.d.ts +2 -0
  22. package/dist/src/authority/reduction-state.js +5 -0
  23. package/dist/src/authority/reduction.js +24 -0
  24. package/dist/src/authority/status-input.d.ts +2 -0
  25. package/dist/src/authority/status.d.ts +2 -0
  26. package/dist/src/authority/status.js +1 -0
  27. package/dist/src/authority/stop-sequence.d.ts +1 -0
  28. package/dist/src/authority/stop-sequence.js +2 -1
  29. package/dist/src/authority/transitions.d.ts +6 -4
  30. package/dist/src/authority/transitions.js +7 -0
  31. package/dist/src/broker/actor/authority-health.d.ts +9 -0
  32. package/dist/src/broker/actor/authority-health.js +24 -0
  33. package/dist/src/broker/actor/authority-queries.d.ts +2 -1
  34. package/dist/src/broker/actor/authority-queries.js +14 -5
  35. package/dist/src/broker/actor/authority-receipts.js +1 -1
  36. package/dist/src/broker/actor/authority-runtime.d.ts +4 -2
  37. package/dist/src/broker/actor/authority-runtime.js +29 -20
  38. package/dist/src/broker/actor/authority-session.d.ts +6 -19
  39. package/dist/src/broker/actor/authority-session.js +66 -88
  40. package/dist/src/broker/actor/authority-settings.d.ts +2 -1
  41. package/dist/src/broker/actor/authority-settings.js +6 -3
  42. package/dist/src/broker/actor/authority-upgrades.d.ts +23 -2
  43. package/dist/src/broker/actor/authority-upgrades.js +8 -2
  44. package/dist/src/broker/actor/authority-watchdog.d.ts +6 -2
  45. package/dist/src/broker/actor/authority-watchdog.js +31 -9
  46. package/dist/src/broker/actor/authority.js +3 -1
  47. package/dist/src/broker/actor/delivery-intents.js +2 -0
  48. package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
  49. package/dist/src/broker/actor/effect-delivery.js +15 -2
  50. package/dist/src/broker/actor/effect-plan.js +11 -2
  51. package/dist/src/broker/actor/effect-queries.d.ts +4 -0
  52. package/dist/src/broker/actor/effect-queries.js +9 -1
  53. package/dist/src/broker/actor/effect-turn.js +2 -0
  54. package/dist/src/broker/actor/projection-memory.d.ts +43 -0
  55. package/dist/src/broker/actor/projection-memory.js +207 -0
  56. package/dist/src/broker/actor/runtime-parts.d.ts +5 -0
  57. package/dist/src/broker/actor/runtime-parts.js +8 -3
  58. package/dist/src/broker/actor/stop-plan.js +9 -3
  59. package/dist/src/broker/actor/stop-turn.d.ts +2 -0
  60. package/dist/src/broker/actor/stop-turn.js +24 -11
  61. package/dist/src/broker/actor/turn-draft.d.ts +1 -0
  62. package/dist/src/broker/actor/turn-draft.js +4 -0
  63. package/dist/src/broker/actor/turn-state.js +5 -1
  64. package/dist/src/broker/authority-admission.js +60 -0
  65. package/dist/src/broker/authority-restore.d.ts +2 -0
  66. package/dist/src/broker/authority-restore.js +35 -1
  67. package/dist/src/broker/command-wait-restore.d.ts +31 -0
  68. package/dist/src/broker/command-wait-restore.js +86 -0
  69. package/dist/src/broker/decision-restore.d.ts +1 -1
  70. package/dist/src/broker/decision-restore.js +1 -0
  71. package/dist/src/broker/effect-upgrade.d.ts +3 -0
  72. package/dist/src/broker/effect-upgrade.js +11 -2
  73. package/dist/src/cli/arguments.d.ts +13 -0
  74. package/dist/src/cli/arguments.js +43 -3
  75. package/dist/src/cli/chat-stores.d.ts +2 -0
  76. package/dist/src/cli/chat-stores.js +113 -0
  77. package/dist/src/cli/client.d.ts +7 -2
  78. package/dist/src/cli/client.js +13 -7
  79. package/dist/src/cli/command-requests.d.ts +46 -0
  80. package/dist/src/cli/command-requests.js +84 -0
  81. package/dist/src/cli/command-waits.d.ts +9 -0
  82. package/dist/src/cli/command-waits.js +51 -0
  83. package/dist/src/cli/commands.js +70 -88
  84. package/dist/src/cli/config-file.d.ts +2 -2
  85. package/dist/src/cli/config-file.js +4 -2
  86. package/dist/src/cli/config-notice.js +5 -2
  87. package/dist/src/cli/doctor-retention.d.ts +2 -0
  88. package/dist/src/cli/doctor-retention.js +93 -0
  89. package/dist/src/cli/doctor-workflows.d.ts +5 -2
  90. package/dist/src/cli/doctor-workflows.js +12 -7
  91. package/dist/src/cli/doctor.js +11 -9
  92. package/dist/src/cli/harness-probes.d.ts +2 -0
  93. package/dist/src/cli/harness-probes.js +1 -1
  94. package/dist/src/cli/harness-processes.d.ts +6 -0
  95. package/dist/src/cli/harness-processes.js +36 -0
  96. package/dist/src/cli/init-command.d.ts +9 -0
  97. package/dist/src/cli/init-command.js +52 -0
  98. package/dist/src/cli/init-prompt-command.d.ts +10 -0
  99. package/dist/src/cli/init-prompt-command.js +145 -0
  100. package/dist/src/cli/init-prompt.d.ts +35 -0
  101. package/dist/src/cli/init-prompt.js +74 -0
  102. package/dist/src/cli/init-selection.d.ts +13 -0
  103. package/dist/src/cli/init-selection.js +75 -0
  104. package/dist/src/cli/main.d.ts +2 -0
  105. package/dist/src/cli/main.js +37 -7
  106. package/dist/src/cli/mcp-server.d.ts +1 -0
  107. package/dist/src/cli/mcp-server.js +156 -0
  108. package/dist/src/cli/mcp-tools.d.ts +15 -0
  109. package/dist/src/cli/mcp-tools.js +242 -0
  110. package/dist/src/cli/queue-arguments.d.ts +15 -0
  111. package/dist/src/cli/queue-arguments.js +31 -0
  112. package/dist/src/cli/queue-render.d.ts +3 -0
  113. package/dist/src/cli/queue-render.js +26 -0
  114. package/dist/src/cli/reload-render.d.ts +2 -0
  115. package/dist/src/cli/reload-render.js +12 -0
  116. package/dist/src/cli/render.d.ts +1 -1
  117. package/dist/src/cli/render.js +54 -38
  118. package/dist/src/cli/report-ci-jobs.d.ts +23 -0
  119. package/dist/src/cli/report-ci-jobs.js +103 -0
  120. package/dist/src/cli/report-ci-usage.d.ts +9 -0
  121. package/dist/src/cli/report-ci-usage.js +185 -0
  122. package/dist/src/cli/report-ci.d.ts +13 -0
  123. package/dist/src/cli/report-ci.js +74 -0
  124. package/dist/src/cli/report-closures.d.ts +6 -0
  125. package/dist/src/cli/report-closures.js +97 -0
  126. package/dist/src/cli/report-flow.d.ts +7 -0
  127. package/dist/src/cli/report-flow.js +122 -0
  128. package/dist/src/cli/report-github-reader.d.ts +29 -0
  129. package/dist/src/cli/report-github-reader.js +157 -0
  130. package/dist/src/cli/report-github.d.ts +15 -8
  131. package/dist/src/cli/report-github.js +131 -150
  132. package/dist/src/cli/report-operator.d.ts +3 -0
  133. package/dist/src/cli/report-operator.js +40 -0
  134. package/dist/src/cli/report-ready.d.ts +3 -0
  135. package/dist/src/cli/report-ready.js +96 -0
  136. package/dist/src/cli/report-text.d.ts +9 -0
  137. package/dist/src/cli/report-text.js +33 -0
  138. package/dist/src/cli/report.d.ts +1 -0
  139. package/dist/src/cli/report.js +104 -27
  140. package/dist/src/cli/runtime-arguments.d.ts +18 -3
  141. package/dist/src/cli/runtime-arguments.js +29 -20
  142. package/dist/src/cli/schedule-arguments.d.ts +14 -0
  143. package/dist/src/cli/schedule-arguments.js +26 -0
  144. package/dist/src/cli/schedule-render.d.ts +22 -0
  145. package/dist/src/cli/schedule-render.js +73 -0
  146. package/dist/src/cli/terminal-text.d.ts +3 -0
  147. package/dist/src/cli/terminal-text.js +28 -0
  148. package/dist/src/cli/toolchain.d.ts +1 -0
  149. package/dist/src/cli/toolchain.js +1 -0
  150. package/dist/src/cli/usage-render.d.ts +1 -0
  151. package/dist/src/cli/usage-render.js +28 -1
  152. package/dist/src/cli/usage.d.ts +2 -2
  153. package/dist/src/cli/usage.js +89 -11
  154. package/dist/src/cli/watch-actions.js +2 -2
  155. package/dist/src/cli/watch-api-document.d.ts +430 -0
  156. package/dist/src/cli/watch-api-document.js +291 -0
  157. package/dist/src/cli/watch-api-run.d.ts +56 -0
  158. package/dist/src/cli/watch-api-run.js +112 -0
  159. package/dist/src/cli/watch-api.d.ts +17 -0
  160. package/dist/src/cli/watch-api.js +230 -0
  161. package/dist/src/cli/watch-board-view.js +19 -2
  162. package/dist/src/cli/watch-board.d.ts +4 -2
  163. package/dist/src/cli/watch-board.js +53 -43
  164. package/dist/src/cli/watch-card-forms.d.ts +1 -1
  165. package/dist/src/cli/watch-card-forms.js +11 -10
  166. package/dist/src/cli/watch-client.d.ts +1 -1
  167. package/dist/src/cli/watch-client.js +2 -11
  168. package/dist/src/cli/watch-header-view.d.ts +1 -5
  169. package/dist/src/cli/watch-header-view.js +17 -21
  170. package/dist/src/cli/watch-model.d.ts +5 -1
  171. package/dist/src/cli/watch-model.js +20 -11
  172. package/dist/src/cli/watch-page.js +15 -15
  173. package/dist/src/cli/watch-phases.d.ts +12 -3
  174. package/dist/src/cli/watch-phases.js +68 -11
  175. package/dist/src/cli/watch-pr-board.js +1 -1
  176. package/dist/src/cli/watch-pr-command.d.ts +1 -0
  177. package/dist/src/cli/watch-pull-request.js +18 -8
  178. package/dist/src/cli/watch-reads.d.ts +3 -0
  179. package/dist/src/cli/watch-reads.js +22 -20
  180. package/dist/src/cli/watch-render.d.ts +15 -0
  181. package/dist/src/cli/watch-run-input.d.ts +0 -1
  182. package/dist/src/cli/watch-run-input.js +0 -13
  183. package/dist/src/cli/watch-server.js +24 -10
  184. package/dist/src/cli/watch-view.d.ts +0 -3
  185. package/dist/src/cli/watch-view.js +13 -13
  186. package/dist/src/cli.js +73 -12
  187. package/dist/src/command-wait.d.ts +4 -0
  188. package/dist/src/command-wait.js +45 -0
  189. package/dist/src/configuration-change.d.ts +7 -0
  190. package/dist/src/configuration-change.js +14 -0
  191. package/dist/src/configuration-display.js +2 -0
  192. package/dist/src/configuration-schema.d.ts +14 -0
  193. package/dist/src/configuration-schema.js +6 -2
  194. package/dist/src/daemon/attachment-file.d.ts +6 -0
  195. package/dist/src/daemon/attachment-file.js +86 -0
  196. package/dist/src/daemon/attachments.d.ts +14 -0
  197. package/dist/src/daemon/attachments.js +17 -0
  198. package/dist/src/daemon/claude-recovery.d.ts +50 -0
  199. package/dist/src/daemon/claude-recovery.js +208 -0
  200. package/dist/src/daemon/claude-stream.d.ts +27 -0
  201. package/dist/src/daemon/claude-stream.js +63 -0
  202. package/dist/src/daemon/claude-turn.d.ts +11 -25
  203. package/dist/src/daemon/claude-turn.js +64 -81
  204. package/dist/src/daemon/claude-worker.d.ts +5 -4
  205. package/dist/src/daemon/claude-worker.js +127 -126
  206. package/dist/src/daemon/daemon-adapters.d.ts +9 -0
  207. package/dist/src/daemon/daemon-adapters.js +33 -5
  208. package/dist/src/daemon/daemon-loops.d.ts +5 -1
  209. package/dist/src/daemon/daemon-loops.js +18 -10
  210. package/dist/src/daemon/daemon.js +80 -61
  211. package/dist/src/daemon/github-attach.d.ts +2 -0
  212. package/dist/src/daemon/github-attach.js +222 -0
  213. package/dist/src/daemon/github-calls.js +1 -1
  214. package/dist/src/daemon/github-ci-filters.d.ts +6 -0
  215. package/dist/src/daemon/github-ci-filters.js +138 -0
  216. package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
  217. package/dist/src/daemon/github-ci-workflows.js +148 -0
  218. package/dist/src/daemon/github-ci.js +22 -4
  219. package/dist/src/daemon/github-issue-methods.d.ts +2 -0
  220. package/dist/src/daemon/github-issue-methods.js +37 -2
  221. package/dist/src/daemon/github-merge-call.d.ts +2 -1
  222. package/dist/src/daemon/github-merge-call.js +10 -3
  223. package/dist/src/daemon/github-merge.js +52 -24
  224. package/dist/src/daemon/github-methods.js +18 -4
  225. package/dist/src/daemon/github-operation.d.ts +4 -0
  226. package/dist/src/daemon/github-operation.js +6 -0
  227. package/dist/src/daemon/github-worker.d.ts +4 -0
  228. package/dist/src/daemon/github-worker.js +6 -0
  229. package/dist/src/daemon/issue-queue.d.ts +4 -1
  230. package/dist/src/daemon/issue-queue.js +76 -78
  231. package/dist/src/daemon/merge-turns.d.ts +10 -0
  232. package/dist/src/daemon/merge-turns.js +37 -0
  233. package/dist/src/daemon/notify-events.d.ts +6 -0
  234. package/dist/src/daemon/notify-events.js +84 -0
  235. package/dist/src/daemon/notify-journal.js +1 -1
  236. package/dist/src/daemon/notify-message.d.ts +4 -1
  237. package/dist/src/daemon/notify-message.js +36 -0
  238. package/dist/src/daemon/notify.d.ts +1 -1
  239. package/dist/src/daemon/notify.js +5 -77
  240. package/dist/src/daemon/operation-journal.d.ts +1 -0
  241. package/dist/src/daemon/queue-control.d.ts +13 -0
  242. package/dist/src/daemon/queue-control.js +86 -0
  243. package/dist/src/daemon/queue-journal.d.ts +20 -0
  244. package/dist/src/daemon/queue-journal.js +89 -0
  245. package/dist/src/daemon/queue-status.d.ts +9 -3
  246. package/dist/src/daemon/queue-status.js +17 -4
  247. package/dist/src/daemon/record-archive.d.ts +19 -0
  248. package/dist/src/daemon/record-archive.js +82 -0
  249. package/dist/src/daemon/record-sweep.d.ts +24 -0
  250. package/dist/src/daemon/record-sweep.js +147 -0
  251. package/dist/src/daemon/resume-index-lock.d.ts +13 -0
  252. package/dist/src/daemon/resume-index-lock.js +160 -0
  253. package/dist/src/daemon/resume-worktree.d.ts +7 -0
  254. package/dist/src/daemon/resume-worktree.js +29 -0
  255. package/dist/src/daemon/retrying-turn.d.ts +2 -12
  256. package/dist/src/daemon/retrying-turn.js +98 -172
  257. package/dist/src/daemon/schedule-control.d.ts +26 -0
  258. package/dist/src/daemon/schedule-control.js +110 -0
  259. package/dist/src/daemon/schedule-journal.d.ts +2 -15
  260. package/dist/src/daemon/schedule-journal.js +67 -4
  261. package/dist/src/daemon/settings-reload.d.ts +26 -0
  262. package/dist/src/daemon/settings-reload.js +82 -0
  263. package/dist/src/daemon/ticket-registration.d.ts +2 -7
  264. package/dist/src/daemon/ticket-registration.js +15 -81
  265. package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
  266. package/dist/src/daemon/turn-attempt-journal.js +136 -0
  267. package/dist/src/daemon/turn-attempts.d.ts +47 -0
  268. package/dist/src/daemon/turn-attempts.js +166 -0
  269. package/dist/src/daemon/turn-details.d.ts +4 -0
  270. package/dist/src/daemon/turn-details.js +33 -0
  271. package/dist/src/daemon/turn-report.d.ts +8 -1
  272. package/dist/src/daemon/turn-report.js +39 -0
  273. package/dist/src/daemon/work-tree.d.ts +9 -0
  274. package/dist/src/daemon/work-tree.js +20 -0
  275. package/dist/src/daemon/worker-profile.d.ts +9 -0
  276. package/dist/src/daemon/worker-profile.js +44 -0
  277. package/dist/src/daemon/workflow-generations.d.ts +7 -4
  278. package/dist/src/daemon/workflow-generations.js +22 -14
  279. package/dist/src/daemon/workflow-reload.d.ts +41 -0
  280. package/dist/src/daemon/workflow-reload.js +244 -0
  281. package/dist/src/daemon/workflow-replay.d.ts +2 -1
  282. package/dist/src/daemon/workflow-replay.js +7 -3
  283. package/dist/src/daemon/workflow-schedules.d.ts +3 -0
  284. package/dist/src/daemon/workflow-schedules.js +98 -45
  285. package/dist/src/daemon/worktree-processes.d.ts +9 -0
  286. package/dist/src/daemon/worktree-processes.js +151 -0
  287. package/dist/src/doctor-report.d.ts +4 -6
  288. package/dist/src/doctor-report.js +8 -13
  289. package/dist/src/harness-start.d.ts +15 -0
  290. package/dist/src/harness-start.js +37 -0
  291. package/dist/src/host/command-wait.d.ts +38 -0
  292. package/dist/src/host/command-wait.js +115 -0
  293. package/dist/src/host/start-delivery.d.ts +5 -7
  294. package/dist/src/host/start-delivery.js +3 -15
  295. package/dist/src/host/step-bridge-host.d.ts +2 -0
  296. package/dist/src/host/step-bridge-host.js +21 -0
  297. package/dist/src/operation-identity.d.ts +1 -0
  298. package/dist/src/operation-identity.js +4 -0
  299. package/dist/src/private-config.schema.json +71 -0
  300. package/dist/src/project-config.schema.json +40 -0
  301. package/dist/src/project-settings.d.ts +16 -2
  302. package/dist/src/project-settings.js +35 -1
  303. package/dist/src/queue-spend.d.ts +4 -0
  304. package/dist/src/queue-spend.js +21 -0
  305. package/dist/src/queue-state.d.ts +26 -0
  306. package/dist/src/queue-state.js +34 -0
  307. package/dist/src/record-retention.d.ts +46 -0
  308. package/dist/src/record-retention.js +81 -0
  309. package/dist/src/relay/relay-service.d.ts +3 -0
  310. package/dist/src/relay/relay-service.js +5 -3
  311. package/dist/src/report-ci.d.ts +164 -0
  312. package/dist/src/report-ci.js +32 -0
  313. package/dist/src/report-effects.d.ts +15 -0
  314. package/dist/src/report-effects.js +212 -0
  315. package/dist/src/report-flow-types.d.ts +38 -0
  316. package/dist/src/report-flow-types.js +7 -0
  317. package/dist/src/report-flow.d.ts +43 -0
  318. package/dist/src/report-flow.js +193 -0
  319. package/dist/src/report-operator.d.ts +67 -0
  320. package/dist/src/report-operator.js +25 -0
  321. package/dist/src/report-quality.d.ts +221 -0
  322. package/dist/src/report-quality.js +94 -0
  323. package/dist/src/report-ready.d.ts +23 -0
  324. package/dist/src/report-ready.js +117 -0
  325. package/dist/src/report-statistics.d.ts +2 -1
  326. package/dist/src/report-statistics.js +40 -4
  327. package/dist/src/report.d.ts +588 -47
  328. package/dist/src/report.js +156 -41
  329. package/dist/src/schedule-progress.d.ts +33 -0
  330. package/dist/src/schedule-progress.js +45 -0
  331. package/dist/src/service/active-tickets.js +11 -6
  332. package/dist/src/service/command-waits.d.ts +34 -0
  333. package/dist/src/service/command-waits.js +86 -0
  334. package/dist/src/service/dispatcher.d.ts +4 -0
  335. package/dist/src/service/dispatcher.js +33 -0
  336. package/dist/src/service/expiry.js +2 -0
  337. package/dist/src/service/gateway.js +3 -1
  338. package/dist/src/service/queue-handlers.d.ts +4 -0
  339. package/dist/src/service/queue-handlers.js +32 -0
  340. package/dist/src/service/queue-spend.d.ts +6 -0
  341. package/dist/src/service/queue-spend.js +68 -0
  342. package/dist/src/service/registry.d.ts +28 -2
  343. package/dist/src/service/registry.js +48 -0
  344. package/dist/src/service/replies.d.ts +22 -8
  345. package/dist/src/service/replies.js +16 -2
  346. package/dist/src/service/run-handlers.js +37 -12
  347. package/dist/src/service/run-metadata.d.ts +15 -1
  348. package/dist/src/service/run-metadata.js +93 -8
  349. package/dist/src/service/service.d.ts +11 -3
  350. package/dist/src/service/service.js +22 -37
  351. package/dist/src/service/submission-handler.js +18 -4
  352. package/dist/src/service/worker-port.js +9 -1
  353. package/dist/src/service/worker-totals.d.ts +6 -0
  354. package/dist/src/service/worker-totals.js +8 -1
  355. package/dist/src/service/workflow-reload.d.ts +35 -0
  356. package/dist/src/service/workflow-reload.js +52 -0
  357. package/dist/src/step-bridge.d.ts +20 -0
  358. package/dist/src/steps/command-wait.d.ts +12 -0
  359. package/dist/src/steps/command-wait.js +26 -0
  360. package/dist/src/steps/open-decision-wait.d.ts +2 -0
  361. package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
  362. package/dist/src/steps/review-by-person.js +4 -1
  363. package/dist/src/steps/wait-for-command.d.ts +3 -0
  364. package/dist/src/steps/wait-for-command.js +17 -0
  365. package/dist/src/steps/wait-for-decision.js +1 -1
  366. package/dist/src/storage/command-wait-rows.d.ts +30 -0
  367. package/dist/src/storage/command-wait-rows.js +96 -0
  368. package/dist/src/storage/decision-snapshots.d.ts +8 -2
  369. package/dist/src/storage/decision-snapshots.js +16 -8
  370. package/dist/src/storage/domain-changes.d.ts +3 -1
  371. package/dist/src/storage/domain-changes.js +4 -0
  372. package/dist/src/storage/domain-schema.d.ts +16 -1
  373. package/dist/src/storage/domain-schema.js +35 -4
  374. package/dist/src/storage/effect-schema.d.ts +2 -0
  375. package/dist/src/storage/effect-schema.js +9 -0
  376. package/dist/src/storage/projection-changes.d.ts +12 -0
  377. package/dist/src/storage/projection-changes.js +194 -0
  378. package/dist/src/storage/projection-lookups.d.ts +7 -0
  379. package/dist/src/storage/projection-lookups.js +30 -0
  380. package/dist/src/testing-requests.d.ts +15 -0
  381. package/dist/src/testing-requests.js +93 -0
  382. package/dist/src/testing.d.ts +4 -10
  383. package/dist/src/testing.js +33 -86
  384. package/dist/src/worker-usage.d.ts +1 -0
  385. package/dist/src/worker-usage.js +3 -0
  386. package/dist/src/workflow-candidate.d.ts +1 -0
  387. package/dist/src/workflow-candidate.js +12 -1
  388. package/dist/src/workflow-contracts.d.ts +1 -0
  389. package/dist/src/workflow-contracts.js +9 -2
  390. package/dist/src/workflow-declaration.d.ts +1 -0
  391. package/dist/src/workflow-declaration.js +3 -0
  392. package/dist/src/workflow-discovery.d.ts +2 -13
  393. package/dist/src/workflow-discovery.js +1 -13
  394. package/dist/src/workflow-refusals.js +0 -1
  395. package/dist/src/workflows.d.ts +1 -1
  396. package/dist/src/workflows.js +1 -1
  397. package/dist/tools/compile-workflows.js +3 -0
  398. package/dist/tools/project-configuration.d.ts +7 -2
  399. package/dist/tools/project-configuration.js +30 -1
  400. package/dist/tools/red-green-command.d.ts +1 -0
  401. package/dist/tools/red-green-command.js +174 -0
  402. package/dist/tools/red-green-process.d.ts +10 -0
  403. package/dist/tools/red-green-process.js +59 -0
  404. package/dist/tools/self-host-processes.d.ts +2 -0
  405. package/dist/tools/self-host-processes.js +69 -26
  406. package/dist/tools/self-host-project.d.ts +2 -0
  407. package/dist/tools/self-host-project.js +30 -77
  408. package/dist/tools/self-host-runtime.js +1 -1
  409. package/dist/tools/self-host.js +76 -34
  410. package/dist/tools/template-command.d.ts +1 -0
  411. package/dist/tools/template-command.js +160 -0
  412. package/dist/tools/template-copy.d.ts +11 -0
  413. package/dist/tools/template-copy.js +130 -0
  414. package/dist/tools/template-files.d.ts +17 -0
  415. package/dist/tools/template-files.js +74 -0
  416. package/dist/tools/workflow-bundles.js +1 -0
  417. package/dist/tools/workflow-candidate-counts.js +2 -2
  418. package/dist/tools/workflow-candidate-program.d.ts +4 -2
  419. package/dist/tools/workflow-candidate-program.js +30 -11
  420. package/dist/tools/workflow-candidate-shape.d.ts +3 -0
  421. package/dist/tools/workflow-candidate-shape.js +90 -0
  422. package/dist/tools/workflow-candidate-source.d.ts +1 -0
  423. package/dist/tools/workflow-candidate-source.js +26 -4
  424. package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
  425. package/dist/tools/workflow-candidate-syntax.js +24 -94
  426. package/dist/tools/workflow-command.js +1 -2
  427. package/dist/tools/workflow-folders.d.ts +2 -3
  428. package/dist/tools/workflow-folders.js +1 -1
  429. package/package.json +17 -9
  430. package/templates/develop/README.md +93 -4
  431. package/templates/develop/develop/flow-tests.ts +38 -1
  432. package/templates/develop/develop/interruption-tests.ts +157 -0
  433. package/templates/develop/develop/local.ts +1 -0
  434. package/templates/develop/develop/option-tests.ts +138 -9
  435. package/templates/develop/develop/pull.ts +5 -1
  436. package/templates/develop/develop/red-green.ts +55 -0
  437. package/templates/develop/develop/refusal-tests.ts +77 -0
  438. package/templates/develop/develop/report.ts +31 -11
  439. package/templates/develop/develop/round.ts +1 -0
  440. package/templates/develop/develop/scenarios.ts +27 -0
  441. package/templates/develop/develop/turn.ts +28 -7
  442. package/templates/develop/develop.declaration.json +1 -1
  443. package/templates/develop/develop.test.ts +4 -0
  444. package/templates/develop/template.json +29 -2
  445. package/templates/idea-to-issue/README.md +27 -0
  446. package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
  447. package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
  448. package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
  449. package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
  450. package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
  451. package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
  452. package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
  453. package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
  454. package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
  455. package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
  456. package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
  457. package/templates/idea-to-issue/idea-to-issue.ts +49 -0
  458. package/templates/idea-to-issue/template.json +81 -0
  459. package/templates/review-day/README.md +97 -0
  460. package/templates/review-day/review-day/critique.ts +58 -0
  461. package/templates/review-day/review-day/decision.ts +29 -0
  462. package/templates/review-day/review-day/facts.ts +69 -0
  463. package/templates/review-day/review-day/label.ts +29 -0
  464. package/templates/review-day/review-day/next.ts +28 -0
  465. package/templates/review-day/review-day/post.ts +27 -0
  466. package/templates/review-day/review-day/report.ts +98 -0
  467. package/templates/review-day/review-day/rules.ts +12 -0
  468. package/templates/review-day/review-day/scenarios.ts +76 -0
  469. package/templates/review-day/review-day/turn.ts +73 -0
  470. package/templates/review-day/review-day.declaration.json +16 -0
  471. package/templates/review-day/review-day.test.ts +362 -0
  472. package/templates/review-day/review-day.ts +37 -0
  473. package/templates/review-day/template.json +56 -0
  474. package/dist/src/cli/watch-start-view.d.ts +0 -18
  475. package/dist/src/cli/watch-start-view.js +0 -77
  476. package/dist/src/steps/decision-gate.d.ts +0 -3
  477. package/dist/workflows/develop-prd.d.ts +0 -7
  478. package/dist/workflows/develop-prd.js +0 -165
  479. package/dist/workflows/develop-ticket.d.ts +0 -9
  480. package/dist/workflows/develop-ticket.js +0 -207
  481. package/dist/workflows/issue-labels.d.ts +0 -16
  482. package/dist/workflows/issue-labels.js +0 -70
  483. package/dist/workflows/ticket-prompts.d.ts +0 -35
  484. package/dist/workflows/ticket-prompts.js +0 -147
@@ -36,3 +36,24 @@ export function notBefore(value, bound) {
36
36
  export function isAfter(value, bound) {
37
37
  return notBefore(value, bound) && !notBefore(bound, value);
38
38
  }
39
+ function leapDaysBefore(year) {
40
+ const previous = year - 1;
41
+ return (Math.floor(previous / 4) -
42
+ Math.floor(previous / 100) +
43
+ Math.floor(previous / 400));
44
+ }
45
+ export function instantMilliseconds(value) {
46
+ if (!isInstant(value))
47
+ throw new Error("invalid-instant");
48
+ const year = Number(value.slice(0, 4));
49
+ const month = Number(value.slice(5, 7));
50
+ let days = Number(value.slice(8, 10)) - 1;
51
+ for (let preceding = 1; preceding < month; preceding += 1)
52
+ days += daysIn(year, preceding);
53
+ days += 365 * (year - 1970) + leapDaysBefore(year) - leapDaysBefore(1970);
54
+ return (days * 86_400_000 +
55
+ Number(value.slice(11, 13)) * 3_600_000 +
56
+ Number(value.slice(14, 16)) * 60_000 +
57
+ Number(value.slice(17, 19)) * 1000 +
58
+ Number(value.slice(20, 23)));
59
+ }
@@ -1,3 +1,4 @@
1
+ import { type CommandWaitsState } from "./command-waits.ts";
1
2
  import { type RunDetails } from "./details.ts";
2
3
  import { type GateState } from "./gates.ts";
3
4
  import { type Disposition, type EffectState } from "./operations.ts";
@@ -20,6 +21,7 @@ export interface Recorded {
20
21
  }
21
22
  export interface Change extends Recorded {
22
23
  readonly moved?: RunState;
24
+ readonly commandWaits?: CommandWaitsState;
23
25
  readonly gates?: readonly GateState[];
24
26
  readonly added?: readonly EffectIntent[];
25
27
  readonly questions?: number;
@@ -1,3 +1,4 @@
1
+ import { closedCommandWaits } from "./command-waits.js";
1
2
  import { operationIdentity } from "../operation-identity.js";
2
3
  import { continued } from "./details.js";
3
4
  import { gateKey } from "./gates.js";
@@ -40,12 +41,16 @@ function nextDetails(change) {
40
41
  }
41
42
  export function applied(state, change) {
42
43
  const { event } = change;
44
+ const waits = change.commandWaits ?? state.commandWaits;
43
45
  return {
44
46
  kind: "applied",
45
47
  ...(change.disposition === undefined
46
48
  ? {}
47
49
  : { disposition: change.disposition }),
48
50
  state: {
51
+ ...(waits === undefined
52
+ ? {}
53
+ : { commandWaits: closedCommandWaits(waits, event) }),
49
54
  sequence: event.sequence,
50
55
  runs: change.moved
51
56
  ? { ...state.runs, [event.runId]: change.moved }
@@ -1,3 +1,6 @@
1
+ import { checkedCommandWait } from "./command-wait-checks.js";
2
+ import { waitEffectTime, waitEffectChange } from "./command-wait-results.js";
3
+ import { commandWaitKey, commandWaitsAfter, validCommandWaitTime, } from "./command-waits.js";
1
4
  import { admittedDetails, observed } from "./details.js";
2
5
  import { settled } from "./gates.js";
3
6
  import { admittedBudgets } from "./budgets.js";
@@ -57,6 +60,8 @@ function dispatched(state, recorded) {
57
60
  function effect(rule) {
58
61
  return (state, recorded) => {
59
62
  const { event, run } = recorded;
63
+ if (!waitEffectTime(state.commandWaits ?? {}, event))
64
+ return invalid("invalid-recorded-time");
60
65
  const result = rule(state.effects, { event, runStatus: run.status });
61
66
  if (result.kind === "invalid")
62
67
  return result;
@@ -64,6 +69,7 @@ function effect(rule) {
64
69
  return applied(state, {
65
70
  ...recorded,
66
71
  effects: result.effects,
72
+ ...waitEffectChange(state, { event, result }),
67
73
  ...(result.released === undefined ? {} : { released: result.released }),
68
74
  ...(result.disposition === undefined
69
75
  ? {}
@@ -78,8 +84,24 @@ function effect(rule) {
78
84
  });
79
85
  };
80
86
  }
87
+ const changeCommandWait = (state, recorded) => {
88
+ const { event, run } = recorded;
89
+ const waits = state.commandWaits ?? {};
90
+ const key = commandWaitKey(event.runId, event.payload["waitName"] ?? "");
91
+ if (event.type === "command-wait.opened" &&
92
+ waits[key] === undefined &&
93
+ run.status !== "running")
94
+ return invalid("command-wait-run-not-running");
95
+ const result = commandWaitsAfter(waits, event);
96
+ return result.kind === "invalid"
97
+ ? result
98
+ : applied(state, { ...recorded, commandWaits: result.waits });
99
+ };
81
100
  const handlers = {
82
101
  "schedule.skipped": applied,
102
+ "command-wait.opened": changeCommandWait,
103
+ "command-wait.checked": checkedCommandWait,
104
+ "command-wait.expired": changeCommandWait,
83
105
  "effect.requested": effect(requested),
84
106
  "lease.granted": effect(granted),
85
107
  "lease.expired": effect(leaseExpired),
@@ -146,6 +168,8 @@ function created(state, recorded) {
146
168
  };
147
169
  }
148
170
  export function reduce(state, event) {
171
+ if (!validCommandWaitTime(state.commandWaits ?? {}, event))
172
+ return invalid("invalid-command-wait-time");
149
173
  if (event.sequence !== state.sequence + 1)
150
174
  return invalid("sequence-gap");
151
175
  if (state.commands[event.commandId])
@@ -1,3 +1,4 @@
1
+ import type { CommandWaitView } from "./command-wait-view.ts";
1
2
  import type { RunDetails } from "./details.ts";
2
3
  import type { GateState } from "./gates.ts";
3
4
  import type { RunClosure } from "./stop-sequence.ts";
@@ -21,6 +22,7 @@ export interface BudgetSummary {
21
22
  readonly spent: number;
22
23
  }
23
24
  export interface StatusInput {
25
+ readonly commandWaits: readonly CommandWaitView[];
24
26
  readonly run: RunState;
25
27
  readonly details: RunDetails | undefined;
26
28
  readonly gates: readonly GateState[];
@@ -1,3 +1,4 @@
1
+ import type { CommandWaitView } from "./command-wait-view.ts";
1
2
  import { type EffectView, type Recovery } from "./status-effects.ts";
2
3
  import { type BudgetSummary, type StatusInput } from "./status-input.ts";
3
4
  import type { RunStatus } from "./transitions.ts";
@@ -5,6 +6,7 @@ export { unresolved, unresolvedEffects } from "./status-closure.ts";
5
6
  export type { EffectView } from "./status-effects.ts";
6
7
  export type { Assessment, BudgetSummary, EffectSummary, OperationSummary, StatusInput, } from "./status-input.ts";
7
8
  export interface RunView {
9
+ readonly commandWaits: readonly CommandWaitView[];
8
10
  readonly runId: string;
9
11
  readonly workflow: string;
10
12
  readonly state: RunStatus;
@@ -266,6 +266,7 @@ export function runView(input) {
266
266
  attempts: observation?.attempt ?? 0,
267
267
  limit: observation?.limit ?? null,
268
268
  },
269
+ commandWaits: input.commandWaits,
269
270
  budget: input.budget,
270
271
  effects: effectViews(input.effects),
271
272
  nextAction: assessment.nextAction,
@@ -5,6 +5,7 @@ export interface AttemptSummary {
5
5
  readonly stagedSequence: number;
6
6
  }
7
7
  export interface StopSubject {
8
+ readonly stopSequence?: number;
8
9
  readonly operationId: string;
9
10
  readonly kind: string;
10
11
  readonly attempts: readonly AttemptSummary[];
@@ -39,7 +39,8 @@ const stopPurposes = ["stop", "reconcile"];
39
39
  export function stopCount(subject, cancelledSequence) {
40
40
  return subject.attempts.filter((attempt) => attempt.outcome !== null &&
41
41
  stopPurposes.includes(attempt.purpose) &&
42
- attempt.stagedSequence >= cancelledSequence).length;
42
+ attempt.stagedSequence >=
43
+ Math.max(cancelledSequence, subject.stopSequence ?? 0)).length;
43
44
  }
44
45
  const uncertainStatuses = ["recovering", "blocked"];
45
46
  function uncertain(subject) {
@@ -1,3 +1,4 @@
1
+ import type { CommandWaitsState } from "./command-waits.ts";
1
2
  import type { RunDetails } from "./details.ts";
2
3
  import type { GateState } from "./gates.ts";
3
4
  import type { EffectState } from "./operations.ts";
@@ -26,9 +27,10 @@ export interface AuthorityState {
26
27
  readonly gates: Readonly<Record<string, GateState>>;
27
28
  readonly details: Readonly<Record<string, RunDetails>>;
28
29
  readonly questions: number;
30
+ readonly commandWaits?: CommandWaitsState;
29
31
  readonly effects: EffectState;
30
32
  }
31
- export declare const eventTypes: readonly ["run.created", "run.started", "gate.opened", "gate.wait-registered", "gate.decided", "gate.expired", "run.paused", "run.resumed", "run.completed", "run.failed", "run.cancelled", "run.observed", "step.dispatched", "effect.requested", "lease.granted", "lease.expired", "effect.reported", "operation.reconciled", "schedule.skipped"];
33
+ export declare const eventTypes: readonly ["run.created", "run.started", "gate.opened", "gate.wait-registered", "gate.decided", "gate.expired", "run.paused", "run.resumed", "run.completed", "run.failed", "run.cancelled", "run.observed", "step.dispatched", "effect.requested", "lease.granted", "lease.expired", "effect.reported", "operation.reconciled", "schedule.skipped", "command-wait.opened", "command-wait.checked", "command-wait.expired"];
32
34
  export type EventType = (typeof eventTypes)[number];
33
35
  export interface AuthorityEvent {
34
36
  readonly sequence: number;
@@ -39,8 +41,8 @@ export interface AuthorityEvent {
39
41
  readonly request: string;
40
42
  readonly payload: Readonly<Record<string, string>>;
41
43
  }
42
- export declare const numberFields: readonly ["expectedRevision", "expectedObservation", "generation", "attempt", "limit", "effectLimit", "units", "recoveryLimit", "leaseGeneration", "sourceGeneration", "capacity", "slot"];
43
- export declare const textFields: readonly ["parentRunId", "chainId", "workflow", "workflowId", "submission", "input", "resolver", "gateId", "gateKind", "waitMode", "subject", "prompt", "expiresAt", "decision", "answer", "condition", "reason", "evidence", "retryAt", "operationId", "receipt", "capabilities", "capability", "method", "target", "payload", "inputDigest", "resource", "transport", "source", "worker", "outcome", "outcomeReason", "promotionId", "ticketStatus", "issueUpdate", "result", "actor"];
44
+ export declare const numberFields: readonly ["expectedRevision", "expectedObservation", "generation", "attempt", "limit", "effectLimit", "units", "recoveryLimit", "leaseGeneration", "sourceGeneration", "capacity", "slot", "maximumWaitSeconds", "pollEverySeconds"];
45
+ export declare const textFields: readonly ["parentRunId", "chainId", "workflow", "workflowId", "submission", "input", "resolver", "gateId", "gateKind", "waitMode", "subject", "prompt", "expiresAt", "decision", "answer", "condition", "reason", "evidence", "retryAt", "operationId", "receipt", "capabilities", "capability", "method", "target", "payload", "inputDigest", "resource", "transport", "source", "worker", "outcome", "outcomeReason", "promotionId", "ticketStatus", "issueUpdate", "result", "actor", "waitName", "commandOutput"];
44
46
  export type NumberField = (typeof numberFields)[number];
45
47
  export type TextField = (typeof textFields)[number];
46
48
  export type AuthorityCommand = {
@@ -48,7 +50,7 @@ export type AuthorityCommand = {
48
50
  readonly commandId: string;
49
51
  readonly runId: string;
50
52
  } & Readonly<Partial<Record<NumberField, number>>> & Readonly<Partial<Record<TextField, string>>>;
51
- export type Move = Exclude<EventType, "run.created" | "step.dispatched" | "gate.wait-registered" | "run.observed" | "effect.requested" | "lease.granted" | "lease.expired" | "effect.reported" | "operation.reconciled" | "schedule.skipped">;
53
+ export type Move = Exclude<EventType, "run.created" | "step.dispatched" | "gate.wait-registered" | "run.observed" | "effect.requested" | "lease.granted" | "lease.expired" | "effect.reported" | "operation.reconciled" | "schedule.skipped" | "command-wait.opened" | "command-wait.checked" | "command-wait.expired">;
52
54
  export declare const terminal: readonly RunStatus[];
53
55
  export type Transition = {
54
56
  readonly kind: "moved";
@@ -18,6 +18,9 @@ export const eventTypes = [
18
18
  "effect.reported",
19
19
  "operation.reconciled",
20
20
  "schedule.skipped",
21
+ "command-wait.opened",
22
+ "command-wait.checked",
23
+ "command-wait.expired",
21
24
  ];
22
25
  export const numberFields = [
23
26
  "expectedRevision",
@@ -32,6 +35,8 @@ export const numberFields = [
32
35
  "sourceGeneration",
33
36
  "capacity",
34
37
  "slot",
38
+ "maximumWaitSeconds",
39
+ "pollEverySeconds",
35
40
  ];
36
41
  export const textFields = [
37
42
  "parentRunId",
@@ -72,6 +77,8 @@ export const textFields = [
72
77
  "issueUpdate",
73
78
  "result",
74
79
  "actor",
80
+ "waitName",
81
+ "commandOutput",
75
82
  ];
76
83
  export const terminal = [
77
84
  "completed",
@@ -0,0 +1,9 @@
1
+ import type { Logger } from "solid-objects";
2
+ export interface AuthorityHealth {
3
+ readonly refresh: () => Promise<void>;
4
+ readonly condition: () => string | null;
5
+ }
6
+ export declare function authorityHealth(source: {
7
+ readonly condition: () => Promise<string | undefined>;
8
+ readonly logger: Logger;
9
+ }): AuthorityHealth;
@@ -0,0 +1,24 @@
1
+ export function authorityHealth(source) {
2
+ const state = { condition: null, checks: 0, checked: 0 };
3
+ return {
4
+ refresh: async () => {
5
+ state.checks += 1;
6
+ const check = state.checks;
7
+ const detected = (await source.condition()) ?? null;
8
+ if (check < state.checked)
9
+ return;
10
+ state.checked = check;
11
+ changed(state, { detected, logger: source.logger });
12
+ },
13
+ condition: () => state.condition,
14
+ };
15
+ }
16
+ function changed(state, change) {
17
+ const { detected, logger } = change;
18
+ const previous = state.condition;
19
+ state.condition = detected;
20
+ if (previous === null && detected !== null)
21
+ logger.warn({ event: "authority-unhealthy", condition: detected });
22
+ if (previous !== null && detected === null)
23
+ logger.info({ event: "authority-recovered", condition: previous });
24
+ }
@@ -33,6 +33,7 @@ export interface CompletionCursor {
33
33
  readonly terminal?: boolean;
34
34
  }
35
35
  export interface RunRecord extends RunState {
36
+ readonly admissionCommandId: string | null;
36
37
  readonly sequence: number;
37
38
  }
38
39
  export interface AuthorityQueries {
@@ -43,7 +44,7 @@ export interface AuthorityQueries {
43
44
  readonly eventsAfter: (cursor: EventCursor) => Promise<EventPage>;
44
45
  readonly latestCompletion: (cursor: CompletionCursor) => Promise<PublishedEvent | undefined>;
45
46
  readonly sequences: () => Promise<Sequences>;
46
- readonly workflowIds: () => Promise<Readonly<Record<string, string>>>;
47
+ readonly workflowIds: (runIds?: readonly string[]) => Promise<Readonly<Record<string, string>>>;
47
48
  readonly runOrigins: () => Promise<RunOrigins>;
48
49
  readonly runLinks: () => Promise<Readonly<Record<string, RunLinks>>>;
49
50
  }
@@ -6,11 +6,15 @@ import { storedEvents, storedRun } from "../authority-restore.js";
6
6
  import { documentDigest } from "../decision-restore.js";
7
7
  import { runLinks, } from "../../authority/handoff-chain.js";
8
8
  async function run(connection, runId) {
9
- const row = await connection.get("SELECT run_id, status, revision, workflow, paused_from, gates, sequence FROM runs WHERE run_id = ?", [runId]);
9
+ const row = await connection.get("SELECT r.run_id, r.status, r.revision, r.workflow, r.paused_from, r.gates, r.sequence, c.command_id AS admission_command_id FROM runs r LEFT JOIN events c ON c.run_id = r.run_id AND c.type = 'run.created' WHERE r.run_id = ? ORDER BY c.sequence LIMIT 1", [runId]);
10
10
  if (row === undefined)
11
11
  return undefined;
12
12
  const record = runRow(row);
13
- return { ...storedRun(record), sequence: record.sequence };
13
+ return {
14
+ ...storedRun(record),
15
+ sequence: record.sequence,
16
+ admissionCommandId: optionalText(row, "admission_command_id"),
17
+ };
14
18
  }
15
19
  async function runOrigins(connection, cursor) {
16
20
  const rows = await connection.all("SELECT run_id, json_extract(payload, '$.parentRunId') AS parent_run_id, coalesce(json_extract(payload, '$.chainId'), run_id) AS chain_id FROM events WHERE type = 'run.created' AND sequence > ? AND sequence <= ? ORDER BY sequence", [cursor.after, cursor.through]);
@@ -84,8 +88,13 @@ async function sequences(connection) {
84
88
  times: Object.fromEntries(rows.map((row) => [text(row, "run_id"), text(row, "recorded_at")])),
85
89
  };
86
90
  }
87
- async function workflowIds(connection) {
88
- const rows = await connection.all("SELECT d.run_id, json_extract(s.body, '$.workflowId') AS workflow_id FROM run_details d JOIN documents s ON s.digest = d.submission WHERE json_valid(s.body) AND json_type(s.body, '$.workflowId') = 'text'");
91
+ async function workflowIds(connection, runIds) {
92
+ if (runIds?.length === 0)
93
+ return {};
94
+ const scoped = runIds === undefined
95
+ ? ""
96
+ : ` AND d.run_id IN (${runIds.map(() => "?").join(", ")})`;
97
+ const rows = await connection.all(`SELECT d.run_id, json_extract(s.body, '$.workflowId') AS workflow_id FROM run_details d JOIN documents s ON s.digest = d.submission WHERE json_valid(s.body) AND json_type(s.body, '$.workflowId') = 'text'${scoped}`, runIds);
89
98
  return Object.fromEntries(rows.map((row) => [text(row, "run_id"), text(row, "workflow_id")]));
90
99
  }
91
100
  function cachedOrigins(read) {
@@ -142,7 +151,7 @@ export function authorityQueries(read) {
142
151
  eventsAfter: (cursor) => read((connection) => eventsAfter(connection, cursor)),
143
152
  latestCompletion: (cursor) => read((connection) => latestCompletion(connection, cursor)),
144
153
  sequences: () => read(sequences),
145
- workflowIds: () => read(workflowIds),
154
+ workflowIds: (runIds) => read((connection) => workflowIds(connection, runIds)),
146
155
  runOrigins: origins,
147
156
  runLinks: currentLinks,
148
157
  };
@@ -24,7 +24,7 @@ export function oversized(request) {
24
24
  command["kind"] === "report-effect" &&
25
25
  command["worker"] === "command";
26
26
  const limit = report
27
- ? maximumRequestBytes + commandLimits.stdoutBytes * 6
27
+ ? maximumRequestBytes + commandLimits.stdoutBytes * 12
28
28
  : maximumRequestBytes;
29
29
  return Buffer.byteLength(JSON.stringify(request)) > limit;
30
30
  }
@@ -1,8 +1,9 @@
1
- import { type Database, type InstrumentationEvent, type JsonObject, type SolidObjectsRuntime } from "solid-objects";
1
+ import { type Database, type InstrumentationEvent, type JsonObject, type Logger, type SolidObjectsRuntime } from "solid-objects";
2
2
  import { type SequenceListener } from "./authority-changes.ts";
3
3
  import { type SchemaState } from "../../storage/domain-schema.ts";
4
4
  import { type AvailableManifest, type Delivery } from "./authority-delivery.ts";
5
5
  import { type AuthorityTiming, type EffectSettings } from "./authority-settings.ts";
6
+ import { type ProjectionMemory } from "./projection-memory.ts";
6
7
  export interface AuthorityOptions {
7
8
  readonly delivery?: Delivery;
8
9
  readonly timing?: AuthorityTiming;
@@ -44,11 +45,12 @@ export interface SessionLimits {
44
45
  export interface AuthorityRuntime {
45
46
  readonly runtime: SolidObjectsRuntime;
46
47
  readonly reader: Database;
48
+ readonly memory: ProjectionMemory;
47
49
  readonly invoker: (actorId: string, idempotencyKey?: string) => AuthorityInvoker;
48
50
  readonly stop: () => Promise<void>;
49
51
  readonly handlersSettled: () => Promise<boolean>;
50
52
  readonly setEpoch: (epoch: number) => void;
51
- readonly unhealthy: () => string | undefined;
53
+ readonly logger: Logger;
52
54
  readonly watchMilliseconds: number;
53
55
  readonly limits: SessionLimits;
54
56
  readonly releaseEarlierOwners: () => Promise<void>;
@@ -11,9 +11,10 @@ import { sequenceSubscriber, } from "./authority-changes.js";
11
11
  import { contentionMilliseconds, lockContention, lockExclusively, observeSettings, requiredSettingsViolation, takeOwnership, } from "./authority-connection.js";
12
12
  import { inspectSchema, } from "../../storage/domain-schema.js";
13
13
  import { deliveryHandler, } from "./authority-delivery.js";
14
- import { authorityTiming, effectConfiguration, } from "./authority-settings.js";
14
+ import { authorityLogger, authorityTiming, effectConfiguration, } from "./authority-settings.js";
15
15
  import { failureCounter, registeredRuntime, runtimeSettings, wallClock, } from "./runtime-parts.js";
16
16
  import { strandingWatchdog, } from "./authority-watchdog.js";
17
+ import { projectionMemory, } from "./projection-memory.js";
17
18
  export { authorityTiming } from "./authority-settings.js";
18
19
  export function refused(reason, error) {
19
20
  return {
@@ -78,13 +79,6 @@ export async function recoverDeliveries(invoker) {
78
79
  return staged;
79
80
  }
80
81
  }
81
- function unhealthy(watchdog) {
82
- const dead = watchdog.deadLettered();
83
- if (dead !== undefined)
84
- return `dead-lettered message ${dead}`;
85
- const stranded = watchdog.stranded();
86
- return stranded === undefined ? undefined : `stranded message ${stranded}`;
87
- }
88
82
  const deliveryCallbacks = ["deliveryCompleted", "deliveryFailed"];
89
83
  async function retryDeliveryCallbacks(retry) {
90
84
  const administration = { authorizationContext: retry.broker };
@@ -131,11 +125,18 @@ async function storedActorRefusal(check) {
131
125
  return sequence === latest ? undefined : actorSequenceMismatch;
132
126
  }
133
127
  async function condition(watch) {
134
- const { runtime, broker, watchdog } = watch;
135
- const dead = watchdog.deadLettered();
136
- if (dead === undefined)
137
- return unhealthy(watchdog);
138
- return `dead-lettered message ${dead}: ${await deadLetterCause({ runtime, broker, messageId: dead })}`;
128
+ const { runtime, broker, database, watchdog } = watch;
129
+ const report = await watchdog.report((messageIds) => messageRuns(database, messageIds));
130
+ if (report === undefined)
131
+ return undefined;
132
+ const { kind, messageId } = report;
133
+ if (kind === "stranded")
134
+ return `stranded message ${messageId}`;
135
+ return `dead-lettered message ${messageId}: ${await deadLetterCause({ runtime, broker, messageId })}`;
136
+ }
137
+ async function messageRuns(database, messageIds) {
138
+ const rows = await database.connection((connection) => connection.all(`SELECT messages.id AS message_id, runs.status AS status FROM solid_messages AS messages JOIN runs ON runs.run_id = coalesce(json_extract(messages.arguments, '$.command.runId'), json_extract(messages.arguments, '$.arguments.runId')) WHERE messages.id IN (${messageIds.map(() => "?").join(", ")})`, messageIds));
139
+ return new Map(rows.map((row) => [text(row, "message_id"), text(row, "status")]));
139
140
  }
140
141
  async function deadLetterCause(lookup) {
141
142
  const { runtime, broker, messageId } = lookup;
@@ -150,6 +151,14 @@ async function deadLetterCause(lookup) {
150
151
  return "unreadable cause";
151
152
  }
152
153
  }
154
+ function invokerOf(parts) {
155
+ const { runtime, actor, broker, timing } = parts;
156
+ return (actorId, idempotencyKey) => runtime.ref(actor, actorId).with({
157
+ authorizationContext: broker,
158
+ timeoutMilliseconds: timing.callTimeoutMilliseconds,
159
+ ...(idempotencyKey === undefined ? {} : { idempotencyKey }),
160
+ });
161
+ }
153
162
  export function authorityRuntime(database, options) {
154
163
  const timing = options.timing ?? authorityTiming;
155
164
  const reader = guardApplicationDatabase(database);
@@ -159,6 +168,8 @@ export function authorityRuntime(database, options) {
159
168
  boundMilliseconds: timing.callTimeoutMilliseconds,
160
169
  });
161
170
  const effects = effectConfiguration(options);
171
+ const logger = authorityLogger(options.log);
172
+ const memory = projectionMemory({ logger });
162
173
  const shared = { reader, effects, clock: options.clock ?? wallClock };
163
174
  const ClovingAuthority = authorityActor({
164
175
  ...shared,
@@ -168,6 +179,7 @@ export function authorityRuntime(database, options) {
168
179
  database,
169
180
  actor: ClovingAuthority,
170
181
  settings: runtimeSettings({ timing, options, broker, watchdog }),
182
+ record: memory.record,
171
183
  });
172
184
  const delivery = trackedDelivery({
173
185
  runtime,
@@ -183,22 +195,19 @@ export function authorityRuntime(database, options) {
183
195
  return {
184
196
  runtime,
185
197
  reader,
186
- invoker: (actorId, idempotencyKey) => runtime.ref(ClovingAuthority, actorId).with({
187
- authorizationContext: broker,
188
- timeoutMilliseconds: timing.callTimeoutMilliseconds,
189
- ...(idempotencyKey === undefined ? {} : { idempotencyKey }),
190
- }),
198
+ memory,
199
+ invoker: invokerOf({ runtime, actor: ClovingAuthority, broker, timing }),
191
200
  ...delivery,
192
201
  setEpoch: (value) => {
193
202
  epoch = value;
194
203
  },
195
- unhealthy: () => unhealthy(watchdog),
204
+ logger,
196
205
  watchMilliseconds: timing.leaseMilliseconds,
197
206
  limits: effects,
198
207
  releaseEarlierOwners: () => releaseEarlierOwners({ runtime, broker, timing }),
199
208
  retryDeliveryCallbacks: () => retryDeliveryCallbacks({ runtime, broker }),
200
209
  storedActorRefusal: (actorId) => storedActorRefusal({ database, actor: ClovingAuthority, actorId }),
201
- condition: () => condition({ runtime, broker, watchdog }),
210
+ condition: () => condition({ runtime, broker, database, watchdog }),
202
211
  subscribe: sequenceSubscriber({ realtime: runtime.realtime, broker }),
203
212
  };
204
213
  }
@@ -1,35 +1,22 @@
1
- import type { Database, JsonObject } from "solid-objects";
2
- import { type AuthorityEvent, type EffectIntent } from "../../authority/reducer.ts";
3
- import { type ProjectionSnapshot } from "../../storage/decision-snapshots.ts";
1
+ import type { Database, JsonObject, Logger } from "solid-objects";
2
+ import type { AuthorityEvent, EffectIntent } from "../../authority/reducer.ts";
4
3
  import type { AdmissionResult, ExecutionManifest } from "../../workflow-admission.ts";
5
4
  import { type StoredState } from "../authority-restore.ts";
6
5
  import { type SequenceChanges, type SequenceListener } from "./authority-changes.ts";
7
6
  import { type AuthorityQueries } from "./authority-queries.ts";
8
7
  import { type EffectQueries } from "./effect-queries.ts";
8
+ import type { OperationRecord, ProjectionMemory } from "./projection-memory.ts";
9
9
  import { type ConnectionSettings } from "./authority-connection.ts";
10
10
  import { type StoreReceipt } from "./authority-receipts.ts";
11
11
  export type { StoreReceipt } from "./authority-receipts.ts";
12
12
  export type { StoredState } from "../authority-restore.ts";
13
+ export { operationRecords, type OperationRecord } from "./projection-memory.ts";
13
14
  export interface CommandContext {
14
15
  readonly recordedAt: string;
15
16
  readonly manifest?: ExecutionManifest;
16
17
  readonly epoch?: number;
17
18
  readonly documents?: readonly string[];
18
19
  }
19
- export interface OperationRecord {
20
- readonly operationId: string;
21
- readonly kind: EffectIntent["kind"];
22
- readonly runId: string;
23
- readonly createdSequence: number;
24
- readonly releasedSequence: number | null;
25
- readonly deliveries: readonly {
26
- readonly effectId: string;
27
- readonly outcome: string | null;
28
- readonly receipt: string | null;
29
- readonly purpose: string;
30
- readonly epoch: number | null;
31
- }[];
32
- }
33
20
  export interface Authority {
34
21
  readonly execute: (command: unknown, context: CommandContext) => Promise<StoreReceipt>;
35
22
  readonly state: () => Promise<StoredState>;
@@ -50,6 +37,7 @@ export interface Authority {
50
37
  export interface SessionParts {
51
38
  readonly database: Database;
52
39
  readonly reader: Database;
40
+ readonly memory: ProjectionMemory;
53
41
  readonly execute: (request: JsonObject) => Promise<unknown>;
54
42
  readonly run: (signal: AbortSignal) => Promise<void>;
55
43
  readonly stop: () => Promise<void>;
@@ -58,10 +46,9 @@ export interface SessionParts {
58
46
  readonly epoch: number;
59
47
  readonly stopLimit: number;
60
48
  readonly recoveryLimit: number;
61
- readonly unhealthy: () => string | undefined;
62
49
  readonly condition: () => Promise<string | undefined>;
50
+ readonly logger: Logger;
63
51
  readonly watchMilliseconds: number;
64
52
  readonly subscribe: (listener: SequenceListener) => () => void;
65
53
  }
66
54
  export declare function authoritySession(parts: SessionParts): Authority;
67
- export declare function operationRecords(snapshot: Pick<ProjectionSnapshot, "outbox" | "deliveries">): readonly OperationRecord[];