@shivaedev/work-fleet 0.2.0 → 0.3.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 (502) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +60 -18
  3. package/dist/DispatchRequest.d.ts +13 -0
  4. package/dist/DispatchRequest.d.ts.map +1 -0
  5. package/dist/DispatchRequest.js +12 -0
  6. package/dist/DispatchRequest.js.map +1 -0
  7. package/dist/admit.d.ts +11 -0
  8. package/dist/admit.d.ts.map +1 -1
  9. package/dist/attention.d.ts +1 -0
  10. package/dist/attention.d.ts.map +1 -1
  11. package/dist/attention.js +4 -0
  12. package/dist/attention.js.map +1 -1
  13. package/dist/board/fleetField.d.ts +1 -0
  14. package/dist/board/fleetField.d.ts.map +1 -1
  15. package/dist/board/fleetField.js +4 -0
  16. package/dist/board/fleetField.js.map +1 -1
  17. package/dist/board/markdown.d.ts.map +1 -1
  18. package/dist/board/markdown.js +7 -2
  19. package/dist/board/markdown.js.map +1 -1
  20. package/dist/board/publish.d.ts +2 -0
  21. package/dist/board/publish.d.ts.map +1 -1
  22. package/dist/board/publishReport.d.ts +1 -0
  23. package/dist/board/publishReport.d.ts.map +1 -1
  24. package/dist/board/readPass.d.ts +1 -0
  25. package/dist/board/readPass.d.ts.map +1 -1
  26. package/dist/cli.js +13 -6
  27. package/dist/cli.js.map +1 -1
  28. package/dist/engine/abandonStalled.d.ts +1171 -1004
  29. package/dist/engine/abandonStalled.d.ts.map +1 -1
  30. package/dist/engine/admissionOrder.d.ts +1091 -0
  31. package/dist/engine/admissionOrder.d.ts.map +1 -0
  32. package/dist/engine/admissionOrder.js +15 -0
  33. package/dist/engine/admissionOrder.js.map +1 -0
  34. package/dist/engine/applyResolution.d.ts +20 -0
  35. package/dist/engine/applyResolution.d.ts.map +1 -1
  36. package/dist/engine/approveBrief.d.ts +31 -0
  37. package/dist/engine/approveBrief.d.ts.map +1 -1
  38. package/dist/engine/authorizeResolution.d.ts +1160 -1003
  39. package/dist/engine/authorizeResolution.d.ts.map +1 -1
  40. package/dist/engine/boardBrief.d.ts +32 -0
  41. package/dist/engine/boardBrief.d.ts.map +1 -1
  42. package/dist/engine/capacityRetry.d.ts +3488 -3007
  43. package/dist/engine/capacityRetry.d.ts.map +1 -1
  44. package/dist/engine/closeDecisions.d.ts +20 -0
  45. package/dist/engine/closeDecisions.d.ts.map +1 -1
  46. package/dist/engine/completeBoardWork.d.ts +20 -0
  47. package/dist/engine/completeBoardWork.d.ts.map +1 -1
  48. package/dist/engine/completeReport.d.ts +21 -0
  49. package/dist/engine/completeReport.d.ts.map +1 -1
  50. package/dist/engine/continueCommand.d.ts +10 -0
  51. package/dist/engine/continueCommand.d.ts.map +1 -1
  52. package/dist/engine/continueWorker.d.ts +20 -0
  53. package/dist/engine/continueWorker.d.ts.map +1 -1
  54. package/dist/engine/deliverPendingAnswers.d.ts +1085 -898
  55. package/dist/engine/deliverPendingAnswers.d.ts.map +1 -1
  56. package/dist/engine/dispatchCommand.d.ts +14 -1
  57. package/dist/engine/dispatchCommand.d.ts.map +1 -1
  58. package/dist/engine/dispatchCommand.js +25 -5
  59. package/dist/engine/dispatchCommand.js.map +1 -1
  60. package/dist/engine/ensureDecisionOwner.d.ts +20 -0
  61. package/dist/engine/ensureDecisionOwner.d.ts.map +1 -1
  62. package/dist/engine/ensurePublication.d.ts +20 -0
  63. package/dist/engine/ensurePublication.d.ts.map +1 -1
  64. package/dist/engine/failureContext.d.ts +1 -0
  65. package/dist/engine/failureContext.d.ts.map +1 -1
  66. package/dist/engine/failureContext.js.map +1 -1
  67. package/dist/engine/failureMessage.js +11 -1
  68. package/dist/engine/failureMessage.js.map +1 -1
  69. package/dist/engine/health.d.ts +10 -0
  70. package/dist/engine/health.d.ts.map +1 -1
  71. package/dist/engine/inspectRenewal.d.ts +21 -0
  72. package/dist/engine/inspectRenewal.d.ts.map +1 -1
  73. package/dist/engine/launchInput.d.ts +10 -0
  74. package/dist/engine/launchInput.d.ts.map +1 -1
  75. package/dist/engine/launchReceipt.d.ts +10 -0
  76. package/dist/engine/launchReceipt.d.ts.map +1 -1
  77. package/dist/engine/localOnlyCriteria.d.ts +1 -0
  78. package/dist/engine/localOnlyCriteria.d.ts.map +1 -1
  79. package/dist/engine/localOnlyCriteria.js +5 -1
  80. package/dist/engine/localOnlyCriteria.js.map +1 -1
  81. package/dist/engine/makeAdopt.d.ts +21 -0
  82. package/dist/engine/makeAdopt.d.ts.map +1 -1
  83. package/dist/engine/makeAdvance.d.ts +10 -0
  84. package/dist/engine/makeAdvance.d.ts.map +1 -1
  85. package/dist/engine/makeDeliver.d.ts +20 -0
  86. package/dist/engine/makeDeliver.d.ts.map +1 -1
  87. package/dist/engine/makeHuman.d.ts +20 -0
  88. package/dist/engine/makeHuman.d.ts.map +1 -1
  89. package/dist/engine/makeLaunch.d.ts +20 -0
  90. package/dist/engine/makeLaunch.d.ts.map +1 -1
  91. package/dist/engine/makeLaunch.js +4 -13
  92. package/dist/engine/makeLaunch.js.map +1 -1
  93. package/dist/engine/makeObserve.d.ts +20 -0
  94. package/dist/engine/makeObserve.d.ts.map +1 -1
  95. package/dist/engine/makeReview.d.ts +21 -0
  96. package/dist/engine/makeReview.d.ts.map +1 -1
  97. package/dist/engine/makeState.d.ts +1164 -1010
  98. package/dist/engine/makeState.d.ts.map +1 -1
  99. package/dist/engine/makeState.js +19 -11
  100. package/dist/engine/makeState.js.map +1 -1
  101. package/dist/engine/makeValidate.d.ts +21 -0
  102. package/dist/engine/makeValidate.d.ts.map +1 -1
  103. package/dist/engine/mergeReadiness.d.ts +1425 -1764
  104. package/dist/engine/mergeReadiness.d.ts.map +1 -1
  105. package/dist/engine/mergeReadiness.js +3 -4
  106. package/dist/engine/mergeReadiness.js.map +1 -1
  107. package/dist/engine/observeDeliveryFailure.d.ts +1170 -1003
  108. package/dist/engine/observeDeliveryFailure.d.ts.map +1 -1
  109. package/dist/engine/observeRenewal.d.ts +33 -0
  110. package/dist/engine/observeRenewal.d.ts.map +1 -1
  111. package/dist/engine/obtainReview.d.ts +11 -0
  112. package/dist/engine/obtainReview.d.ts.map +1 -1
  113. package/dist/engine/obtainReview.js +2 -1
  114. package/dist/engine/obtainReview.js.map +1 -1
  115. package/dist/engine/operationRecord.d.ts +1898 -1779
  116. package/dist/engine/operationRecord.d.ts.map +1 -1
  117. package/dist/engine/persistTerminalReceipts.d.ts +20 -0
  118. package/dist/engine/persistTerminalReceipts.d.ts.map +1 -1
  119. package/dist/engine/prepareCommand.d.ts +10 -0
  120. package/dist/engine/prepareCommand.d.ts.map +1 -1
  121. package/dist/engine/prepareCommand.js +1 -1
  122. package/dist/engine/prepareCommand.js.map +1 -1
  123. package/dist/engine/queueAnswerCommand.d.ts +10 -0
  124. package/dist/engine/queueAnswerCommand.d.ts.map +1 -1
  125. package/dist/engine/readOrContinueReview.d.ts +11 -0
  126. package/dist/engine/readOrContinueReview.d.ts.map +1 -1
  127. package/dist/engine/readOrContinueReview.js +2 -1
  128. package/dist/engine/readOrContinueReview.js.map +1 -1
  129. package/dist/engine/readResolution.d.ts +1 -0
  130. package/dist/engine/readResolution.d.ts.map +1 -1
  131. package/dist/engine/readRetry.d.ts +2344 -2010
  132. package/dist/engine/readRetry.d.ts.map +1 -1
  133. package/dist/engine/readRetry.js +20 -1
  134. package/dist/engine/readRetry.js.map +1 -1
  135. package/dist/engine/reassignCommand.d.ts +10 -0
  136. package/dist/engine/reassignCommand.d.ts.map +1 -1
  137. package/dist/engine/reconcileAttempt.d.ts +12 -1
  138. package/dist/engine/reconcileAttempt.d.ts.map +1 -1
  139. package/dist/engine/reconcileAttempt.js +2 -1
  140. package/dist/engine/reconcileAttempt.js.map +1 -1
  141. package/dist/engine/reconcileCommand.d.ts +10 -0
  142. package/dist/engine/reconcileCommand.d.ts.map +1 -1
  143. package/dist/engine/recordResponseCommand.d.ts +551 -0
  144. package/dist/engine/recordResponseCommand.d.ts.map +1 -0
  145. package/dist/engine/recordResponseCommand.js +30 -0
  146. package/dist/engine/recordResponseCommand.js.map +1 -0
  147. package/dist/engine/recoverStall.d.ts +1172 -1004
  148. package/dist/engine/recoverStall.d.ts.map +1 -1
  149. package/dist/engine/recoverStall.js +1 -1
  150. package/dist/engine/recoverStall.js.map +1 -1
  151. package/dist/engine/recoverUnobservable.d.ts +1172 -1004
  152. package/dist/engine/recoverUnobservable.d.ts.map +1 -1
  153. package/dist/engine/refreshBrief.d.ts +2344 -2009
  154. package/dist/engine/refreshBrief.d.ts.map +1 -1
  155. package/dist/engine/refreshReviewResult.d.ts +21 -0
  156. package/dist/engine/refreshReviewResult.d.ts.map +1 -1
  157. package/dist/engine/releaseClosedPreparation.d.ts +1171 -1003
  158. package/dist/engine/releaseClosedPreparation.d.ts.map +1 -1
  159. package/dist/engine/releaseExecution.d.ts +1170 -1003
  160. package/dist/engine/releaseExecution.d.ts.map +1 -1
  161. package/dist/engine/releaseFinishedWork.d.ts +10 -0
  162. package/dist/engine/releaseFinishedWork.d.ts.map +1 -1
  163. package/dist/engine/repository.d.ts +1115 -1003
  164. package/dist/engine/repository.d.ts.map +1 -1
  165. package/dist/engine/repository.js +12 -12
  166. package/dist/engine/repository.js.map +1 -1
  167. package/dist/engine/requestConflictRepair.d.ts +1170 -1003
  168. package/dist/engine/requestConflictRepair.d.ts.map +1 -1
  169. package/dist/engine/requestRework.d.ts +20 -0
  170. package/dist/engine/requestRework.d.ts.map +1 -1
  171. package/dist/engine/resolveCommand.d.ts +10 -0
  172. package/dist/engine/resolveCommand.d.ts.map +1 -1
  173. package/dist/engine/resolveExecution.d.ts +1170 -1003
  174. package/dist/engine/resolveExecution.d.ts.map +1 -1
  175. package/dist/engine/resumeAttempt.d.ts +1171 -1003
  176. package/dist/engine/resumeAttempt.d.ts.map +1 -1
  177. package/dist/engine/retireUnacknowledged.d.ts +20 -0
  178. package/dist/engine/retireUnacknowledged.d.ts.map +1 -1
  179. package/dist/engine/retryTerminal.d.ts +1160 -1003
  180. package/dist/engine/retryTerminal.d.ts.map +1 -1
  181. package/dist/engine/saveLaunch.d.ts +10598 -0
  182. package/dist/engine/saveLaunch.d.ts.map +1 -0
  183. package/dist/engine/saveLaunch.js +30 -0
  184. package/dist/engine/saveLaunch.js.map +1 -0
  185. package/dist/engine/scheduler.d.ts +21 -1
  186. package/dist/engine/scheduler.d.ts.map +1 -1
  187. package/dist/engine/scheduler.js +3 -5
  188. package/dist/engine/scheduler.js.map +1 -1
  189. package/dist/engine/sessionCleanup.d.ts +20 -0
  190. package/dist/engine/sessionCleanup.d.ts.map +1 -1
  191. package/dist/engine/settleMergedDelivery.d.ts +1170 -1003
  192. package/dist/engine/settleMergedDelivery.d.ts.map +1 -1
  193. package/dist/engine/steerBrief.d.ts +1075 -898
  194. package/dist/engine/steerBrief.d.ts.map +1 -1
  195. package/dist/engine/submissionFailure.d.ts +1150 -1003
  196. package/dist/engine/submissionFailure.d.ts.map +1 -1
  197. package/dist/engine/submitLaunch.d.ts +1160 -1003
  198. package/dist/engine/submitLaunch.d.ts.map +1 -1
  199. package/dist/engine/views.d.ts.map +1 -1
  200. package/dist/engine/views.js +4 -0
  201. package/dist/engine/views.js.map +1 -1
  202. package/dist/engine/workerReport.d.ts +30 -0
  203. package/dist/engine/workerReport.d.ts.map +1 -1
  204. package/dist/fleet.d.ts +2716 -983
  205. package/dist/fleet.d.ts.map +1 -1
  206. package/dist/fleet.js +4 -0
  207. package/dist/fleet.js.map +1 -1
  208. package/dist/host/actionCommands.d.ts.map +1 -1
  209. package/dist/host/actionCommands.js +7 -6
  210. package/dist/host/actionCommands.js.map +1 -1
  211. package/dist/host/admission.d.ts +24 -1
  212. package/dist/host/admission.d.ts.map +1 -1
  213. package/dist/host/admission.js +2 -2
  214. package/dist/host/admission.js.map +1 -1
  215. package/dist/host/answerWork.d.ts +12 -2
  216. package/dist/host/answerWork.d.ts.map +1 -1
  217. package/dist/host/answerWork.js +19 -23
  218. package/dist/host/answerWork.js.map +1 -1
  219. package/dist/host/commands.d.ts +28 -4
  220. package/dist/host/commands.d.ts.map +1 -1
  221. package/dist/host/commands.js +19 -5
  222. package/dist/host/commands.js.map +1 -1
  223. package/dist/host/config.d.ts +77 -1
  224. package/dist/host/config.d.ts.map +1 -1
  225. package/dist/host/config.js +37 -9
  226. package/dist/host/config.js.map +1 -1
  227. package/dist/host/configSettings.d.ts +486 -0
  228. package/dist/host/configSettings.d.ts.map +1 -0
  229. package/dist/host/configSettings.js +113 -0
  230. package/dist/host/configSettings.js.map +1 -0
  231. package/dist/host/daemon.d.ts +302 -607
  232. package/dist/host/daemon.d.ts.map +1 -1
  233. package/dist/host/daemon.js +2 -1
  234. package/dist/host/daemon.js.map +1 -1
  235. package/dist/host/daemonClient.d.ts +300 -605
  236. package/dist/host/daemonClient.d.ts.map +1 -1
  237. package/dist/host/daemonClient.js +28 -7
  238. package/dist/host/daemonClient.js.map +1 -1
  239. package/dist/host/daemonContract.d.ts +882 -1987
  240. package/dist/host/daemonContract.d.ts.map +1 -1
  241. package/dist/host/daemonContract.js +12 -4
  242. package/dist/host/daemonContract.js.map +1 -1
  243. package/dist/host/daemonDiagnostics.d.ts.map +1 -1
  244. package/dist/host/daemonDiagnostics.js +9 -3
  245. package/dist/host/daemonDiagnostics.js.map +1 -1
  246. package/dist/host/daemonHandlers.d.ts +2 -1
  247. package/dist/host/daemonHandlers.d.ts.map +1 -1
  248. package/dist/host/daemonHandlers.js +20 -7
  249. package/dist/host/daemonHandlers.js.map +1 -1
  250. package/dist/host/daemonSnapshots.d.ts.map +1 -1
  251. package/dist/host/daemonSnapshots.js +21 -1
  252. package/dist/host/daemonSnapshots.js.map +1 -1
  253. package/dist/host/dispatchRequests.d.ts +30 -0
  254. package/dist/host/dispatchRequests.d.ts.map +1 -0
  255. package/dist/host/dispatchRequests.js +40 -0
  256. package/dist/host/dispatchRequests.js.map +1 -0
  257. package/dist/host/follow.js +1 -1
  258. package/dist/host/follow.js.map +1 -1
  259. package/dist/host/followState.d.ts.map +1 -1
  260. package/dist/host/followState.js +5 -4
  261. package/dist/host/followState.js.map +1 -1
  262. package/dist/host/github.d.ts +5 -6
  263. package/dist/host/github.d.ts.map +1 -1
  264. package/dist/host/github.js +3 -4
  265. package/dist/host/github.js.map +1 -1
  266. package/dist/host/githubApi.d.ts +15 -0
  267. package/dist/host/githubApi.d.ts.map +1 -0
  268. package/dist/host/githubApi.js +117 -0
  269. package/dist/host/githubApi.js.map +1 -0
  270. package/dist/host/githubChecks.d.ts +13 -3
  271. package/dist/host/githubChecks.d.ts.map +1 -1
  272. package/dist/host/githubChecks.js +5 -5
  273. package/dist/host/githubChecks.js.map +1 -1
  274. package/dist/host/githubDelivery.d.ts +13 -1
  275. package/dist/host/githubDelivery.d.ts.map +1 -1
  276. package/dist/host/githubDelivery.js +39 -6
  277. package/dist/host/githubDelivery.js.map +1 -1
  278. package/dist/host/githubRateLimit.d.ts +23 -0
  279. package/dist/host/githubRateLimit.d.ts.map +1 -0
  280. package/dist/host/githubRateLimit.js +70 -0
  281. package/dist/host/githubRateLimit.js.map +1 -0
  282. package/dist/host/githubRequiredChecks.d.ts +1 -2
  283. package/dist/host/githubRequiredChecks.d.ts.map +1 -1
  284. package/dist/host/githubRequiredChecks.js +2 -2
  285. package/dist/host/githubRequiredChecks.js.map +1 -1
  286. package/dist/host/githubResponse.d.ts +10 -0
  287. package/dist/host/githubResponse.d.ts.map +1 -0
  288. package/dist/host/githubResponse.js +29 -0
  289. package/dist/host/githubResponse.js.map +1 -0
  290. package/dist/host/githubResult.d.ts +3 -2
  291. package/dist/host/githubResult.d.ts.map +1 -1
  292. package/dist/host/githubResult.js +9 -12
  293. package/dist/host/githubResult.js.map +1 -1
  294. package/dist/host/githubTransport.d.ts +13 -0
  295. package/dist/host/githubTransport.d.ts.map +1 -0
  296. package/dist/host/{githubRead.js → githubTransport.js} +9 -10
  297. package/dist/host/githubTransport.js.map +1 -0
  298. package/dist/host/integrations.d.ts +6 -0
  299. package/dist/host/integrations.d.ts.map +1 -0
  300. package/dist/host/integrations.js +34 -0
  301. package/dist/host/integrations.js.map +1 -0
  302. package/dist/host/liveConfig.d.ts +21 -0
  303. package/dist/host/liveConfig.d.ts.map +1 -0
  304. package/dist/host/liveConfig.js +74 -0
  305. package/dist/host/liveConfig.js.map +1 -0
  306. package/dist/host/providers.d.ts.map +1 -1
  307. package/dist/host/providers.js +2 -2
  308. package/dist/host/providers.js.map +1 -1
  309. package/dist/host/readWaitStates.d.ts.map +1 -1
  310. package/dist/host/readWaitStates.js +8 -18
  311. package/dist/host/readWaitStates.js.map +1 -1
  312. package/dist/host/reassignWork.d.ts +10 -0
  313. package/dist/host/reassignWork.d.ts.map +1 -1
  314. package/dist/host/recordDecisionResponse.d.ts +1 -0
  315. package/dist/host/recordDecisionResponse.d.ts.map +1 -1
  316. package/dist/host/releaseWork.d.ts +24 -3
  317. package/dist/host/releaseWork.d.ts.map +1 -1
  318. package/dist/host/releaseWork.js +11 -7
  319. package/dist/host/releaseWork.js.map +1 -1
  320. package/dist/host/renderStatus.d.ts +2 -2
  321. package/dist/host/renderStatus.d.ts.map +1 -1
  322. package/dist/host/renderStatus.js +8 -2
  323. package/dist/host/renderStatus.js.map +1 -1
  324. package/dist/host/reportBoard.d.ts +1 -1
  325. package/dist/host/reportBoard.d.ts.map +1 -1
  326. package/dist/host/reportBoard.js +6 -3
  327. package/dist/host/reportBoard.js.map +1 -1
  328. package/dist/host/reportPublication.d.ts +2 -1
  329. package/dist/host/reportPublication.d.ts.map +1 -1
  330. package/dist/host/reportPublication.js +5 -2
  331. package/dist/host/reportPublication.js.map +1 -1
  332. package/dist/host/runtime.d.ts +8 -6
  333. package/dist/host/runtime.d.ts.map +1 -1
  334. package/dist/host/runtime.js +37 -46
  335. package/dist/host/runtime.js.map +1 -1
  336. package/dist/host/snapshotStream.d.ts.map +1 -1
  337. package/dist/host/snapshotStream.js +4 -1
  338. package/dist/host/snapshotStream.js.map +1 -1
  339. package/dist/host/status.d.ts +22 -2
  340. package/dist/host/status.d.ts.map +1 -1
  341. package/dist/host/status.js +19 -5
  342. package/dist/host/status.js.map +1 -1
  343. package/dist/host/statusLayer.d.ts +3 -3
  344. package/dist/host/statusLayer.d.ts.map +1 -1
  345. package/dist/host/statusLayer.js +13 -3
  346. package/dist/host/statusLayer.js.map +1 -1
  347. package/dist/host/waitOutcome.d.ts.map +1 -1
  348. package/dist/host/waitOutcome.js +5 -2
  349. package/dist/host/waitOutcome.js.map +1 -1
  350. package/dist/model.d.ts +39 -0
  351. package/dist/model.d.ts.map +1 -1
  352. package/dist/model.js +5 -0
  353. package/dist/model.js.map +1 -1
  354. package/dist/operations.d.ts +270 -0
  355. package/dist/operations.d.ts.map +1 -1
  356. package/dist/packageInfo.d.ts +1 -1
  357. package/dist/packageInfo.js +1 -1
  358. package/dist/policy.d.ts +7 -0
  359. package/dist/policy.d.ts.map +1 -1
  360. package/dist/policy.js +2 -0
  361. package/dist/policy.js.map +1 -1
  362. package/dist/providers/codexCloud.d.ts +2 -0
  363. package/dist/providers/codexCloud.d.ts.map +1 -1
  364. package/dist/providers/codexCloud.js +2 -1
  365. package/dist/providers/codexCloud.js.map +1 -1
  366. package/dist/qualifyDependencies.d.ts +10 -0
  367. package/dist/qualifyDependencies.d.ts.map +1 -1
  368. package/dist/scheduling/admission.d.ts +1635 -0
  369. package/dist/scheduling/admission.d.ts.map +1 -0
  370. package/dist/scheduling/admission.js +11 -0
  371. package/dist/scheduling/admission.js.map +1 -0
  372. package/dist/scheduling/areas.d.ts +30 -0
  373. package/dist/scheduling/areas.d.ts.map +1 -1
  374. package/dist/scheduling/backPressure.d.ts +1637 -0
  375. package/dist/scheduling/backPressure.d.ts.map +1 -0
  376. package/dist/scheduling/backPressure.js +44 -0
  377. package/dist/scheduling/backPressure.js.map +1 -0
  378. package/dist/storage/FleetStoreOptions.d.ts +2 -2
  379. package/dist/storage/FleetStoreOptions.d.ts.map +1 -1
  380. package/dist/storage/addShapeColumns.d.ts +5 -0
  381. package/dist/storage/addShapeColumns.d.ts.map +1 -0
  382. package/dist/storage/addShapeColumns.js +24 -0
  383. package/dist/storage/addShapeColumns.js.map +1 -0
  384. package/dist/storage/dispatchStore.d.ts +47 -0
  385. package/dist/storage/dispatchStore.d.ts.map +1 -0
  386. package/dist/storage/dispatchStore.js +89 -0
  387. package/dist/storage/dispatchStore.js.map +1 -0
  388. package/dist/storage/errors.d.ts +2 -1
  389. package/dist/storage/errors.d.ts.map +1 -1
  390. package/dist/storage/errors.js +2 -1
  391. package/dist/storage/errors.js.map +1 -1
  392. package/dist/storage/fleetMigrations.d.ts +1 -1
  393. package/dist/storage/fleetMigrations.d.ts.map +1 -1
  394. package/dist/storage/fleetMigrations.js +24 -17
  395. package/dist/storage/fleetMigrations.js.map +1 -1
  396. package/dist/storage/listedRecords.d.ts +9 -0
  397. package/dist/storage/listedRecords.d.ts.map +1 -0
  398. package/dist/storage/listedRecords.js +40 -0
  399. package/dist/storage/listedRecords.js.map +1 -0
  400. package/dist/storage/makePostgresFleetStore.d.ts +2 -6
  401. package/dist/storage/makePostgresFleetStore.d.ts.map +1 -1
  402. package/dist/storage/makePostgresFleetStore.js +4 -10
  403. package/dist/storage/makePostgresFleetStore.js.map +1 -1
  404. package/dist/storage/model.d.ts +9 -0
  405. package/dist/storage/model.d.ts.map +1 -1
  406. package/dist/storage/model.js.map +1 -1
  407. package/dist/storage/shapeV14.d.ts +808 -0
  408. package/dist/storage/shapeV14.d.ts.map +1 -0
  409. package/dist/storage/shapeV14.js +18 -0
  410. package/dist/storage/shapeV14.js.map +1 -0
  411. package/package.json +6 -6
  412. package/src/DispatchRequest.ts +13 -0
  413. package/src/attention.ts +5 -0
  414. package/src/board/fleetField.ts +5 -0
  415. package/src/board/markdown.ts +7 -2
  416. package/src/cli.ts +24 -10
  417. package/src/engine/admissionOrder.ts +25 -0
  418. package/src/engine/dispatchCommand.ts +29 -5
  419. package/src/engine/failureContext.ts +1 -0
  420. package/src/engine/failureMessage.ts +12 -1
  421. package/src/engine/localOnlyCriteria.ts +6 -1
  422. package/src/engine/makeLaunch.ts +4 -17
  423. package/src/engine/makeState.ts +30 -26
  424. package/src/engine/mergeReadiness.ts +6 -5
  425. package/src/engine/obtainReview.ts +2 -1
  426. package/src/engine/prepareCommand.ts +1 -1
  427. package/src/engine/readOrContinueReview.ts +2 -1
  428. package/src/engine/readRetry.ts +23 -1
  429. package/src/engine/reconcileAttempt.ts +2 -1
  430. package/src/engine/recordResponseCommand.ts +38 -0
  431. package/src/engine/recoverStall.ts +1 -1
  432. package/src/engine/repository.ts +17 -16
  433. package/src/engine/saveLaunch.ts +45 -0
  434. package/src/engine/scheduler.ts +4 -6
  435. package/src/engine/views.ts +5 -0
  436. package/src/fleet.ts +4 -0
  437. package/src/host/actionCommands.ts +22 -7
  438. package/src/host/admission.ts +3 -3
  439. package/src/host/answerWork.ts +28 -27
  440. package/src/host/commands.ts +29 -8
  441. package/src/host/config.ts +46 -9
  442. package/src/host/configSettings.ts +124 -0
  443. package/src/host/daemon.ts +2 -1
  444. package/src/host/daemonClient.ts +42 -7
  445. package/src/host/daemonContract.ts +12 -4
  446. package/src/host/daemonDiagnostics.ts +11 -3
  447. package/src/host/daemonHandlers.ts +24 -7
  448. package/src/host/daemonSnapshots.ts +24 -1
  449. package/src/host/dispatchRequests.ts +53 -0
  450. package/src/host/follow.ts +1 -1
  451. package/src/host/followState.ts +6 -6
  452. package/src/host/github.ts +8 -6
  453. package/src/host/githubApi.ts +142 -0
  454. package/src/host/githubChecks.ts +6 -5
  455. package/src/host/githubDelivery.ts +47 -10
  456. package/src/host/githubRateLimit.ts +91 -0
  457. package/src/host/githubRequiredChecks.ts +2 -2
  458. package/src/host/githubResponse.ts +37 -0
  459. package/src/host/githubResult.ts +15 -17
  460. package/src/host/githubTransport.ts +31 -0
  461. package/src/host/integrations.ts +40 -0
  462. package/src/host/liveConfig.ts +134 -0
  463. package/src/host/providers.ts +4 -2
  464. package/src/host/readWaitStates.ts +8 -20
  465. package/src/host/releaseWork.ts +12 -9
  466. package/src/host/renderStatus.ts +10 -3
  467. package/src/host/reportBoard.ts +6 -3
  468. package/src/host/reportPublication.ts +6 -4
  469. package/src/host/runtime.ts +48 -56
  470. package/src/host/snapshotStream.ts +6 -1
  471. package/src/host/status.ts +24 -7
  472. package/src/host/statusLayer.ts +21 -5
  473. package/src/host/waitOutcome.ts +5 -2
  474. package/src/model.ts +6 -0
  475. package/src/packageInfo.ts +1 -1
  476. package/src/policy.ts +7 -0
  477. package/src/providers/codexCloud.ts +2 -1
  478. package/src/scheduling/admission.ts +19 -0
  479. package/src/scheduling/backPressure.ts +55 -0
  480. package/src/storage/FleetStoreOptions.ts +7 -2
  481. package/src/storage/addShapeColumns.ts +24 -0
  482. package/src/storage/dispatchStore.ts +104 -0
  483. package/src/storage/errors.ts +2 -1
  484. package/src/storage/fleetMigrations.ts +24 -17
  485. package/src/storage/listedRecords.ts +53 -0
  486. package/src/storage/makePostgresFleetStore.ts +4 -10
  487. package/src/storage/model.ts +7 -0
  488. package/src/storage/shapeV14.ts +19 -0
  489. package/dist/host/githubRead.d.ts +0 -5
  490. package/dist/host/githubRead.d.ts.map +0 -1
  491. package/dist/host/githubRead.js.map +0 -1
  492. package/dist/host/recordPayloads.d.ts +0 -4
  493. package/dist/host/recordPayloads.d.ts.map +0 -1
  494. package/dist/host/recordPayloads.js +0 -21
  495. package/dist/host/recordPayloads.js.map +0 -1
  496. package/dist/storage/migrateFleet.d.ts +0 -3
  497. package/dist/storage/migrateFleet.d.ts.map +0 -1
  498. package/dist/storage/migrateFleet.js +0 -11
  499. package/dist/storage/migrateFleet.js.map +0 -1
  500. package/src/host/githubRead.ts +0 -20
  501. package/src/host/recordPayloads.ts +0 -24
  502. package/src/storage/migrateFleet.ts +0 -11
