@shivaedev/work-fleet 0.2.1 → 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 +41 -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 +880 -1185
  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 +1974 -3079
  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
@@ -1,5 +1,6 @@
1
1
  import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
2
2
  import { sessionStatus } from "#engine/sessionStatus.ts";
3
+ import { type DaemonStatus, renderConfig } from "#host/configSettings.ts";
3
4
  import type { FleetViews } from "#model.ts";
4
5
 
5
6
  const { DAEMON_PORT } = diagnosticsApi;
@@ -7,14 +8,14 @@ const { DAEMON_PORT } = diagnosticsApi;
7
8
  type View = (typeof FleetViews.Type)["active"][number];
8
9
 
9
10
  function line(view: View, waiting: boolean, port: number) {
10
- const reason = view.decision?.reason ?? view.blocker;
11
+ const reason = view.blocker ?? view.decision?.reason ?? (view.overLimit ? "launched over the limit" : undefined);
11
12
  const detail = reason === undefined ? "" : ` ${reason}`;
12
13
  const links = [...view.links, ...view.sessions.map(sessionStatus)];
13
14
  const answer = waiting ? `\n work-fleet answer ${view.workId}${port === DAEMON_PORT ? "" : ` --port ${port}`}` : "";
14
15
  return ` ${view.workId} ${view.stage}${detail}${links.length === 0 ? "" : ` (${links.join(", ")})`}${answer}`;
15
16
  }
16
17
 