@@ -21,7 +21,7 @@ export const recoverStall = Effect.fn("Fleet.recoverStall")(function* (
21
21
  if (attempt.status === "interrupted" && recovery?.interruptRequestedAt !== undefined) {
22
22
  return yield* resumeStalled(state, stored, attempt);
23
23
  }
24
- if (!stalled(attempt, now, state.policy.stallMinutes ?? 30)) {
24
+ if (!stalled(attempt, now, (yield* state.current).stallMinutes ?? 30)) {
25
25
  return undefined;
26
26
  }
27
27
  const work = yield* state.board.get(stored.value.workId);
@@ -4,33 +4,34 @@ import { defineService } from "@shivaedev/effect-service/define-service.ts";
4
4
  import { operationRecord } from "#engine/operationRecord.ts";
5
5
  import { threadName } from "#engine/threadNames.ts";
6
6
  import { type Attempt, allAttempts, backlog, executing, FleetRecord } from "#model.ts";
7
- import { checkAreas, needsAreaRecords, requeue } from "#scheduling/areas.ts";
7
+ import { checkLaunchAdmission, needsLaunchRecords } from "#scheduling/admission.ts";
8
+ import { requeue } from "#scheduling/areas.ts";
8
9
  import { SessionFailure, type SessionReceipt } from "#session/schema.ts";
9
10
  import { SessionJournal } from "#session/service.ts";
11
+ import type { FleetStoreOptions } from "#storage/FleetStoreOptions.ts";
10
12
  import { makePostgresFleetStore } from "#storage/makePostgresFleetStore.ts";
11
13
 
14
+ const fleetStoreOptions = {
15
+ admission: checkLaunchAdmission,
16
+ admissionNeedsRecords: needsLaunchRecords,
17
+ backlog,
18
+ executing,
19
+ requeue,
20
+ submissions: (record, since) => allAttempts(record).filter((attempt) => attempt.submittedAt >= since).length,
21
+ } satisfies FleetStoreOptions<FleetRecord>;
22
+
12
23
  type Store = Effect.Success<ReturnType<typeof makePostgresFleetStore<typeof FleetRecord>>>;
13
- export class FleetRepository extends Context.Service<
14
- FleetRepository,
15
- Omit<Store, "initialize" | "operationEntries"> & Partial<Pick<Store, "operationEntries">>
16
- >()("@shivaedev/work-fleet/FleetRepository") {}
24
+ export class FleetRepository extends Context.Service<FleetRepository, Omit<Store, "operationEntries"> & Partial<Pick<Store, "operationEntries">>>()(
25
+ "@shivaedev/work-fleet/FleetRepository",
26
+ ) {}
17
27
  class RepositoryNamespace extends Context.Service<RepositoryNamespace, string | undefined>()("Fleet/RepositoryNamespace") {}
18
28
  const PostgresFleetRepository = defineService({
19
29
  id: "Fleet/PostgresFleetRepository",
20
30
  initialize: Effect.gen(function* () {
21
31
  const namespace = yield* RepositoryNamespace;
22
- const store = yield* makePostgresFleetStore(FleetRecord, {
23
- admission: checkAreas,
24
- admissionNeedsRecords: needsAreaRecords,
25
- backlog,
26
- executing,
27
- requeue,
28
- submissions: (record, since) => allAttempts(record).filter((attempt) => attempt.submittedAt >= since).length,
29
- ...(namespace === undefined ? {} : { namespace }),
30
- });
31
- return store;
32
+ return yield* makePostgresFleetStore(FleetRecord, { ...fleetStoreOptions, ...(namespace === undefined ? {} : { namespace }) });
32
33
  }),
33
- methods: ({ initialize: _initialize, ...methods }) => methods,
34
+ methods: (store) => store,
34
35
  requires: [SqlClient.SqlClient, RepositoryNamespace],
35
36
  });
36
37
 
@@ -0,0 +1,45 @@
1
+ import { Effect } from "effect";
2
+ import type { EngineState, LaunchAdmission } from "#engine/makeState.ts";
3
+ import type { Attempt, FleetRecord } from "#model.ts";
4
+ import type { BoardWork } from "#policy.ts";
5
+ import type { Versioned } from "#storage/model.ts";
6
+
7
+ function launched(record: FleetRecord, attempt: Attempt): FleetRecord {
8
+ return {
9
+ ...record,
10
+ admissionReady: true,
11
+ attempts: [...record.attempts, attempt],
12
+ blocker: undefined,
13
+ launchRetry: undefined,
14
+ mergeAreasReleased: undefined,
15
+ mergeReadyAt: undefined,
16
+ mergeReadyHead: undefined,
17
+ pendingAnswers: undefined,
18
+ stage: "executing",
19
+ };
20
+ }
21
+
22
+ // Urgent work first asks for admission within the limits, so only a launch the limits refused is recorded as over the limit.
23
+ export const saveLaunch = Effect.fn("Fleet.saveLaunch")(function* (
24
+ state: EngineState,
25
+ stored: Versioned<FleetRecord>,
26
+ record: FleetRecord,
27
+ attempt: Attempt,
28
+ launch: Pick<LaunchAdmission, "quota" | "role"> & { readonly priority: BoardWork["priority"] },
29
+ ) {
30
+ const implementer = stored.value.stage === "prepared";
31
+ const admission: LaunchAdmission = {
32
+ ignoreAreas: implementer && stored.value.dispatchNow?.ignoreAreas === true,
33
+ implementer,
34
+ quota: launch.quota,
35
+ role: launch.role,
36
+ };
37
+ const urgent = implementer && (launch.priority === "urgent" || stored.value.dispatchNow !== undefined);
38
+ return yield* state
39
+ .save(stored, launched(record, attempt), admission)
40
+ .pipe(
41
+ Effect.catchTag("StorageCapacity", (error) =>
42
+ urgent ? state.save(stored, launched(record, { ...attempt, overLimit: true }), { ...admission, overLimit: true }) : Effect.fail(error),
43
+ ),
44
+ );
45
+ });
@@ -10,9 +10,7 @@ import type { Versioned } from "#storage/model.ts";
10
10
 
11
11
  const dispatchRecords = Effect.fn("Fleet.dispatchRecords")(function* (records: readonly Versioned<FleetRecord>[]) {
12
12
  const fleet = yield* Fleet;
13
- const prepared = records
14
- .filter(({ value }) => value.stage === "prepared")
15
- .sort((left, right) => (right.value.launchRetry?.retryAt ?? 0) - (left.value.launchRetry?.retryAt ?? 0));
13
+ const prepared = yield* fleet.admissionOrder(records);
16
14
  const dispatched: Result.Result<Effect.Success<ReturnType<typeof fleet.dispatch>>, Effect.Error<ReturnType<typeof fleet.dispatch>>>[] = [];
17
15
  for (const { value } of prepared) {
18
16
  const result = yield* fleet.dispatch(value.workId).pipe(Effect.result);
@@ -60,8 +58,8 @@ export const cycle = inBoardReadPass(
60
58
  return result;
61
59
  }),
62
60
  );
63
- export const run = Effect.fn("Fleet.run")(function* <R = never>(
64
- interval: Parameters<typeof Effect.sleep>[0],
61
+ export const run = Effect.fn("Fleet.run")(function* <R = never, TPause = never>(
62
+ pause: Effect.Effect<void, never, TPause>,
65
63
  admit: Effect.Effect<void, never, R> = Effect.void,
66
64
  ) {
67
65
  const fleet = yield* Fleet;
@@ -82,6 +80,6 @@ export const run = Effect.fn("Fleet.run")(function* <R = never>(
82
80
  yield* dispatchPrepared;
83
81
  yield* schedulerPassed;
84
82
  }),
85
- ).pipe(Effect.andThen(Effect.sleep(interval))),
83
+ ).pipe(Effect.andThen(pause)),
86
84
  );
87
85
  });
@@ -12,6 +12,7 @@ export function views(records: readonly FleetRecord[]): typeof FleetViews.Type {
12
12
  decision: record.stage === "completed" ? undefined : record.decision,
13
13
  links: [...(record.report === undefined ? [] : [record.report.sourcePath]), ...(record.result?.kind === "change" ? [record.result.pr] : [])],
14
14
  outcome: record.outcome,
15
+ ...(launchedOverLimit(record) ? { overLimit: true } : {}),
15
16
  sessions: record.attempts.flatMap(sessionView),
16
17
  stage: record.stage,
17
18
  workId: record.workId,
@@ -41,3 +42,7 @@ function sessionView(attempt: Attempt) {
41
42
  },
42
43
  ];
43
44
  }
45
+
46
+ function launchedOverLimit(record: FleetRecord) {
47
+ return record.attempts.some((attempt) => attempt.overLimit === true && ["submitting", "accepted", "running"].includes(attempt.status));
48
+ }
package/src/fleet.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Effect } from "effect";
2
2
  import { defineService } from "@shivaedev/effect-service/define-service.ts";
3
+ import { admissionOrder } from "#engine/admissionOrder.ts";
3
4
  import { closeDecisions } from "#engine/closeDecisions.ts";
4
5
  import { continueCommand } from "#engine/continueCommand.ts";
5
6
  import { dispatchCommand } from "#engine/dispatchCommand.ts";
@@ -11,6 +12,7 @@ import { prepareCommand } from "#engine/prepareCommand.ts";
11
12
  import { queueAnswerCommand } from "#engine/queueAnswerCommand.ts";
12
13
  import { reassignCommand } from "#engine/reassignCommand.ts";
13
14
  import { reconcileCommand } from "#engine/reconcileCommand.ts";
15
+ import { recordResponseCommand } from "#engine/recordResponseCommand.ts";
14
16
  import { FleetRepository } from "#engine/repository.ts";
15
17
  import { resolveCommand } from "#engine/resolveCommand.ts";
16
18
  import { cleanupSessions } from "#engine/sessionCleanup.ts";
@@ -33,6 +35,7 @@ export const Fleet = defineService({
33
35
  return { ...state, advance: makeAdvance(state, launch), launch };
34
36
  }),
35
37
  methods: (state) => ({
38
+ admissionOrder: admissionOrder(state),
36
39
  continue: continueCommand(state, state.launch),
37
40
  dispatch: dispatchCommand(state, state.launch),
38
41
  get: (workId: string) => state.load(workId),
@@ -43,6 +46,7 @@ export const Fleet = defineService({
43
46
  queueAnswer: queueAnswerCommand(state),
44
47
  reassign: reassignCommand(state),
45
48
  reconcile: (workId: string) => reconcileCommand(state, state.advance)(workId).pipe(Effect.flatMap(cleanupSessions(state))),
49
+ recordResponse: recordResponseCommand(state),
46
50
  resolve: (workId: string, decisionId: string, responseId: string) =>
47
51
  resolveCommand(state)(workId, decisionId, responseId).pipe(Effect.flatMap(cleanupSessions(state))),
48
52
  }),
@@ -12,7 +12,11 @@ export const continueCommand = Command.make(
12
12
  { args: [Argument.String("id"), Argument.String("message").pipe(Argument.optional)] as const, board, config, port },
13
13
  Effect.fn("WorkFleetCli.continue")(function* (input) {
14
14
  const message = yield* continuationMessage(Option.getOrUndefined(input.args[1]));
15
- const value = yield* daemonRequest(input.port, (client) => client("fleet.continue", { message, workId: input.args[0] }));
15
+ const value = yield* daemonRequest(
16
+ input.port,
17
+ (client) => client("fleet.continue", { message, workId: input.args[0] }),
18
+ `continue ${input.args[0]}`,
19
+ );
16
20
  yield* Console.log(`${value.workId} ${value.stage}${value.blocker === undefined ? "" : `: ${value.blocker}`}`);
17
21
  }),
18
22
  ).pipe(
@@ -23,7 +27,11 @@ export const releaseCommand = Command.make(
23
27
  "release",
24
28
  { board, config, port, workIds: Argument.String("id").pipe(Argument.variadic({ min: 1 })) },
25
29
  Effect.fn("WorkFleetCli.release")(function* (input) {
26
- const released = yield* daemonRequest(input.port, (client) => client("daemon.release", { workIds: input.workIds }));
30
+ const released = yield* daemonRequest(
31
+ input.port,
32
+ (client) => client("daemon.release", { workIds: input.workIds }),
33
+ `release ${input.workIds.join(", ")}`,
34
+ );
27
35
  for (const value of released) {
28
36
  yield* Console.log(`${value.workId} ${value.stage}${value.blocker === undefined ? "" : `: ${value.blocker}`}`);
29
37
  }
@@ -41,8 +49,10 @@ export const reassignCommand = Command.make(
41
49
  to: Argument.Literals("owner", ["maintainer", "orchestrator", "automation"]),
42
50
  },
43
51
  Effect.fn("WorkFleetCli.reassign")(function* (input) {
44
- const value = yield* daemonRequest(input.port, (client) =>
45
- client("fleet.reassign", { attentionOwner: input.to, decisionId: input.question, workId: input.id }),
52
+ const value = yield* daemonRequest(
53
+ input.port,
54
+ (client) => client("fleet.reassign", { attentionOwner: input.to, decisionId: input.question, workId: input.id }),
55
+ `reassign ${input.id}`,
46
56
  );
47
57
  yield* Console.log(`${value.workId} ${value.stage} (waiting on ${value.attentionOwner})`);
48
58
  }),
@@ -52,7 +62,7 @@ export const nameThreadsCommand = Command.make(
52
62
  "name-threads",
53
63
  { board, config, port },
54
64
  Effect.fn("WorkFleetCli.nameThreads")(function* (input) {
55
- const results = yield* daemonRequest(input.port, (client) => client("daemon.name-threads", {}));
65
+ const results = yield* daemonRequest(input.port, (client) => client("daemon.name-threads", {}), "name-threads");
56
66
  for (const result of results) {
57
67
  yield* result.error ? Console.error(result.message) : Console.log(result.message);
58
68
  }
@@ -69,8 +79,13 @@ export const answerCommand = Command.make(
69
79
  release: Flag.Boolean("release").pipe(Flag.withDefault(false)),
70
80
  },
71
81
  Effect.fn("WorkFleetCli.answer")(function* (input) {
72
- const text = yield* answerText(Option.getOrUndefined(input.args[1]));
73
- const value = yield* daemonRequest(input.port, (client) => client("daemon.answer", { release: input.release, text, workId: input.args[0] }));
82
+ const supplied = Option.getOrUndefined(input.args[1]);
83
+ const text = input.release && supplied === undefined ? "" : yield* answerText(supplied);
84
+ const value = yield* daemonRequest(
85
+ input.port,
86
+ (client) => client("daemon.answer", { release: input.release, text, workId: input.args[0] }),
87
+ `answer ${input.args[0]}`,
88
+ );
74
89
  const detail = (value.pendingAnswers?.length ?? 0) > 0 ? "queued for the next turn" : value.blocker;
75
90
  yield* Console.log(`${value.workId} ${value.stage}${detail === undefined ? "" : `: ${detail}`}`);
76
91
  }),
@@ -8,7 +8,7 @@ import { Fleet } from "#fleet.ts";
8
8
  import type { FleetHost } from "#host/config.ts";
9
9
  import { type MainSnapshot, MainSource } from "#host/mainSource.ts";
10
10
  import { workerCwd } from "#host/providers.ts";
11
- import type { FleetRecord } from "#model.ts";
11
+ import type { DispatchNow, FleetRecord } from "#model.ts";
12
12
  import { BoardGateway, type BoardWork } from "#policy.ts";
13
13
  import type { Preparation } from "#preparation/schema.ts";
14
14
  import { workerPrompt } from "#prompt/worker.ts";
@@ -116,7 +116,7 @@ export const admitApproved = Effect.fn("FleetHost.admitApproved")(function* (hos
116
116
  return failures;
117
117
  }, inBoardReadPass);
118
118
 
119
- export const dispatchApproved = Effect.fn("FleetHost.dispatchApproved")(function* (host: FleetHost, workId: string) {
119
+ export const dispatchApproved = Effect.fn("FleetHost.dispatchApproved")(function* (host: FleetHost, workId: string, now?: DispatchNow) {
120
120
  const fleet = yield* Fleet;
121
121
  const work = yield* (yield* BoardGateway).get(workId);
122
122
  if (!work.approved) {
@@ -127,5 +127,5 @@ export const dispatchApproved = Effect.fn("FleetHost.dispatchApproved")(function
127
127
  if (existing === undefined || ["completed", "released"].includes(existing.stage) || unlaunched(existing) || !briefChanged(existing, work)) {
128
128
  yield* prepareApproved(host, work, existing, "explicit");
129
129
  }
130
- return yield* fleet.dispatch(workId, launchPrompt(host, work));
130
+ return yield* fleet.dispatch(workId, launchPrompt(host, work), now);
131
131
  }, inBoardReadPass);
@@ -3,37 +3,38 @@ import { BadRequest, Conflict } from "@shivaedev/platform/errors/taxonomy.ts";
3
3
  import { Fleet } from "#fleet.ts";
4
4
  import type { FleetHost } from "#host/config.ts";
5
5
  import { recordDecisionResponse } from "#host/recordDecisionResponse.ts";
6
- import { withDecisionResponses } from "#host/releaseWork.ts";
7
6
  import type { FleetRecord } from "#model.ts";
8
7
  import type { Decision } from "#policy.ts";
9
8
 
10
- export function answerWork(host: FleetHost, workId: string, text = "", release = false) {
11
- return withDecisionResponses(
12
- host,
13
- Effect.gen(function* () {
14
- const fleet = yield* Fleet;
15
- const original = (yield* fleet.get(workId)).value.decision;
16
- let recorded: { readonly decisionId: string; readonly responseId: string } | undefined;
17
- return yield* Effect.gen(function* () {
18
- const current = (yield* fleet.get(workId)).value;
19
- if (recorded !== undefined && hasResponse(current, recorded)) {
20
- return yield* fleet.resolve(workId, recorded.decisionId, recorded.responseId);
21
- }
22
- if (canQueueAnswer(current, text, release)) {
23
- return yield* fleet.queueAnswer(workId, text);
24
- }
25
- yield* checkDecision(current, original);
26
- const response = yield* publishAnswer(host, workId, original, text, release);
27
- recorded = response;
28
- return yield* fleet
29
- .resolve(workId, response.decisionId, response.responseId)
30
- .pipe(Effect.catchTag("Conflict", (error) => decisionConflict(fleet, workId, response.decisionId, error)));
31
- }).pipe(
32
- Effect.retry({ while: (error) => error._tag === "StorageConflict" || (error._tag === "Conflict" && error.message === "Decision changed") }),
33
- );
34
- }),
9
+ export const answerWork = Effect.fn("FleetHost.answerWork")(function* (
10
+ host: FleetHost,
11
+ workId: string,
12
+ text = "",
13
+ release = false,
14
+ background = false,
15
+ ) {
16
+ const fleet = yield* Fleet;
17
+ const resolve = background ? fleet.recordResponse : fleet.resolve;
18
+ const original = (yield* fleet.get(workId)).value.decision;
19
+ let recorded: { readonly decisionId: string; readonly responseId: string } | undefined;
20
+ return yield* Effect.gen(function* () {
21
+ const current = (yield* fleet.get(workId)).value;
22
+ if (recorded !== undefined && hasResponse(current, recorded)) {
23
+ return yield* resolve(workId, recorded.decisionId, recorded.responseId);
24
+ }
25
+ if (canQueueAnswer(current, text, release)) {
26
+ return yield* fleet.queueAnswer(workId, text);
27
+ }
28
+ yield* checkDecision(current, original);
29
+ const response = yield* publishAnswer(host, workId, original, text, release);
30
+ recorded = response;
31
+ return yield* resolve(workId, response.decisionId, response.responseId).pipe(
32
+ Effect.catchTag("Conflict", (error) => decisionConflict(fleet, workId, response.decisionId, error)),
33
+ );
34
+ }).pipe(
35
+ Effect.retry({ while: (error) => error._tag === "StorageConflict" || (error._tag === "Conflict" && error.message === "Decision changed") }),
35
36
  );
36
- }
37
+ });
37
38
 
38
39
  function checkDecision(record: FleetRecord, original: Decision | undefined) {
39
40
  const current = record.decision;
@@ -1,11 +1,13 @@
1
1
  import * as NodeServices from "@effect/platform-node/NodeServices";
2
- import { Console, Effect, Layer } from "effect";
2
+ import { Console, Effect, Layer, Stream } from "effect";
3
3
  import type { ReportInspection } from "#engine/ReportInspection.ts";
4
4
  import { run } from "#engine/scheduler.ts";
5
5
  import { Fleet } from "#fleet.ts";
6
6
  import { admitApproved, dispatchApproved } from "#host/admission.ts";
7
7
  import type { FleetHost } from "#host/config.ts";
8
+ import { GithubApi } from "#host/githubApi.ts";
8
9
  import { healthLayer } from "#host/healthLayer.ts";
10
+ import { LiveConfig, staticConfig } from "#host/liveConfig.ts";
9
11
  import { gitMainSource, type MainSource } from "#host/mainSource.ts";
10
12
  import { hostProvider } from "#host/providers.ts";
11
13
  import { fleetHostLayer } from "#host/runtime.ts";
@@ -14,8 +16,9 @@ import type { BoardGateway, FleetIntegrations, FleetPolicy } from "#policy.ts";
14
16
  import type { SessionTransport } from "#session/service.ts";
15
17
 
16
18
  export interface HostParts {
17
- readonly board?: Layer.Layer<BoardGateway | ReportInspection, unknown, MainSource>;
18
- readonly integrations?: Layer.Layer<FleetIntegrations, unknown, MainSource>;
19
+ readonly board?: Layer.Layer<BoardGateway | ReportInspection, unknown, MainSource | GithubApi>;
20
+ readonly github?: Layer.Layer<GithubApi>;
21
+ readonly integrations?: Layer.Layer<FleetIntegrations, unknown, MainSource | GithubApi>;
19
22
  readonly main: Layer.Layer<MainSource, unknown>;
20
23
  readonly policy?: Layer.Layer<FleetPolicy>;
21
24
  readonly provider: Layer.Layer<SessionTransport, unknown>;
@@ -25,13 +28,31 @@ export function productionParts(host: FleetHost): HostParts {
25
28
  return { main: gitMainSource(host), provider: hostProvider(host) };
26
29
  }
27
30
 
28
- export function hostLayer(host: FleetHost, parts: HostParts) {
29
- const runtime = Layer.mergeAll(fleetHostLayer(host, parts), NodeServices.layer).pipe(Layer.provideMerge(healthLayer(host.boardDir)));
30
- return statusLayer(host.boardDir, { concurrency: host.concurrency, staleAfterMs: Math.max(60_000, host.interval * 3000) }).pipe(
31
- Layer.provideMerge(runtime),
31
+ export function hostLayer(host: FleetHost, parts: HostParts, config: Layer.Layer<LiveConfig, unknown> = staticConfig(host)) {
32
+ const runtime = Layer.mergeAll(fleetHostLayer(host, parts, config), NodeServices.layer).pipe(Layer.provideMerge(healthLayer(host.boardDir)));
33
+ const status = Layer.unwrap(
34
+ Effect.map(LiveConfig, (live) =>
35
+ statusLayer(
36
+ host.boardDir,
37
+ Effect.map(live.current, ({ host: applied }) => ({
38
+ concurrency: applied.concurrency,
39
+ staleAfterMs: Math.max(60_000, applied.interval * 3000),
40
+ })),
41
+ ),
42
+ ),
32
43
  );
44
+ return status.pipe(Layer.provideMerge(runtime), Layer.provideMerge(config));
33
45
  }
34
46
 
47
+ // An applied config edit starts the next pass at once instead of after the interval it replaced, and a low GitHub budget stretches that interval.
48
+ export const schedulerPause = Effect.gen(function* () {
49
+ const live = yield* LiveConfig;
50
+ const github = yield* GithubApi;
51
+ const { host: applied } = yield* live.current;
52
+ const delay = yield* github.pace(applied.interval * 1000);
53
+ yield* Effect.raceFirst(Effect.sleep(delay), live.changes.pipe(Stream.drop(1), Stream.take(1), Stream.runDrain));
54
+ });
55
+
35
56
  export function hostScheduler(host: FleetHost) {
36
57
  let reported = new Set<string>();
37
58
  const admission = admitApproved(host).pipe(
@@ -45,7 +66,7 @@ export function hostScheduler(host: FleetHost) {
45
66
  }),
46
67
  ),
47
68
  );
48
- return run(`${host.interval} seconds`, admission);
69
+ return run(schedulerPause, admission);
49
70
  }
50
71
 
51
72
  export function runFleet(host: FleetHost, parts: HostParts = productionParts(host)) {
@@ -2,11 +2,14 @@ import * as Effect from "effect/Effect";
2
2
  import * as FileSystem from "effect/FileSystem";
3
3
  import * as Path from "effect/Path";
4
4
  import * as Schema from "effect/Schema";
5
+ import * as SchemaIssue from "effect/SchemaIssue";
5
6
  import { CONFIG_FILE, DEFAULT_NAMESPACE, NAMESPACE, SHARED_LOCAL_POSTGRES } from "#host/defaults.ts";
6
7
  import { DEFAULT_AREA_MERGE_WAIT_MS } from "#scheduling/areas.ts";
7
8
  import { LaunchSettings } from "#session/schema.ts";
9
+ import type { OpenPullRequestCurve } from "#storage/model.ts";
8
10
 
9
11
  const Positive = Schema.Int.check(Schema.isGreaterThan(0));
12
+ const Count = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
10
13
  const Text = Schema.String.check(Schema.isMinLength(1));
11
14
  const Guidance = Schema.Union([Text, Schema.Struct({ file: Text })]);
12
15
 
@@ -21,6 +24,7 @@ export const HostConfig = Schema.Struct({
21
24
  endpoint: Schema.optional(Text),
22
25
  environmentId: Text,
23
26
  projectId: Schema.optional(Text),
27
+ recoveryGraceMs: Schema.optional(Positive),
24
28
  refreshCommand: Schema.optional(Schema.Struct({ args: Schema.Array(Schema.String), command: Text })),
25
29
  requestTimeoutMs: Schema.optional(Positive),
26
30
  threadNamePrefix: Schema.optional(Text),
@@ -33,6 +37,11 @@ export const HostConfig = Schema.Struct({
33
37
  launch: Schema.optional(LaunchSettings),
34
38
  local: Schema.optional(Schema.Struct({ endpoint: Text, requestTimeoutMs: Schema.optional(Positive) })),
35
39
  namespace: Schema.optional(Schema.String.check(Schema.isPattern(NAMESPACE))),
40
+ openPullRequests: Schema.optional(
41
+ Schema.Struct({ ease: Count, floor: Schema.optional(Count), max: Positive }).check(
42
+ Schema.makeFilter((curve) => curve.ease <= curve.max || "openPullRequests.ease must not exceed openPullRequests.max"),
43
+ ),
44
+ ),
36
45
  provider: Schema.Literals(["local", "cloud"]),
37
46
  quota: Schema.optional(Schema.Literals(["codex", "unlimited"])),
38
47
  repository: Schema.optional(Schema.Struct({ branch: Text, remote: Text })),
@@ -51,18 +60,27 @@ export type HostConfig = typeof HostConfig.Type;
51
60
 
52
61
  export class HostFailure extends Schema.TaggedError<HostFailure>()("HostFailure", { message: Schema.String }) {}
53
62
 
63
+ export class HostConfigRejected extends Schema.TaggedError<HostConfigRejected>()("HostConfigRejected", {
64
+ field: Schema.optional(Schema.String),
65
+ file: Schema.String,
66
+ message: Schema.String,
67
+ }) {}
68
+
54
69
  export interface FleetHost {
55
70
  readonly areaMergeWaitMs: number;
56
71
  readonly backlog: number;
57
72
  readonly boardDir: string;
58
73
  readonly cloud: HostConfig["cloud"];
59
74
  readonly concurrency: number;
75
+ readonly config: HostConfig;
76
+ readonly configFile?: string;
60
77
  readonly databaseUrl: string;
61
78
  readonly interval: number;
62
79
  readonly launch: NonNullable<HostConfig["launch"]>;
63
80
  readonly local: HostConfig["local"];
64
81
  readonly maxConnections: number;
65
82
  readonly namespace: string;
83
+ readonly openPullRequests?: OpenPullRequestCurve;
66
84
  readonly provider: HostConfig["provider"];
67
85
  readonly quota: NonNullable<HostConfig["quota"]>;
68
86
  readonly repository: NonNullable<HostConfig["repository"]>;
@@ -71,19 +89,22 @@ export interface FleetHost {
71
89
  readonly worker: HostConfig["worker"];
72
90
  }
73
91
 
74
- export function resolveHost(boardDir: string, config: HostConfig): FleetHost {
92
+ export function resolveHost(boardDir: string, config: HostConfig, configFile?: string): FleetHost {
75
93
  return {
76
94
  areaMergeWaitMs: config.areaMergeWaitMs ?? DEFAULT_AREA_MERGE_WAIT_MS,
77
95
  backlog: config.backlog ?? 100,
78
96
  boardDir,
79
97
  cloud: config.cloud,
80
98
  concurrency: config.concurrency ?? 100,
99
+ config,
100
+ ...(configFile === undefined ? {} : { configFile }),
81
101
  databaseUrl: config.database?.url ?? SHARED_LOCAL_POSTGRES,
82
102
  interval: config.intervalSeconds ?? 15,
83
103
  launch: config.launch ?? {},
84
104
  local: config.local,
85
105
  maxConnections: config.database?.maxConnections ?? 20,
86
106
  namespace: config.namespace ?? DEFAULT_NAMESPACE,
107
+ ...(config.openPullRequests === undefined ? {} : { openPullRequests: { ...config.openPullRequests, floor: config.openPullRequests.floor ?? 0 } }),
87
108
  provider: config.provider,
88
109
  quota: config.quota ?? "codex",
89
110
  repository: config.repository ?? { branch: "main", remote: "origin" },
@@ -93,19 +114,35 @@ export function resolveHost(boardDir: string, config: HostConfig): FleetHost {
93
114
  };
94
115
  }
95
116
 
96
- export const loadHost = Effect.fn("FleetHost.loadHost")(function* (board: string, configPath?: string) {
117
+ export const readHostConfig = Effect.fn("FleetHost.readHostConfig")(function* (file: string) {
97
118
  const fs = yield* FileSystem.FileSystem;
98
- const path = yield* Path.Path;
99
- const boardDir = path.resolve(board);
100
- const file = configPath === undefined ? path.join(boardDir, CONFIG_FILE) : path.resolve(configPath);
101
119
  const text = yield* fs
102
120
  .readFileString(file)
103
- .pipe(Effect.mapError(() => new HostFailure({ message: `Fleet host configuration is missing or unreadable: ${file}` })));
121
+ .pipe(Effect.mapError(() => new HostConfigRejected({ file, message: `Fleet host configuration is missing or unreadable: ${file}` })));
104
122
  const config = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(HostConfig))(text).pipe(
105
- Effect.mapError((error) => new HostFailure({ message: `Fleet host configuration ${file} is invalid: ${error.message}` })),
123
+ Effect.mapError((error) => {
124
+ const field = SchemaIssue.makeFormatterStandardSchemaV1()(error.issue).issues[0]?.path?.map(String).join(".");
125
+ return new HostConfigRejected({
126
+ ...(field === undefined || field === "" ? {} : { field }),
127
+ file,
128
+ message: `Fleet host configuration ${file} is invalid: ${error.message}`,
129
+ });
130
+ }),
106
131
  );
107
132
  if (config.provider === "cloud" && (config.cloud === undefined || config.worker === undefined)) {
108
- return yield* new HostFailure({ message: `Fleet host configuration ${file} selects provider "cloud" without cloud and worker settings` });
133
+ return yield* new HostConfigRejected({
134
+ field: config.cloud === undefined ? "cloud" : "worker",
135
+ file,
136
+ message: `Fleet host configuration ${file} selects provider "cloud" without cloud and worker settings`,
137
+ });
109
138
  }
110
- return resolveHost(boardDir, config);
139
+ return config;
140
+ });
141
+
142
+ export const loadHost = Effect.fn("FleetHost.loadHost")(function* (board: string, configPath?: string) {
143
+ const path = yield* Path.Path;
144
+ const boardDir = path.resolve(board);
145
+ const file = configPath === undefined ? path.join(boardDir, CONFIG_FILE) : path.resolve(configPath);
146
+ const config = yield* readHostConfig(file).pipe(Effect.mapError((rejected) => new HostFailure({ message: rejected.message })));
147
+ return resolveHost(boardDir, config, file);
111
148
  });