17
- export function renderStatus(current: typeof FleetViews.Type, port: number = DAEMON_PORT): string {
18
+ export function renderStatus(current: typeof DaemonStatus.Type, port: number = DAEMON_PORT): string {
18
19
  const sections: readonly [string, readonly View[]][] = [
19
20
  ["Active", current.active],
20
21
  ["Waiting on maintainer", current.waiting.maintainer],
@@ -22,7 +23,7 @@ export function renderStatus(current: typeof FleetViews.Type, port: number = DAE
22
23
  ["Waiting on automation", current.waiting.automation],
23
24
  ["Completed", current.completed],
24
25
  ];
25
- return sections
26
+ const rendered = sections
26
27
  .map(([title, items]) =>
27
28
  [
28
29
  `${title} (${items.length})`,
@@ -30,4 +31,10 @@ export function renderStatus(current: typeof FleetViews.Type, port: number = DAE
30
31
  ].join("\n"),
31
32
  )
32
33
  .join("\n");
34
+ const dispatches = current.dispatches ?? [];
35
+ const views =
36
+ dispatches.length === 0
37
+ ? rendered
38
+ : `${rendered}\nDispatches (${dispatches.length})\n${dispatches.map((request) => ` ${request.workId} dispatch ${request.status}${request.error === undefined ? "" : `: ${request.error}`}`).join("\n")}`;
39
+ return current.config === undefined ? views : `${views}\n${renderConfig(current.config)}`;
33
40
  }
@@ -1,7 +1,7 @@
1
1
  import * as NodeServices from "@effect/platform-node/NodeServices";
2
2
  import { Context, Effect, Layer } from "effect";
3
3
  import { defineService } from "@shivaedev/effect-service/define-service.ts";
4
- import { BadRequest, ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
4
+ import { BadRequest } from "@shivaedev/platform/errors/taxonomy.ts";
5
5
  import { markdownBoard } from "#board/markdown.ts";
6
6
  import { reportContent } from "#board/reportContent.ts";
7
7
  import { reportFiles } from "#board/reportFiles.ts";
@@ -12,6 +12,8 @@ import { withFailureContext } from "#engine/failureContext.ts";
12
12
  import { ReportInspection } from "#engine/ReportInspection.ts";
13
13
  import { isFleetError } from "#errors.ts";
14
14
  import type { FleetHost } from "#host/config.ts";
15
+ import { GithubApi } from "#host/githubApi.ts";
16
+ import { githubFailure } from "#host/githubRateLimit.ts";
15
17
  import { MainSource } from "#host/mainSource.ts";
16
18
  import { reportPublication, reportRepository } from "#host/reportPublication.ts";
17
19
  import { BoardFailure, BoardGateway, type BoardWork } from "#policy.ts";
@@ -57,7 +59,7 @@ const ReportBoard = defineService({
57
59
  const { root, check, files } = yield* ReportInputs;
58
60
  function inspect(work: BoardWork) {
59
61
  return check(work).pipe(
60
- Effect.mapError(() => new ServiceUnavailable({ message: "Report publication could not be checked on GitHub" })),
62
+ Effect.mapError(githubFailure("Report publication could not be checked on GitHub")),
61
63
  Effect.flatMap((published) =>
62
64
  published ? Effect.fail(withFailureContext(new BadRequest({ message: PUBLISHED_REPORT }), { code: "report-published" })) : Effect.void,
63
65
  ),
@@ -121,12 +123,13 @@ export function hostReportBoard(host: FleetHost) {
121
123
  return Layer.unwrap(
122
124
  Effect.gen(function* () {
123
125
  const main = yield* MainSource;
126
+ const github = yield* GithubApi;
124
127
  function check(work: BoardWork) {
125
128
  return Effect.gen(function* () {
126
129
  if (host.worker === undefined) {
127
130
  return yield* Effect.fail(new BoardFailure({ message: "Report publication checks need worker.branchPrefix" }));
128
131
  }
129
- return yield* reportPublication(
132
+ return yield* reportPublication(github)(
130
133
  yield* reportRepository(main.repositoryRoot, host.repository.remote),
131
134
  `${host.worker.branchPrefix}${work.workId}`,
132
135
  );
@@ -1,6 +1,8 @@
1
1
  import { Effect, Schema } from "effect";
2
2
  import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
3
3
  import type { FleetError } from "#errors.ts";
4
+ import type { GithubRead } from "#host/github.ts";
5
+ import { githubFailure } from "#host/githubRateLimit.ts";
4
6
  import { readCommand } from "#host/readCommand.ts";
5
7
 
6
8
  const References = Schema.Array(Schema.Array(Schema.Struct({ ref: Schema.String })));
@@ -17,13 +19,13 @@ export function makeReportPublication<R>(read: (endpoint: string) => Effect.Effe
17
19
  ).pipe(Effect.flatMap(Schema.decodeUnknownEffect(Schema.fromJsonString(PullRequests))));
18
20
  return refs.flat().some((ref) => ref.ref === `refs/heads/${branch}`) || prs.flat().length > 0;
19
21
  },
20
- Effect.mapError(() => new ServiceUnavailable({ message: "Report publication could not be checked on GitHub" })),
22
+ Effect.mapError(githubFailure("Report publication could not be checked on GitHub")),
21
23
  );
22
24
  }
23
25
 
24
- export const reportPublication = makeReportPublication((endpoint) =>
25
- readCommand("gh", ["api", "--method", "GET", "--paginate", "--slurp", endpoint]),
26
- );
26
+ export function reportPublication(read: GithubRead) {
27
+ return makeReportPublication(read.pages);
28
+ }
27
29
 
28
30
  export const reportRepository = Effect.fn("Fleet.reportRepository")(function* (cwd: string, remote: string) {
29
31
  const url = (yield* readCommand("git", ["remote", "get-url", remote], cwd)).trim();
@@ -1,81 +1,62 @@
1
1
  import * as NodeServices from "@effect/platform-node/NodeServices";
2
2
  import { Clock, Effect, Layer, Redacted } from "effect";
3
- import { defineService } from "@shivaedev/effect-service/define-service.ts";
4
3
  import { appDatabase } from "@shivaedev/platform/appHost.ts";
5
4
  import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
6
- import type { DecisionCode } from "#DecisionCode.ts";
7
- import { withFailureContext } from "#engine/failureContext.ts";
8
5
  import type { ReportInspection } from "#engine/ReportInspection.ts";
9
6
  import { fleetSessionJournal, postgresFleetRepository } from "#engine/repository.ts";
10
7
  import { Fleet } from "#fleet.ts";
11
8
  import { type FleetHost, HostFailure } from "#host/config.ts";
12
- import { githubChecks } from "#host/githubChecks.ts";
13
- import { githubDelivery } from "#host/githubDelivery.ts";
14
- import { githubResult } from "#host/githubResult.ts";
15
- import { hostGuidance } from "#host/guidance.ts";
9
+ import { type GithubApi, githubApiLayer } from "#host/githubApi.ts";
10
+ import { hostIntegrations } from "#host/integrations.ts";
11
+ import { type AppliedConfig, LiveConfig, staticConfig } from "#host/liveConfig.ts";
16
12
  import { localOnlyBoardPath } from "#host/localOnlyBoardPath.ts";
17
13
  import { MainSource } from "#host/mainSource.ts";
18
14
  import { providerHealth } from "#host/providerHealth.ts";
19
15
  import { hostQuota } from "#host/quota.ts";
20
16
  import { hostReportBoard } from "#host/reportBoard.ts";
21
- import { type BoardGateway, FleetIntegrations, FleetPolicy } from "#policy.ts";
17
+ import { type BoardGateway, type FleetConfiguration, type FleetIntegrations, FleetPolicy } from "#policy.ts";
22
18
  import { SessionService, type SessionTransport } from "#session/service.ts";
23
19
  import { fleetMigrations } from "#storage/fleetMigrations.ts";
24
20
 
25
- function unconfigured(message: string, code: DecisionCode = "fleet-integration") {
26
- return Effect.fail(withFailureContext(new ServiceUnavailable({ message }), { attentionOwner: "automation", code, retryable: false }));
27
- }
28
-
29
- export function hostIntegrations(host: FleetHost) {
30
- const HostIntegrations = defineService({
31
- id: "Fleet/HostIntegrations",
32
- initialize: MainSource,
33
- methods: (main) =>
34
- FleetIntegrations.of({
35
- checks: (_work, result) =>
36
- result.kind === "no-change"
37
- ? unconfigured("No-change validation is not configured in this Fleet host; inspect the worker session", "no-change-checks-unconfigured")
38
- : githubChecks(result, host.repository.branch).pipe(Effect.provide(NodeServices.layer)),
39
- delivery: githubDelivery(main.repositoryRoot),
40
- main: main.observe,
41
- result:
42
- host.result === "github"
43
- ? githubResult(host, main)
44
- : () => unconfigured("Worker result adoption is not configured in this Fleet host; inspect the worker session"),
45
- }),
46
- requires: [MainSource],
47
- });
48
- return Layer.effect(FleetIntegrations)(HostIntegrations).pipe(Layer.provide(HostIntegrations.layer));
49
- }
50
-
51
21
  export function hostPolicy(host: FleetHost) {
52
22
  return Layer.effect(FleetPolicy)(
53
23
  Effect.gen(function* () {
54
24
  const clock = yield* Clock.Clock;
55
25
  const main = yield* MainSource;
26
+ const live = yield* LiveConfig;
56
27
  const localPath = host.provider === "cloud" ? yield* localOnlyBoardPath(host.boardDir, main.repositoryRoot) : undefined;
57
- const reviewerGuidance = yield* hostGuidance(host, "reviewer");
58
- const workerGuidance = yield* hostGuidance(host, "worker");
59
28
  function now() {
60
29
  return clock.currentTimeMillisUnsafe();
61
30
  }
62
- return FleetPolicy.of({
63
- areaMergeWaitMs: host.areaMergeWaitMs,
64
- deliveryBacklog: host.backlog,
65
- executionConcurrency: host.concurrency,
66
- launch: host.launch,
67
- ...(localPath === undefined ? {} : { localOnlyBoardPath: localPath }),
68
- now,
69
- operationId: () => crypto.randomUUID(),
70
- quota: { expiresAt: 0, observedAt: 0 },
71
- readGuidance: (role) =>
72
- (role === "worker" ? workerGuidance : reviewerGuidance).pipe(
73
- Effect.mapError((error: HostFailure) => new ServiceUnavailable({ message: error.message })),
74
- ),
75
- refreshQuota: hostQuota(host, now),
76
- stallMinutes: host.stallMinutes,
77
- ...(host.worker === undefined ? {} : { sharedEnvironment: host.worker.sharedEnvironment }),
78
- });
31
+ // Each quota source caches its observation, so a reload reuses the source for an unchanged quota setting.
32
+ const quotas = new Map<FleetHost["quota"], ReturnType<typeof hostQuota>>();
33
+ function refreshQuota(applied: FleetHost) {
34
+ const known = quotas.get(applied.quota);
35
+ if (known !== undefined) {
36
+ return known;
37
+ }
38
+ const created = hostQuota(applied, now);
39
+ quotas.set(applied.quota, created);
40
+ return created;
41
+ }
42
+ function configuration({ guidance, host: applied }: AppliedConfig): FleetConfiguration {
43
+ return {
44
+ areaMergeWaitMs: applied.areaMergeWaitMs,
45
+ deliveryBacklog: applied.backlog,
46
+ executionConcurrency: applied.concurrency,
47
+ launch: applied.launch,
48
+ ...(localPath === undefined ? {} : { localOnlyBoardPath: localPath }),
49
+ now,
50
+ ...(applied.openPullRequests === undefined ? {} : { openPullRequests: applied.openPullRequests }),
51
+ operationId: () => crypto.randomUUID(),
52
+ quota: { expiresAt: 0, observedAt: 0 },
53
+ readGuidance: (role) => guidance[role].pipe(Effect.mapError((error) => new ServiceUnavailable({ message: error.message }))),
54
+ refreshQuota: refreshQuota(applied),
55
+ stallMinutes: applied.stallMinutes,
56
+ ...(applied.worker === undefined ? {} : { sharedEnvironment: applied.worker.sharedEnvironment }),
57
+ };
58
+ }
59
+ return FleetPolicy.of({ ...configuration(yield* live.current), current: Effect.map(live.current, configuration) });
79
60
  }),
80
61
  );
81
62
  }
@@ -107,23 +88,34 @@ export function hostSql(host: FleetHost) {
107
88
  export function fleetHostLayer<TProvider, TMain>(
108
89
  host: FleetHost,
109
90
  parts: {
110
- readonly board?: Layer.Layer<BoardGateway | ReportInspection, unknown, MainSource>;
111
- readonly integrations?: Layer.Layer<FleetIntegrations, unknown, MainSource>;
91
+ readonly board?: Layer.Layer<BoardGateway | ReportInspection, unknown, MainSource | GithubApi>;
92
+ readonly github?: Layer.Layer<GithubApi>;
93
+ readonly integrations?: Layer.Layer<FleetIntegrations, unknown, MainSource | GithubApi>;
112
94
  readonly main: Layer.Layer<MainSource, TMain>;
113
95
  readonly policy?: Layer.Layer<FleetPolicy>;
114
96
  readonly provider: Layer.Layer<SessionTransport, TProvider>;
115
97
  },
98
+ config: Layer.Layer<LiveConfig, unknown> = staticConfig(host),
116
99
  ) {
117
100
  const repository = postgresFleetRepository(host.namespace);
118
101
  const sessions = SessionService.layer.pipe(
119
102
  Layer.provideMerge([fleetSessionJournal.pipe(Layer.provide(repository)), providerHealth.pipe(Layer.provide(parts.provider))]),
120
103
  );
104
+ const github = parts.github ?? githubApiLayer.pipe(Layer.provide(NodeServices.layer));
121
105
  const board = (parts.board ?? hostReportBoard(host)).pipe(Layer.provide(parts.main), Layer.provide(NodeServices.layer));
122
106
  const integrations = (parts.integrations ?? hostIntegrations(host)).pipe(Layer.provide(parts.main));
123
107
  return Fleet.layer.pipe(
124
108
  Layer.provideMerge(
125
- Layer.mergeAll(repository, sessions, board, parts.policy ?? hostPolicy(host).pipe(Layer.provide(parts.main)), integrations, parts.main),
109
+ Layer.mergeAll(
110
+ repository,
111
+ sessions,
112
+ board,
113
+ parts.policy ?? hostPolicy(host).pipe(Layer.provide([parts.main, config])),
114
+ integrations,
115
+ parts.main,
116
+ ),
126
117
  ),
118
+ Layer.provideMerge(github),
127
119
  Layer.provideMerge(hostSql(host)),
128
120
  );
129
121
  }
@@ -1,4 +1,5 @@
1
1
  import { Stream } from "effect";
2
+ import { ANSWER_RECORDED } from "#attention.ts";
2
3
  import type { FleetError } from "#errors.ts";
3
4
  import type { State } from "#host/waitOutcome.ts";
4
5
 
@@ -12,7 +13,11 @@ export function snapshotStream(snapshots: Stream.Stream<States, FleetError>, ids
12
13
  if (continuous && selected === undefined) {
13
14
  return states;
14
15
  }
15
- selected ??= new Set(states.filter((state) => !["completed", "needs-human", "released"].includes(state.stage)).map((state) => state.workId));
16
+ selected ??= new Set(
17
+ states
18
+ .filter((state) => state.blocker === ANSWER_RECORDED || !["completed", "needs-human", "released"].includes(state.stage))
19
+ .map((state) => state.workId),
20
+ );
16
21
  const selection = selected;
17
22
  return states.filter((state) => selection.has(state.workId));
18
23
  }),
@@ -1,16 +1,33 @@
1
1
  import { Effect, Schema } from "effect";
2
+ import { makeRepository } from "@shivaedev/effect-sql/repository.ts";
2
3
  import { views } from "#engine/views.ts";
3
4
  import type { FleetHost } from "#host/config.ts";
4
- import { recordPayloads } from "#host/recordPayloads.ts";
5
- import { FleetRecord, type FleetViews } from "#model.ts";
6
- import { renderStatus as render } from "./renderStatus.ts";
5
+ import { renderStatus as render } from "#host/renderStatus.ts";
6
+ import { FleetRecord } from "#model.ts";
7
+ import { dispatchStore } from "#storage/dispatchStore.ts";
8
+ import { recordModel } from "#storage/model.ts";
9
+ import { readRecords } from "#storage/readRecords.ts";
10
+ import { recordShape } from "#storage/recordShape.ts";
11
+ import { recordValues } from "#storage/recordValue.ts";
7
12
 
8
- export function renderStatus(current: typeof FleetViews.Type) {
13
+ export function renderStatus(current: Parameters<typeof render>[0]) {
9
14
  return render(current);
10
15
  }
11
16
 
12
17
  export const fleetStatus = Effect.fn("FleetHost.fleetStatus")(function* (host: FleetHost, workId?: string) {
13
- const payloads = yield* recordPayloads(host.namespace, workId);
14
- const records = yield* Effect.forEach(payloads, (payload) => Schema.decodeUnknownEffect(Schema.fromJsonString(FleetRecord))(payload));
15
- return views(records);
18
+ const repository = yield* makeRepository(recordModel(), {
19
+ idColumn: "work_id",
20
+ spanPrefix: "FleetReader",
21
+ tableName: `${host.namespace}_records`,
22
+ });
23
+ const records = yield* readRecords(
24
+ host.namespace,
25
+ Effect.gen(function* () {
26
+ const rows = yield* repository.findMany({ orderBy: { direction: "asc", field: "work_id" }, where: { "work_id": workId } });
27
+ return yield* Schema.decodeUnknownEffect(Schema.Array(FleetRecord))(yield* recordValues(rows, recordShape(), host.namespace));
28
+ }),
29
+ );
30
+ const requests = yield* (yield* dispatchStore(host.namespace)).list(workId);
31
+ const dispatches = requests.filter((request) => request.status !== "completed");
32
+ return dispatches.length === 0 ? views(records) : { ...views(records), dispatches };
16
33
  });
@@ -8,18 +8,22 @@ import { writeStatus } from "#board/writeStatus.ts";
8
8
  import { Health, HealthPublication, HealthSnapshot } from "#engine/health.ts";
9
9
  import { views } from "#engine/views.ts";
10
10
  import { Fleet } from "#fleet.ts";
11
+ import { GithubApi } from "#host/githubApi.ts";
12
+ import type { GithubObservation } from "#host/githubRateLimit.ts";
11
13
  import { executing } from "#model.ts";
12
14
 
13
15
  const { SourceFailure } = diagnosticsApi;
14
16
 
15
17
  class StatusHealth extends Context.Service<StatusHealth, Option.Option<Health["Service"]>>()("Fleet/StatusHealth") {}
18
+ class StatusGithub extends Context.Service<StatusGithub, Effect.Effect<readonly GithubObservation[]>>()("Fleet/StatusGithub") {}
16
19
 
17
- export function statusLayer(root: string, healthConfig?: { readonly concurrency: number; readonly staleAfterMs: number }) {
20
+ export function statusLayer(root: string, healthConfig?: Effect.Effect<{ readonly concurrency: number; readonly staleAfterMs: number }>) {
18
21
  const StatusPublication = defineService({
19
22
  id: "Fleet/StatusPublication",
20
23
  initialize: Effect.gen(function* () {
21
24
  const fleet = yield* Fleet;
22
25
  const health = yield* StatusHealth;
26
+ const github = yield* StatusGithub;
23
27
  const fs = yield* FileSystem.FileSystem;
24
28
  const realRoot = yield* fs.realPath(root);
25
29
  const lock = yield* Semaphore.make(1);
@@ -37,10 +41,12 @@ export function statusLayer(root: string, healthConfig?: { readonly concurrency:
37
41
  ).pipe(Effect.catch((error) => Console.error(`work-fleet: status publication failed: ${error.message}`)));
38
42
  if (healthConfig !== undefined) {
39
43
  const state = health._tag === "Some" ? yield* Ref.get(health.value) : { lastCapacityRejection: null, lastSchedulerPass: null };
44
+ const observations = yield* github;
40
45
  const nextHealth: FleetHealth = {
46
+ ...(observations.length === 0 ? {} : { github: observations }),
41
47
  observedAt: yield* Clock.currentTimeMillis,
42
48
  version: 2,
43
- ...healthConfig,
49
+ ...(yield* healthConfig),
44
50
  ...state,
45
51
  queued: records.filter(({ value }) => value.stage === "prepared").length,
46
52
  running: records.filter(({ value }) => executing(value)).length,
@@ -71,18 +77,28 @@ export function statusLayer(root: string, healthConfig?: { readonly concurrency:
71
77
  readHealth: () => readSnapshot(snapshot),
72
78
  reassign: (...args: Parameters<typeof fleet.reassign>) => after(fleet.reassign(...args)),
73
79
  reconcile: (workId: string) => after(fleet.reconcile(workId)),
80
+ recordResponse: (...args: Parameters<typeof fleet.recordResponse>) => after(fleet.recordResponse(...args)),
74
81
  resolve: (...args: Parameters<typeof fleet.resolve>) => after(fleet.resolve(...args)),
75
82
  };
76
83
  },
77
- requires: [Fleet, FileSystem.FileSystem, StatusHealth],
84
+ requires: [Fleet, FileSystem.FileSystem, StatusHealth, StatusGithub],
78
85
  });
79
86
  return Layer.unwrap(
80
- Effect.map(Effect.serviceOption(Health), (health) =>
87
+ Effect.map(Effect.all([Effect.serviceOption(Health), Effect.serviceOption(GithubApi)]), ([health, github]) =>
81
88
  Layer.unwrap(
82
89
  Effect.map(StatusPublication, ({ readHealth, publishHealth, ...fleet }) =>
83
90
  Layer.mergeAll(Layer.succeed(HealthSnapshot, readHealth()), Layer.succeed(HealthPublication, publishHealth()), Layer.succeed(Fleet, fleet)),
84
91
  ),
85
- ).pipe(Layer.provide(StatusPublication.layer.pipe(Layer.provide(Layer.succeed(StatusHealth, health))))),
92
+ ).pipe(
93
+ Layer.provide(
94
+ StatusPublication.layer.pipe(
95
+ Layer.provide([
96
+ Layer.succeed(StatusHealth, health),
97
+ Layer.succeed(StatusGithub, github._tag === "Some" ? github.value.observations() : Effect.succeed([])),
98
+ ]),
99
+ ),
100
+ ),
101
+ ),
86
102
  ),
87
103
  );
88
104
  }
@@ -1,5 +1,5 @@
1
1
  import * as Schema from "effect/Schema";
2
- import { AttentionOwner, waitingOwner } from "#attention.ts";
2
+ import { ANSWER_RECORDED, AttentionOwner, waitingOwner } from "#attention.ts";
3
3
 
4
4
  export const WAIT_EXIT = { completed: 0, error: 1, released: 3, timeout: 4, waitingDecision: 2 } as const;
5
5
 
@@ -28,6 +28,9 @@ export type WaitState = typeof WaitState.Type;
28
28
  export const State = Schema.Struct({ ...WaitState.fields, workId: Schema.String });
29
29
 
30
30
  export function settled(workId: string, state: WaitState): WaitOutcome | undefined {
31
+ if (state.blocker === ANSWER_RECORDED) {
32
+ return undefined;
33
+ }
31
34
  const owner = waitingOwner(state);
32
35
  const attention = owner === undefined ? "" : ` (waiting on ${owner})`;
33
36
  if (state.stage === "completed") {
@@ -37,7 +40,7 @@ export function settled(workId: string, state: WaitState): WaitOutcome | undefin
37
40
  if (state.stage === "needs-human") {
38
41
  return {
39
42
  code: WAIT_EXIT.waitingDecision,
40
- summary: `${workId} needs-human${attention}: ${state.decision?.reason ?? state.blocker ?? "a Board decision is pending"}`,
43
+ summary: `${workId} needs-human${attention}: ${state.blocker ?? state.decision?.reason ?? "a Board decision is pending"}`,
41
44
  };
42
45
  }
43
46
  if (state.stage === "released") {
package/src/model.ts CHANGED
@@ -2,6 +2,7 @@ import { Schema } from "effect";
2
2
  import { diagnostics } from "@shivaedev/work-board/integration/diagnostics.ts";
3
3
  import { AttentionOwner } from "#attention.ts";
4
4
  import { BoardReport } from "#board/schema.ts";
5
+ import { DispatchRequest } from "#DispatchRequest.ts";
5
6
  import { Checks, Decision, DecisionResponse, Delivery, Review, SupersededDecision, WorkResult } from "#policy.ts";
6
7
  import { Preparation } from "#preparation/schema.ts";
7
8
  import { LaunchSettings, SessionObservation, SessionReceipt } from "#session/schema.ts";
@@ -29,6 +30,7 @@ export const Attempt = Schema.Struct({
29
30
  observationRetries: Schema.optional(Schema.Number),
30
31
  operationId: Schema.String,
31
32
  output: Schema.optional(Schema.String),
33
+ overLimit: Schema.optional(Schema.Boolean),
32
34
  progress: Schema.optional(Schema.Struct({ at: Schema.Number, signature: Schema.String })),
33
35
  prompt: Schema.optional(Schema.String),
34
36
  providerFailures: Schema.optional(Schema.Number),
@@ -74,6 +76,7 @@ const cycleFields = {
74
76
  decisionAcknowledged: Schema.optional(Schema.Boolean),
75
77
  decisionPublished: Schema.optional(Schema.Boolean),
76
78
  deliverable: Schema.optional(Schema.Literal("report")),
79
+ dispatchNow: Schema.optional(Schema.Struct({ ignoreAreas: Schema.Boolean })),
77
80
  integrationRetry: Schema.optional(Schema.Struct({ error: Schema.String, failures: Schema.Number, retryAt: Schema.Number })),
78
81
  launch: Schema.optional(LaunchSettings),
79
82
  launchRetry: Schema.optional(
@@ -101,6 +104,7 @@ export const FleetCycleSnapshot = Schema.Struct({ ...cycleFields, archivedAt: Sc
101
104
  export type FleetCycleSnapshot = typeof FleetCycleSnapshot.Type;
102
105
  export const FleetRecord = Schema.Struct({ ...cycleFields, history: Schema.optional(Schema.Array(FleetCycleSnapshot)), workId: Schema.String });
103
106
  export type FleetRecord = typeof FleetRecord.Type;
107
+ export type DispatchNow = NonNullable<FleetRecord["dispatchNow"]>;
104
108
  export function executing(record: FleetRecord): boolean {
105
109
  return record.attempts.some((attempt) => ["submitting", "accepted", "running"].includes(attempt.status));
106
110
  }
@@ -114,6 +118,7 @@ export const FleetView = Schema.Struct({
114
118
  decisionAcknowledged: Schema.optional(Schema.Boolean),
115
119
  links: Schema.Array(Schema.String),
116
120
  outcome: FleetRecord.fields.outcome,
121
+ overLimit: Schema.optional(Schema.Boolean),
117
122
  sessions: Schema.Array(
118
123
  Schema.Struct({
119
124
  ...SessionReceipt.fields,
@@ -130,6 +135,7 @@ export const FleetView = Schema.Struct({
130
135
  export const FleetViews = Schema.Struct({
131
136
  active: Schema.Array(FleetView),
132
137
  completed: Schema.Array(FleetView),
138
+ dispatches: Schema.optional(Schema.Array(DispatchRequest)),
133
139
  waiting: Schema.Struct({
134
140
  automation: Schema.Array(FleetView),
135
141
  maintainer: Schema.Array(FleetView),
@@ -1,3 +1,3 @@
1
1
  export const NAME = "work-fleet";
2
2
  export const TITLE = "Work Fleet";
3
- export const VERSION = "0.2.1";
3
+ export const VERSION = "0.3.0";
package/src/policy.ts CHANGED
@@ -12,13 +12,17 @@ import type { FleetError } from "#errors.ts";
12
12
  import type { MainObservation, Preparation } from "#preparation/schema.ts";
13
13
  import type { SessionObservation } from "#session/schema.ts";
14
14
  import { type LaunchSettings, SessionReceipt } from "#session/schema.ts";
15
+ import type { OpenPullRequestCurve } from "#storage/model.ts";
15
16
 
17
+ export const Priority = Schema.Literals(["urgent", "high", "normal"]);
18
+ export type Priority = typeof Priority.Type;
16
19
  export const BoardWork = Schema.Struct({
17
20
  approved: Schema.Boolean,
18
21
  areas: Schema.optional(Schema.Array(Schema.String)),
19
22
  context: Schema.String,
20
23
  deliverable: Schema.optional(Schema.Literal("report")),
21
24
  dependsOn: Schema.Array(Schema.String),
25
+ priority: Schema.optional(Priority),
22
26
  revision: Schema.String,
23
27
  sourcePath: Schema.String,
24
28
  status: Schema.optional(Schema.String),
@@ -105,11 +109,14 @@ export const Delivery = Schema.Struct({ head: Schema.String, revision: Schema.St
105
109
  export type Delivery = typeof Delivery.Type;
106
110
  export interface FleetConfiguration {
107
111
  readonly areaMergeWaitMs?: number;
112
+ // A host that reloads its settings serves the configuration each scheduler pass and launch should apply.
113
+ readonly current?: Effect.Effect<FleetConfiguration>;
108
114
  readonly deliveryBacklog?: number;
109
115
  readonly executionConcurrency?: number;
110
116
  readonly launch?: LaunchSettings;
111
117
  readonly localOnlyBoardPath?: string;
112
118
  readonly now: () => number;
119
+ readonly openPullRequests?: OpenPullRequestCurve;
113
120
  readonly operationId: () => string;
114
121
  readonly quota: { readonly available?: number; readonly observedAt: number; readonly expiresAt: number };
115
122
  readonly readGuidance?: (role: "worker" | "reviewer") => Effect.Effect<string | undefined, FleetError>;
@@ -15,6 +15,7 @@ export const CodexCloudConfiguration = Schema.Struct({
15
15
  endpoint: Schema.optional(Schema.String),
16
16
  environmentId: Schema.String.check(Schema.isNonEmpty()),
17
17
  projectId: Schema.optional(Schema.String.check(Schema.isNonEmpty())),
18
+ recoveryGraceMs: Schema.Finite.check(Schema.isGreaterThan(0)),
18
19
  refreshCommand: Schema.optional(Schema.Struct({ args: Schema.Array(Schema.String), command: Schema.String })),
19
20
  requestTimeoutMs: Schema.Finite.check(Schema.isGreaterThan(0)),
20
21
  threadNamePrefix: Schema.optional(Schema.String.check(Schema.isNonEmpty())),
@@ -86,7 +87,7 @@ const CodexCloud = defineService({
86
87
  const adapter = codexAdapter(rpc, {
87
88
  beforeTurn: verifyEnvironment,
88
89
  provisioning: "unknown",
89
- recoveryGraceMs: 5000,
90
+ recoveryGraceMs: config.recoveryGraceMs,
90
91
  threadStart: (input) => threadStart(config, input),
91
92
  });
92
93
  return {
@@ -0,0 +1,19 @@
1
+ import { Effect } from "effect";
2
+ import type { FleetRecord } from "#model.ts";
3
+ import { checkAreas, needsAreaRecords } from "#scheduling/areas.ts";
4
+ import { acquiresExecution, checkBackPressure } from "#scheduling/backPressure.ts";
5
+ import type { AdmissionLimits } from "#storage/model.ts";
6
+
7
+ export const checkLaunchAdmission = Effect.fn("Fleet.checkLaunchAdmission")(function* (
8
+ record: FleetRecord,
9
+ previous: FleetRecord | undefined,
10
+ records: readonly FleetRecord[],
11
+ limits: AdmissionLimits,
12
+ ) {
13
+ yield* checkAreas(record, previous, records, limits);
14
+ yield* checkBackPressure(record, previous, records, limits);
15
+ });
16
+
17
+ export function needsLaunchRecords(record: FleetRecord, previous: FleetRecord | undefined, limits: AdmissionLimits): boolean {
18
+ return needsAreaRecords(record, previous, limits) || (limits.implementers !== undefined && acquiresExecution(record, previous));
19
+ }
@@ -0,0 +1,55 @@
1
+ import { Effect } from "effect";
2
+ import { backlog, executing, type FleetRecord } from "#model.ts";
3
+ import { StorageCapacity } from "#storage/errors.ts";
4
+ import type { AdmissionLimits, OpenPullRequestCurve } from "#storage/model.ts";
5
+
6
+ export function implementerLimit(concurrency: number, curve: OpenPullRequestCurve | undefined, open: number): number {
7
+ if (curve === undefined || (open <= curve.ease && open < curve.max)) {
8
+ return concurrency;
9
+ }
10
+ const floor = Math.min(curve.floor, concurrency);
11
+ if (open >= curve.max) {
12
+ return floor;
13
+ }
14
+ return floor + Math.floor(((concurrency - floor) * (curve.max - open)) / (curve.max - curve.ease));
15
+ }
16
+
17
+ // Reviews, repairs and answers for work that already has a session hold a slot ahead of new implementers while they wait to launch.
18
+ function awaitsMergeWork(record: FleetRecord): boolean {
19
+ return (
20
+ !executing(record)
21
+ && (["reviewing", "repairing"].includes(record.stage)
22
+ || (!["prepared", "completed", "released"].includes(record.stage) && (record.pendingAnswers?.length ?? 0) > 0))
23
+ );
24
+ }
25
+
26
+ export function acquiresExecution(record: FleetRecord, previous: FleetRecord | undefined): boolean {
27
+ return executing(record) && (previous === undefined || !executing(previous));
28
+ }
29
+
30
+ export const checkBackPressure = Effect.fn("Fleet.checkBackPressure")(function* (
31
+ record: FleetRecord,
32
+ previous: FleetRecord | undefined,
33
+ records: readonly FleetRecord[],
34
+ limits: AdmissionLimits,
35
+ ) {
36
+ const implementers = limits.implementers;
37
+ if (implementers === undefined || !acquiresExecution(record, previous)) {
38
+ return;
39
+ }
40
+ const others = records.filter((entry) => entry.workId !== record.workId);
41
+ const running = others.filter(executing).length;
42
+ const waiting = others.filter(awaitsMergeWork).length;
43
+ const open = others.filter(backlog).length;
44
+ const curve = implementers.openPullRequests;
45
+ const limit = implementerLimit(implementers.concurrency, curve, open);
46
+ if (running + waiting < limit) {
47
+ return;
48
+ }
49
+ if (curve !== undefined && limit < implementers.concurrency) {
50
+ return yield* Effect.fail(new StorageCapacity({ kind: "open-pull-requests", limit: curve.max, occupied: open }));
51
+ }
52
+ if (running < implementers.concurrency) {
53
+ return yield* Effect.fail(new StorageCapacity({ kind: "merge-work", limit: implementers.concurrency, occupied: waiting }));
54
+ }
55
+ });
@@ -1,9 +1,14 @@
1
1
  import type { Effect } from "effect";
2
- import type { StorageAdmission } from "#storage/errors.ts";
2
+ import type { StorageAdmission, StorageCapacity } from "#storage/errors.ts";
3
3
  import type { AdmissionLimits } from "#storage/model.ts";
4
4
 
5
5
  export interface FleetStoreOptions<A> {
6
- readonly admission?: (record: A, previous: A | undefined, records: readonly A[], limits: AdmissionLimits) => Effect.Effect<void, StorageAdmission>;
6
+ readonly admission?: (
7
+ record: A,
8
+ previous: A | undefined,
9
+ records: readonly A[],
10
+ limits: AdmissionLimits,
11
+ ) => Effect.Effect<void, StorageAdmission | StorageCapacity>;
7
12
  readonly admissionNeedsRecords?: (record: A, previous: A | undefined, limits: AdmissionLimits) => boolean;
8
13
  readonly backlog?: (record: A) => boolean;
9
14
  readonly executing?: (record: A) => boolean;
@@ -0,0 +1,24 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ import { childTable } from "#storage/recordChildren.ts";
4
+ import { collections, type Shape, shapeColumns, sqlTypes } from "#storage/recordShape.ts";
5
+
6
+ export const addShapeColumns = Effect.fn("FleetStore.addShapeColumns")(function* (namespace: string, before: Shape, after: Shape) {
7
+ const sql = yield* SqlClient.SqlClient;
8
+ const existing = new Map(collections(before).map((collection) => [collection.path.join("."), shapeColumns(collection.shape)]));
9
+ const tables = [
10
+ { columns: shapeColumns(after), existing: shapeColumns(before), table: `${namespace}_records` },
11
+ ...collections(after).map((collection) => ({
12
+ columns: shapeColumns(collection.shape),
13
+ existing: existing.get(collection.path.join(".")) ?? {},
14
+ table: childTable(namespace, collection.path),
15
+ })),
16
+ ];
17
+ for (const { columns, existing: present, table } of tables) {
18
+ for (const [name, kind] of Object.entries(columns)) {
19
+ if (!(name in present)) {
20
+ yield* sql`alter table ${sql(table)} add column ${sql(name)} ${sql.literal(sqlTypes[kind])}`;
21
+ }
22
+ }
23
+ }
24
+ });