@shivaedev/work-fleet 0.5.0 → 0.7.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 (492) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +7 -5
  3. package/dist/DecisionCode.d.ts +1 -1
  4. package/dist/DecisionCode.d.ts.map +1 -1
  5. package/dist/DecisionCode.js +1 -0
  6. package/dist/DecisionCode.js.map +1 -1
  7. package/dist/admit.d.ts +2 -4
  8. package/dist/admit.d.ts.map +1 -1
  9. package/dist/board/acknowledgeDecision.d.ts.map +1 -1
  10. package/dist/board/acknowledgeDecision.js +11 -5
  11. package/dist/board/acknowledgeDecision.js.map +1 -1
  12. package/dist/board/briefRevision.d.ts +1 -1
  13. package/dist/board/briefRevision.d.ts.map +1 -1
  14. package/dist/board/briefRevision.js +1 -1
  15. package/dist/board/briefRevision.js.map +1 -1
  16. package/dist/board/closePublishedDecision.d.ts +22 -0
  17. package/dist/board/closePublishedDecision.d.ts.map +1 -0
  18. package/dist/board/closePublishedDecision.js +41 -0
  19. package/dist/board/closePublishedDecision.js.map +1 -0
  20. package/dist/board/decisionAnswer.d.ts +2 -2
  21. package/dist/board/decisionAnswer.d.ts.map +1 -1
  22. package/dist/board/decisionAnswer.js +8 -8
  23. package/dist/board/decisionAnswer.js.map +1 -1
  24. package/dist/board/decisionReading.js +2 -2
  25. package/dist/board/decisionReading.js.map +1 -1
  26. package/dist/board/documents.d.ts +1 -2
  27. package/dist/board/documents.d.ts.map +1 -1
  28. package/dist/board/documents.js +4 -4
  29. package/dist/board/documents.js.map +1 -1
  30. package/dist/board/fleetField.d.ts +1 -1
  31. package/dist/board/fleetField.d.ts.map +1 -1
  32. package/dist/board/markdown.d.ts.map +1 -1
  33. package/dist/board/markdown.js +6 -5
  34. package/dist/board/markdown.js.map +1 -1
  35. package/dist/board/publish.d.ts +1 -1
  36. package/dist/board/publish.d.ts.map +1 -1
  37. package/dist/board/publish.js +10 -8
  38. package/dist/board/publish.js.map +1 -1
  39. package/dist/board/publishReport.js +2 -2
  40. package/dist/board/publishReport.js.map +1 -1
  41. package/dist/board/readDocument.js +1 -1
  42. package/dist/board/readDocument.js.map +1 -1
  43. package/dist/board/readPass.d.ts +1 -1
  44. package/dist/board/readPass.d.ts.map +1 -1
  45. package/dist/board/readPass.js +1 -1
  46. package/dist/board/readPass.js.map +1 -1
  47. package/dist/board/reportIdentity.js +1 -1
  48. package/dist/board/reportIdentity.js.map +1 -1
  49. package/dist/board/reportLinks.js +1 -1
  50. package/dist/board/reportLinks.js.map +1 -1
  51. package/dist/board/schema.d.ts +13 -13
  52. package/dist/board/schema.js +2 -2
  53. package/dist/board/schema.js.map +1 -1
  54. package/dist/board/upgradeDecisionClosure.d.ts +5 -0
  55. package/dist/board/upgradeDecisionClosure.d.ts.map +1 -0
  56. package/dist/board/upgradeDecisionClosure.js +46 -0
  57. package/dist/board/upgradeDecisionClosure.js.map +1 -0
  58. package/dist/board/workRevision.js +2 -2
  59. package/dist/board/workRevision.js.map +1 -1
  60. package/dist/board/writeHealth.d.ts +1 -1
  61. package/dist/board/writeHealth.d.ts.map +1 -1
  62. package/dist/board/writeHealth.js +1 -1
  63. package/dist/board/writeHealth.js.map +1 -1
  64. package/dist/board/writePublished.d.ts +1 -1
  65. package/dist/board/writePublished.d.ts.map +1 -1
  66. package/dist/board/writePublished.js +5 -1
  67. package/dist/board/writePublished.js.map +1 -1
  68. package/dist/cli.js +11 -5
  69. package/dist/cli.js.map +1 -1
  70. package/dist/engine/abandonStalled.d.ts +530 -569
  71. package/dist/engine/abandonStalled.d.ts.map +1 -1
  72. package/dist/engine/admissionOrder.d.ts +4 -8
  73. package/dist/engine/admissionOrder.d.ts.map +1 -1
  74. package/dist/engine/applyResolution.d.ts +4 -8
  75. package/dist/engine/applyResolution.d.ts.map +1 -1
  76. package/dist/engine/approveBrief.d.ts +6 -12
  77. package/dist/engine/approveBrief.d.ts.map +1 -1
  78. package/dist/engine/authorizeResolution.d.ts +528 -565
  79. package/dist/engine/authorizeResolution.d.ts.map +1 -1
  80. package/dist/engine/authorizeResolution.js +1 -1
  81. package/dist/engine/authorizeResolution.js.map +1 -1
  82. package/dist/engine/boardBrief.d.ts +7 -12
  83. package/dist/engine/boardBrief.d.ts.map +1 -1
  84. package/dist/engine/boardBrief.js +3 -10
  85. package/dist/engine/boardBrief.js.map +1 -1
  86. package/dist/engine/capacityRetry.d.ts +1715 -1828
  87. package/dist/engine/capacityRetry.d.ts.map +1 -1
  88. package/dist/engine/closeDecisions.d.ts +4 -8
  89. package/dist/engine/closeDecisions.d.ts.map +1 -1
  90. package/dist/engine/completeBoardWork.d.ts +4 -8
  91. package/dist/engine/completeBoardWork.d.ts.map +1 -1
  92. package/dist/engine/completeReport.d.ts +277 -284
  93. package/dist/engine/completeReport.d.ts.map +1 -1
  94. package/dist/engine/continueCommand.d.ts +2 -4
  95. package/dist/engine/continueCommand.d.ts.map +1 -1
  96. package/dist/engine/continueWorker.d.ts +4 -8
  97. package/dist/engine/continueWorker.d.ts.map +1 -1
  98. package/dist/engine/decisionCopy.d.ts +15 -0
  99. package/dist/engine/decisionCopy.d.ts.map +1 -0
  100. package/dist/engine/decisionCopy.js +44 -0
  101. package/dist/engine/decisionCopy.js.map +1 -0
  102. package/dist/engine/deliverPendingAnswers.d.ts +534 -577
  103. package/dist/engine/deliverPendingAnswers.d.ts.map +1 -1
  104. package/dist/engine/dispatchCommand.d.ts +3 -6
  105. package/dist/engine/dispatchCommand.d.ts.map +1 -1
  106. package/dist/engine/dispatchCommand.js +4 -29
  107. package/dist/engine/dispatchCommand.js.map +1 -1
  108. package/dist/engine/dispatchFailure.d.ts +9391 -0
  109. package/dist/engine/dispatchFailure.d.ts.map +1 -0
  110. package/dist/engine/dispatchFailure.js +24 -0
  111. package/dist/engine/dispatchFailure.js.map +1 -0
  112. package/dist/engine/ensureDecisionOwner.d.ts +4 -8
  113. package/dist/engine/ensureDecisionOwner.d.ts.map +1 -1
  114. package/dist/engine/ensurePublication.d.ts +4 -8
  115. package/dist/engine/ensurePublication.d.ts.map +1 -1
  116. package/dist/engine/failureCode.js +1 -1
  117. package/dist/engine/failureCode.js.map +1 -1
  118. package/dist/engine/health.d.ts +1 -1
  119. package/dist/engine/health.d.ts.map +1 -1
  120. package/dist/engine/inspectRenewal.d.ts +4 -8
  121. package/dist/engine/inspectRenewal.d.ts.map +1 -1
  122. package/dist/engine/launchInput.d.ts +2 -4
  123. package/dist/engine/launchInput.d.ts.map +1 -1
  124. package/dist/engine/launchReceipt.d.ts +2 -4
  125. package/dist/engine/launchReceipt.d.ts.map +1 -1
  126. package/dist/engine/makeAdopt.d.ts +4 -8
  127. package/dist/engine/makeAdopt.d.ts.map +1 -1
  128. package/dist/engine/makeAdvance.d.ts +2 -4
  129. package/dist/engine/makeAdvance.d.ts.map +1 -1
  130. package/dist/engine/makeDeliver.d.ts +4 -8
  131. package/dist/engine/makeDeliver.d.ts.map +1 -1
  132. package/dist/engine/makeDeliver.js +5 -1
  133. package/dist/engine/makeDeliver.js.map +1 -1
  134. package/dist/engine/makeHuman.d.ts +4 -8
  135. package/dist/engine/makeHuman.d.ts.map +1 -1
  136. package/dist/engine/makeLaunch.d.ts +4 -8
  137. package/dist/engine/makeLaunch.d.ts.map +1 -1
  138. package/dist/engine/makeObserve.d.ts +4 -8
  139. package/dist/engine/makeObserve.d.ts.map +1 -1
  140. package/dist/engine/makeReview.d.ts +4 -8
  141. package/dist/engine/makeReview.d.ts.map +1 -1
  142. package/dist/engine/makeState.d.ts +534 -568
  143. package/dist/engine/makeState.d.ts.map +1 -1
  144. package/dist/engine/makeState.js +18 -3
  145. package/dist/engine/makeState.js.map +1 -1
  146. package/dist/engine/makeValidate.d.ts +4 -8
  147. package/dist/engine/makeValidate.d.ts.map +1 -1
  148. package/dist/engine/mergeReadiness.d.ts +536 -581
  149. package/dist/engine/mergeReadiness.d.ts.map +1 -1
  150. package/dist/engine/mergeReadiness.js +1 -1
  151. package/dist/engine/mergeReadiness.js.map +1 -1
  152. package/dist/engine/missingBoardWork.d.ts +9936 -0
  153. package/dist/engine/missingBoardWork.d.ts.map +1 -0
  154. package/dist/engine/missingBoardWork.js +17 -0
  155. package/dist/engine/missingBoardWork.js.map +1 -0
  156. package/dist/engine/observeDeliveryFailure.d.ts +530 -569
  157. package/dist/engine/observeDeliveryFailure.d.ts.map +1 -1
  158. package/dist/engine/observeRenewal.d.ts +6 -12
  159. package/dist/engine/observeRenewal.d.ts.map +1 -1
  160. package/dist/engine/obtainReview.d.ts +2 -4
  161. package/dist/engine/obtainReview.d.ts.map +1 -1
  162. package/dist/engine/obtainReview.js +1 -1
  163. package/dist/engine/obtainReview.js.map +1 -1
  164. package/dist/engine/operationRecord.d.ts +26 -52
  165. package/dist/engine/operationRecord.d.ts.map +1 -1
  166. package/dist/engine/pendingAcknowledgements.d.ts.map +1 -1
  167. package/dist/engine/pendingAcknowledgements.js +3 -1
  168. package/dist/engine/pendingAcknowledgements.js.map +1 -1
  169. package/dist/engine/persistTerminalReceipts.d.ts +4 -8
  170. package/dist/engine/persistTerminalReceipts.d.ts.map +1 -1
  171. package/dist/engine/prepareCommand.d.ts +2 -4
  172. package/dist/engine/prepareCommand.d.ts.map +1 -1
  173. package/dist/engine/queueAnswerCommand.d.ts +2 -4
  174. package/dist/engine/queueAnswerCommand.d.ts.map +1 -1
  175. package/dist/engine/readOrContinueReview.d.ts +2 -4
  176. package/dist/engine/readOrContinueReview.d.ts.map +1 -1
  177. package/dist/engine/readOrContinueReview.js +1 -1
  178. package/dist/engine/readOrContinueReview.js.map +1 -1
  179. package/dist/engine/readResolution.d.ts +1 -1
  180. package/dist/engine/readResolution.js +1 -1
  181. package/dist/engine/readResolution.js.map +1 -1
  182. package/dist/engine/readRetry.d.ts +1177 -1255
  183. package/dist/engine/readRetry.d.ts.map +1 -1
  184. package/dist/engine/reassignCommand.d.ts +2 -4
  185. package/dist/engine/reassignCommand.d.ts.map +1 -1
  186. package/dist/engine/reconcileAttempt.d.ts +2 -4
  187. package/dist/engine/reconcileAttempt.d.ts.map +1 -1
  188. package/dist/engine/reconcileCommand.d.ts +2 -4
  189. package/dist/engine/reconcileCommand.d.ts.map +1 -1
  190. package/dist/engine/reconcileCommand.js +2 -1
  191. package/dist/engine/reconcileCommand.js.map +1 -1
  192. package/dist/engine/recordResponseCommand.d.ts +2 -4
  193. package/dist/engine/recordResponseCommand.d.ts.map +1 -1
  194. package/dist/engine/recoverStall.d.ts +530 -569
  195. package/dist/engine/recoverStall.d.ts.map +1 -1
  196. package/dist/engine/recoverUnobservable.d.ts +530 -569
  197. package/dist/engine/recoverUnobservable.d.ts.map +1 -1
  198. package/dist/engine/refreshBrief.d.ts +1177 -1255
  199. package/dist/engine/refreshBrief.d.ts.map +1 -1
  200. package/dist/engine/refreshReviewResult.d.ts +4 -8
  201. package/dist/engine/refreshReviewResult.d.ts.map +1 -1
  202. package/dist/engine/releaseClosedPreparation.d.ts +530 -569
  203. package/dist/engine/releaseClosedPreparation.d.ts.map +1 -1
  204. package/dist/engine/releaseExecution.d.ts +530 -569
  205. package/dist/engine/releaseExecution.d.ts.map +1 -1
  206. package/dist/engine/releaseFinishedWork.d.ts +2 -4
  207. package/dist/engine/releaseFinishedWork.d.ts.map +1 -1
  208. package/dist/engine/releaseFinishedWork.js +0 -1
  209. package/dist/engine/releaseFinishedWork.js.map +1 -1
  210. package/dist/engine/repository.d.ts +24 -48
  211. package/dist/engine/repository.d.ts.map +1 -1
  212. package/dist/engine/repository.js +1 -1
  213. package/dist/engine/repository.js.map +1 -1
  214. package/dist/engine/requestConflictRepair.d.ts +530 -569
  215. package/dist/engine/requestConflictRepair.d.ts.map +1 -1
  216. package/dist/engine/requestRework.d.ts +4 -8
  217. package/dist/engine/requestRework.d.ts.map +1 -1
  218. package/dist/engine/resolveCommand.d.ts +2 -4
  219. package/dist/engine/resolveCommand.d.ts.map +1 -1
  220. package/dist/engine/resolveExecution.d.ts +530 -569
  221. package/dist/engine/resolveExecution.d.ts.map +1 -1
  222. package/dist/engine/resumeAttempt.d.ts +530 -569
  223. package/dist/engine/resumeAttempt.d.ts.map +1 -1
  224. package/dist/engine/retireUnacknowledged.d.ts +4 -8
  225. package/dist/engine/retireUnacknowledged.d.ts.map +1 -1
  226. package/dist/engine/retryTerminal.d.ts +528 -565
  227. package/dist/engine/retryTerminal.d.ts.map +1 -1
  228. package/dist/engine/saveLaunch.d.ts +533 -574
  229. package/dist/engine/saveLaunch.d.ts.map +1 -1
  230. package/dist/engine/saveLaunch.js +16 -2
  231. package/dist/engine/saveLaunch.js.map +1 -1
  232. package/dist/engine/scheduler.d.ts +4 -8
  233. package/dist/engine/scheduler.d.ts.map +1 -1
  234. package/dist/engine/scheduler.js +4 -1
  235. package/dist/engine/scheduler.js.map +1 -1
  236. package/dist/engine/sessionCleanup.d.ts +4 -8
  237. package/dist/engine/sessionCleanup.d.ts.map +1 -1
  238. package/dist/engine/settleMergedDelivery.d.ts +530 -569
  239. package/dist/engine/settleMergedDelivery.d.ts.map +1 -1
  240. package/dist/engine/situations/choices.d.ts +20 -0
  241. package/dist/engine/situations/choices.d.ts.map +1 -0
  242. package/dist/engine/situations/choices.js +21 -0
  243. package/dist/engine/situations/choices.js.map +1 -0
  244. package/dist/engine/situations/service.d.ts +60 -0
  245. package/dist/engine/situations/service.d.ts.map +1 -0
  246. package/dist/engine/situations/service.js +51 -0
  247. package/dist/engine/situations/service.js.map +1 -0
  248. package/dist/engine/situations/stop.d.ts +25 -0
  249. package/dist/engine/situations/stop.d.ts.map +1 -0
  250. package/dist/engine/situations/stop.js +25 -0
  251. package/dist/engine/situations/stop.js.map +1 -0
  252. package/dist/engine/situations/work.d.ts +114 -0
  253. package/dist/engine/situations/work.d.ts.map +1 -0
  254. package/dist/engine/situations/work.js +91 -0
  255. package/dist/engine/situations/work.js.map +1 -0
  256. package/dist/engine/steerBrief.d.ts +532 -573
  257. package/dist/engine/steerBrief.d.ts.map +1 -1
  258. package/dist/engine/submissionFailure.d.ts +526 -561
  259. package/dist/engine/submissionFailure.d.ts.map +1 -1
  260. package/dist/engine/submitLaunch.d.ts +528 -565
  261. package/dist/engine/submitLaunch.d.ts.map +1 -1
  262. package/dist/engine/threadNames.js +1 -1
  263. package/dist/engine/threadNames.js.map +1 -1
  264. package/dist/engine/workerReport.d.ts +7 -13
  265. package/dist/engine/workerReport.d.ts.map +1 -1
  266. package/dist/exposeFailure.js +1 -1
  267. package/dist/exposeFailure.js.map +1 -1
  268. package/dist/fleet.d.ts +26 -52
  269. package/dist/fleet.d.ts.map +1 -1
  270. package/dist/fleet.js +1 -1
  271. package/dist/fleet.js.map +1 -1
  272. package/dist/host/actionCommands.d.ts +10 -10
  273. package/dist/host/actionCommands.d.ts.map +1 -1
  274. package/dist/host/actionCommands.js +6 -6
  275. package/dist/host/actionCommands.js.map +1 -1
  276. package/dist/host/admission.d.ts +4 -8
  277. package/dist/host/admission.d.ts.map +1 -1
  278. package/dist/host/answerWork.d.ts +4 -5
  279. package/dist/host/answerWork.d.ts.map +1 -1
  280. package/dist/host/cliOptions.d.ts +5 -1
  281. package/dist/host/cliOptions.d.ts.map +1 -1
  282. package/dist/host/cliOptions.js +6 -4
  283. package/dist/host/cliOptions.js.map +1 -1
  284. package/dist/host/commands.d.ts +1 -1
  285. package/dist/host/commands.d.ts.map +1 -1
  286. package/dist/host/configSettings.d.ts +5 -5
  287. package/dist/host/daemon.d.ts +133 -150
  288. package/dist/host/daemon.d.ts.map +1 -1
  289. package/dist/host/daemon.js +7 -3
  290. package/dist/host/daemon.js.map +1 -1
  291. package/dist/host/daemonClient.d.ts +1054 -1072
  292. package/dist/host/daemonClient.d.ts.map +1 -1
  293. package/dist/host/daemonClient.js +1 -1
  294. package/dist/host/daemonClient.js.map +1 -1
  295. package/dist/host/daemonContract.d.ts +146 -172
  296. package/dist/host/daemonContract.d.ts.map +1 -1
  297. package/dist/host/daemonContract.js +1 -1
  298. package/dist/host/daemonContract.js.map +1 -1
  299. package/dist/host/daemonDiagnostics.js +1 -1
  300. package/dist/host/daemonDiagnostics.js.map +1 -1
  301. package/dist/host/daemonHandlers.d.ts +1 -1
  302. package/dist/host/daemonHandlers.d.ts.map +1 -1
  303. package/dist/host/daemonPort.d.ts +6 -0
  304. package/dist/host/daemonPort.d.ts.map +1 -0
  305. package/dist/host/daemonPort.js +40 -0
  306. package/dist/host/daemonPort.js.map +1 -0
  307. package/dist/host/daemonSnapshots.d.ts +1 -1
  308. package/dist/host/daemonSnapshots.d.ts.map +1 -1
  309. package/dist/host/daemonSnapshots.js +1 -1
  310. package/dist/host/daemonSnapshots.js.map +1 -1
  311. package/dist/host/fleetStatus.d.ts +5 -5
  312. package/dist/host/follow.d.ts +1 -0
  313. package/dist/host/follow.d.ts.map +1 -1
  314. package/dist/host/follow.js +10 -4
  315. package/dist/host/follow.js.map +1 -1
  316. package/dist/host/followCommands.d.ts +2 -2
  317. package/dist/host/followCommands.d.ts.map +1 -1
  318. package/dist/host/followCommands.js +4 -2
  319. package/dist/host/followCommands.js.map +1 -1
  320. package/dist/host/githubApi.js +1 -1
  321. package/dist/host/githubApi.js.map +1 -1
  322. package/dist/host/githubDelivery.js +3 -1
  323. package/dist/host/githubDelivery.js.map +1 -1
  324. package/dist/host/healthLayer.js +1 -1
  325. package/dist/host/healthLayer.js.map +1 -1
  326. package/dist/host/integrations.js +1 -1
  327. package/dist/host/integrations.js.map +1 -1
  328. package/dist/host/mainSource.js +1 -1
  329. package/dist/host/mainSource.js.map +1 -1
  330. package/dist/host/providerHealth.js +1 -1
  331. package/dist/host/providerHealth.js.map +1 -1
  332. package/dist/host/quota.js +1 -1
  333. package/dist/host/quota.js.map +1 -1
  334. package/dist/host/recordDecisionResponse.d.ts +3 -2
  335. package/dist/host/recordDecisionResponse.d.ts.map +1 -1
  336. package/dist/host/recordDecisionResponse.js +1 -1
  337. package/dist/host/recordDecisionResponse.js.map +1 -1
  338. package/dist/host/releaseWork.d.ts +6 -9
  339. package/dist/host/releaseWork.d.ts.map +1 -1
  340. package/dist/host/releaseWork.js +2 -2
  341. package/dist/host/releaseWork.js.map +1 -1
  342. package/dist/host/renderStatus.d.ts +4 -1
  343. package/dist/host/renderStatus.d.ts.map +1 -1
  344. package/dist/host/renderStatus.js +6 -6
  345. package/dist/host/renderStatus.js.map +1 -1
  346. package/dist/host/reportBoard.js +1 -1
  347. package/dist/host/reportBoard.js.map +1 -1
  348. package/dist/host/runtime.d.ts +2 -2
  349. package/dist/host/runtime.d.ts.map +1 -1
  350. package/dist/host/runtime.js +1 -1
  351. package/dist/host/runtime.js.map +1 -1
  352. package/dist/host/statusLayer.js +2 -2
  353. package/dist/host/statusLayer.js.map +1 -1
  354. package/dist/host/watch.d.ts.map +1 -1
  355. package/dist/host/watch.js +1 -1
  356. package/dist/host/watch.js.map +1 -1
  357. package/dist/model.d.ts +9 -12
  358. package/dist/model.d.ts.map +1 -1
  359. package/dist/model.js +1 -2
  360. package/dist/model.js.map +1 -1
  361. package/dist/operations.d.ts +57 -99
  362. package/dist/operations.d.ts.map +1 -1
  363. package/dist/packageInfo.d.ts +1 -1
  364. package/dist/packageInfo.js +1 -1
  365. package/dist/policy.d.ts +3 -2
  366. package/dist/policy.d.ts.map +1 -1
  367. package/dist/policy.js +2 -1
  368. package/dist/policy.js.map +1 -1
  369. package/dist/prompt/briefEdit.js +1 -1
  370. package/dist/prompt/briefEdit.js.map +1 -1
  371. package/dist/providers/codexCloud.js +1 -1
  372. package/dist/providers/codexCloud.js.map +1 -1
  373. package/dist/providers/codexLocal.js +1 -1
  374. package/dist/providers/codexLocal.js.map +1 -1
  375. package/dist/qualifyDependencies.d.ts +2 -4
  376. package/dist/qualifyDependencies.d.ts.map +1 -1
  377. package/dist/reportFileDirectory.js +1 -1
  378. package/dist/reportFileDirectory.js.map +1 -1
  379. package/dist/scheduling/admission.d.ts +6 -12
  380. package/dist/scheduling/admission.d.ts.map +1 -1
  381. package/dist/scheduling/areas.d.ts +7 -12
  382. package/dist/scheduling/areas.d.ts.map +1 -1
  383. package/dist/scheduling/areas.js +2 -2
  384. package/dist/scheduling/areas.js.map +1 -1
  385. package/dist/scheduling/backPressure.d.ts +6 -12
  386. package/dist/scheduling/backPressure.d.ts.map +1 -1
  387. package/dist/session/schema.d.ts +1 -1
  388. package/dist/session/service.js +1 -1
  389. package/dist/session/service.js.map +1 -1
  390. package/dist/storage/fleetMigrations.d.ts.map +1 -1
  391. package/dist/storage/fleetMigrations.js +10 -0
  392. package/dist/storage/fleetMigrations.js.map +1 -1
  393. package/dist/storage/makeFleetTransaction.d.ts +1 -1
  394. package/dist/storage/makeFleetTransaction.d.ts.map +1 -1
  395. package/dist/storage/makeFleetTransaction.js +1 -1
  396. package/dist/storage/makeFleetTransaction.js.map +1 -1
  397. package/dist/storage/makeForeignReservations.d.ts.map +1 -1
  398. package/dist/storage/makeForeignReservations.js +16 -4
  399. package/dist/storage/makeForeignReservations.js.map +1 -1
  400. package/dist/storage/model.d.ts +1 -0
  401. package/dist/storage/model.d.ts.map +1 -1
  402. package/package.json +8 -8
  403. package/src/DecisionCode.ts +1 -0
  404. package/src/board/acknowledgeDecision.ts +11 -5
  405. package/src/board/briefRevision.ts +2 -2
  406. package/src/board/closePublishedDecision.ts +51 -0
  407. package/src/board/decisionAnswer.ts +11 -9
  408. package/src/board/decisionReading.ts +3 -3
  409. package/src/board/documents.ts +5 -6
  410. package/src/board/fleetField.ts +1 -1
  411. package/src/board/markdown.ts +6 -5
  412. package/src/board/publish.ts +10 -8
  413. package/src/board/publishReport.ts +2 -2
  414. package/src/board/readDocument.ts +1 -1
  415. package/src/board/readPass.ts +2 -2
  416. package/src/board/reportIdentity.ts +1 -1
  417. package/src/board/reportLinks.ts +1 -1
  418. package/src/board/schema.ts +2 -2
  419. package/src/board/upgradeDecisionClosure.ts +61 -0
  420. package/src/board/workRevision.ts +2 -2
  421. package/src/board/writeHealth.ts +2 -2
  422. package/src/board/writePublished.ts +13 -4
  423. package/src/cli.ts +13 -5
  424. package/src/engine/authorizeResolution.ts +1 -1
  425. package/src/engine/boardBrief.ts +11 -19
  426. package/src/engine/decisionCopy.ts +63 -0
  427. package/src/engine/dispatchCommand.ts +4 -36
  428. package/src/engine/dispatchFailure.ts +25 -0
  429. package/src/engine/failureCode.ts +1 -1
  430. package/src/engine/health.ts +1 -1
  431. package/src/engine/makeDeliver.ts +5 -1
  432. package/src/engine/makeState.ts +24 -5
  433. package/src/engine/mergeReadiness.ts +0 -2
  434. package/src/engine/missingBoardWork.ts +24 -0
  435. package/src/engine/obtainReview.ts +1 -1
  436. package/src/engine/pendingAcknowledgements.ts +9 -1
  437. package/src/engine/readOrContinueReview.ts +1 -1
  438. package/src/engine/readResolution.ts +2 -2
  439. package/src/engine/reconcileCommand.ts +7 -1
  440. package/src/engine/releaseFinishedWork.ts +0 -1
  441. package/src/engine/repository.ts +1 -1
  442. package/src/engine/saveLaunch.ts +27 -2
  443. package/src/engine/scheduler.ts +4 -1
  444. package/src/engine/situations/choices.ts +36 -0
  445. package/src/engine/situations/service.ts +82 -0
  446. package/src/engine/situations/stop.ts +60 -0
  447. package/src/engine/situations/work.ts +94 -0
  448. package/src/engine/threadNames.ts +1 -1
  449. package/src/exposeFailure.ts +1 -1
  450. package/src/fleet.ts +1 -1
  451. package/src/host/actionCommands.ts +6 -6
  452. package/src/host/cliOptions.ts +10 -5
  453. package/src/host/daemon.ts +7 -3
  454. package/src/host/daemonClient.ts +1 -1
  455. package/src/host/daemonContract.ts +1 -1
  456. package/src/host/daemonDiagnostics.ts +1 -1
  457. package/src/host/daemonPort.ts +50 -0
  458. package/src/host/daemonSnapshots.ts +1 -1
  459. package/src/host/follow.ts +16 -5
  460. package/src/host/followCommands.ts +4 -2
  461. package/src/host/githubApi.ts +1 -1
  462. package/src/host/githubDelivery.ts +3 -1
  463. package/src/host/healthLayer.ts +1 -1
  464. package/src/host/integrations.ts +1 -1
  465. package/src/host/mainSource.ts +1 -1
  466. package/src/host/providerHealth.ts +1 -1
  467. package/src/host/quota.ts +1 -1
  468. package/src/host/recordDecisionResponse.ts +1 -1
  469. package/src/host/releaseWork.ts +2 -2
  470. package/src/host/renderStatus.ts +6 -7
  471. package/src/host/reportBoard.ts +1 -1
  472. package/src/host/runtime.ts +1 -1
  473. package/src/host/statusLayer.ts +3 -3
  474. package/src/host/watch.ts +4 -1
  475. package/src/model.ts +1 -2
  476. package/src/packageInfo.ts +1 -1
  477. package/src/policy.ts +2 -1
  478. package/src/prompt/briefEdit.ts +1 -1
  479. package/src/providers/codexCloud.ts +1 -1
  480. package/src/providers/codexLocal.ts +1 -1
  481. package/src/reportFileDirectory.ts +1 -1
  482. package/src/scheduling/areas.ts +2 -2
  483. package/src/session/service.ts +1 -1
  484. package/src/storage/fleetMigrations.ts +10 -0
  485. package/src/storage/makeFleetTransaction.ts +2 -2
  486. package/src/storage/makeForeignReservations.ts +15 -4
  487. package/src/storage/model.ts +1 -1
  488. package/dist/engine/releaseOnly.d.ts +0 -3
  489. package/dist/engine/releaseOnly.d.ts.map +0 -1
  490. package/dist/engine/releaseOnly.js +0 -19
  491. package/dist/engine/releaseOnly.js.map +0 -1
  492. package/src/engine/releaseOnly.ts +0 -24
@@ -1,14 +1,11 @@
1
1
  import { Effect, Result } from "effect";
2
- import { Forbidden } from "@shivaedev/platform/errors/taxonomy.ts";
3
- import { waitingOwner } from "#attention.ts";
4
2
  import { approveDispatchedBrief } from "#engine/approveBrief.ts";
5
3
  import { authorizeBriefContext } from "#engine/boardBrief.ts";
4
+ import { dispatchFailure } from "#engine/dispatchFailure.ts";
6
5
  import { failureCode } from "#engine/failureCode.ts";
7
- import { failureMessage } from "#engine/failureMessage.ts";
8
- import { failureOwner } from "#engine/failureOwner.ts";
9
6
  import type { makeLaunch } from "#engine/makeLaunch.ts";
10
7
  import type { EngineState } from "#engine/makeState.ts";
11
- import { clearIntegrationRetry, readRetry, retryPending } from "#engine/readRetry.ts";
8
+ import { clearIntegrationRetry, retryPending } from "#engine/readRetry.ts";
12
9
  import { refreshBrief } from "#engine/refreshBrief.ts";
13
10
  import { releaseClosedPreparation } from "#engine/releaseClosedPreparation.ts";
14
11
  import type { DispatchNow, FleetRecord } from "#model.ts";
@@ -57,26 +54,7 @@ export function dispatchCommand(state: EngineState, launch: ReturnType<typeof ma
57
54
  ) {
58
55
  stored = yield* save(stored, { ...stored.value, preparation: assessment.preparation });
59
56
  }
60
- return yield* launch(stored, "worker", stored.value.prompt).pipe(
61
- Effect.catch((error) =>
62
- Effect.gen(function* () {
63
- const current = yield* load(workId);
64
- if (current.value.stage !== "prepared") {
65
- return current;
66
- }
67
- const waiting = {
68
- ...current.value,
69
- admissionReady: !(error instanceof Forbidden),
70
- attentionOwner: failureOwner(error),
71
- blocker: failureMessage(error),
72
- };
73
- if (!sameWait(current.value, waiting)) {
74
- yield* save(current, waiting);
75
- }
76
- return yield* Effect.fail(error);
77
- }),
78
- ),
79
- );
57
+ return yield* launch(stored, "worker", stored.value.prompt);
80
58
  });
81
59
  return Effect.fn("Fleet.dispatch")(function* (workId: string, prompt?: string, now?: DispatchNow) {
82
60
  const current = yield* load(workId);
@@ -88,12 +66,7 @@ export function dispatchCommand(state: EngineState, launch: ReturnType<typeof ma
88
66
  }
89
67
  return yield* dispatchPrepared(workId, prompt, now).pipe(
90
68
  Effect.flatMap((updated) => clearIntegrationRetry(state, updated)),
91
- Effect.catch((error) =>
92
- Effect.gen(function* () {
93
- const retrying = yield* readRetry(state, yield* load(workId), error);
94
- return retrying === undefined ? yield* Effect.fail(error) : retrying;
95
- }),
96
- ),
69
+ Effect.catch((error) => dispatchFailure(state, workId, error)),
97
70
  );
98
71
  });
99
72
  }
@@ -105,8 +78,3 @@ function requestedNow(record: FleetRecord, now: DispatchNow | undefined): FleetR
105
78
  }
106
79
  return { ...record, dispatchNow: now };
107
80
  }
108
-
109
- // Every scheduler pass retries waiting work, so rewriting an unchanged wait would make each pass write and notify once per waiter.
110
- function sameWait(current: FleetRecord, waiting: FleetRecord) {
111
- return current.blocker === waiting.blocker && current.admissionReady === waiting.admissionReady && current.attentionOwner === waitingOwner(waiting);
112
- }
@@ -0,0 +1,25 @@
1
+ import { Effect } from "effect";
2
+ import { waitingOwner } from "#attention.ts";
3
+ import { failureMessage } from "#engine/failureMessage.ts";
4
+ import { failureOwner } from "#engine/failureOwner.ts";
5
+ import type { EngineState } from "#engine/makeState.ts";
6
+ import { releaseMissingBoardWork } from "#engine/missingBoardWork.ts";
7
+ import { readRetry } from "#engine/readRetry.ts";
8
+
9
+ export const dispatchFailure = Effect.fn("Fleet.dispatchFailure")(function* <E>(state: EngineState, workId: string, error: E) {
10
+ const current = yield* state.load(workId);
11
+ const released = yield* releaseMissingBoardWork(state, current, error);
12
+ if (released !== undefined) {
13
+ return released;
14
+ }
15
+ const retrying = yield* readRetry(state, current, error);
16
+ if (retrying !== undefined) {
17
+ return retrying;
18
+ }
19
+ const waiting = { ...current.value, attentionOwner: failureOwner(error), blocker: failureMessage(error) };
20
+ // Unchanged waits must not write and wake every subscriber on every scheduler pass.
21
+ if (current.value.stage === "prepared" && (current.value.blocker !== waiting.blocker || current.value.attentionOwner !== waitingOwner(waiting))) {
22
+ yield* state.save(current, waiting);
23
+ }
24
+ return yield* Effect.fail(error);
25
+ });
@@ -24,7 +24,7 @@ export function failureCode(error: unknown): DecisionCode {
24
24
  return error.code ?? `session-${error.reason}`;
25
25
  }
26
26
  if (error instanceof BoardFailure) {
27
- return error.code ?? "board-failure";
27
+ return error.code === "board-item-missing" ? "board-failure" : (error.code ?? "board-failure");
28
28
  }
29
29
  return "integration-failure";
30
30
  }
@@ -1,5 +1,5 @@
1
1
  import { Clock, Context, Effect, Ref } from "effect";
2
- import type { CapacityRejection, FleetHealth, SourceFailure } from "@shivaedev/work-board/integration/diagnostics.ts";
2
+ import type { CapacityRejection, FleetHealth, SourceFailure } from "@shivaedev/work-board/server/integration/diagnostics.ts";
3
3
  import type { SessionObservation } from "#session/schema.ts";
4
4
 
5
5
  export interface HealthState {
@@ -2,6 +2,7 @@ import { Effect, Result } from "effect";
2
2
  import { validateChecks, validateReview } from "#completion.ts";
3
3
  import { authorizeBriefContext } from "#engine/boardBrief.ts";
4
4
  import { failureCode } from "#engine/failureCode.ts";
5
+ import { failureOwner } from "#engine/failureOwner.ts";
5
6
  import type { EngineState } from "#engine/makeState.ts";
6
7
  import { awaitHumanMerge, expireMergeAreas } from "#engine/mergeReadiness.ts";
7
8
  import { observeDeliveryFailure } from "#engine/observeDeliveryFailure.ts";
@@ -54,7 +55,7 @@ function deniedDelivery(state: EngineState, stored: Versioned<FleetRecord>, work
54
55
  error.message,
55
56
  "Restore approval for work that is still needed, or release it",
56
57
  undefined,
57
- "maintainer",
58
+ failureOwner(error),
58
59
  )
59
60
  : state.save(stored, { ...stored.value, blocker: error.message, mergeReadyAt: undefined, mergeReadyHead: undefined }),
60
61
  ),
@@ -72,6 +73,9 @@ const observeDelivery = Effect.fn("Fleet.observeDelivery")(function* (
72
73
  ) {
73
74
  const record = stored.value;
74
75
  const observed = yield* state.integrations.delivery(result).pipe(Effect.result);
76
+ if (Result.isFailure(observed) && failureCode(observed.failure) === "pr-closed") {
77
+ yield* state.store.releaseForeign(result.pr);
78
+ }
75
79
  if (Result.isSuccess(observed) && observed.success !== undefined && !executing(record)) {
76
80
  return yield* settleMergedDelivery(state, stored, result, observed.success, deliveryPending(record));
77
81
  }
@@ -2,16 +2,18 @@ import { Effect } from "effect";
2
2
  import { NotFound } from "@shivaedev/platform/errors/taxonomy.ts";
3
3
  import { type AttentionOwner, waitingOwner } from "#attention.ts";
4
4
  import type { DecisionCode } from "#DecisionCode.ts";
5
+ import { closeDecisions } from "#engine/closeDecisions.ts";
5
6
  import { originalWork } from "#engine/originalWork.ts";
6
7
  import { ReportInspection } from "#engine/ReportInspection.ts";
7
8
  import { FleetRepository } from "#engine/repository.ts";
8
9
  import type { Attempt, FleetRecord } from "#model.ts";
9
- import { BoardGateway, type BoardWork, type Decision, type FleetConfiguration, FleetIntegrations, FleetPolicy } from "#policy.ts";
10
+ import { type BoardFailure, BoardGateway, type BoardWork, type Decision, type FleetConfiguration, FleetIntegrations, FleetPolicy } from "#policy.ts";
10
11
  import { DEFAULT_AREA_MERGE_WAIT_MS } from "#scheduling/areas.ts";
11
12
  import type { SessionReceipt } from "#session/schema.ts";
12
13
  import { SessionService } from "#session/service.ts";
13
14
  import type { AdmissionLimits, Versioned } from "#storage/model.ts";
14
15
  export interface LaunchAdmission {
16
+ readonly areaWaiters: readonly string[];
15
17
  readonly ignoreAreas?: boolean;
16
18
  readonly implementer?: boolean;
17
19
  readonly overLimit?: boolean;
@@ -52,7 +54,7 @@ export const makeState = Effect.gen(function* () {
52
54
  worker?: SessionReceipt,
53
55
  attentionOwner: AttentionOwner = "orchestrator",
54
56
  publicationWork?: BoardWork,
55
- ) {
57
+ ): Effect.fn.Return<Versioned<FleetRecord>, Effect.Error<ReturnType<typeof save>> | BoardFailure> {
56
58
  const value: Decision = {
57
59
  attentionOwner,
58
60
  code,
@@ -63,6 +65,8 @@ export const makeState = Effect.gen(function* () {
63
65
  recommendation,
64
66
  ...(worker === undefined ? {} : { worker }),
65
67
  };
68
+ const previous = stored.value.decision?.published;
69
+ const superseded = stored.value.supersededDecisions ?? [];
66
70
  const updated = yield* save(stored, {
67
71
  ...stored.value,
68
72
  attentionOwner,
@@ -71,18 +75,33 @@ export const makeState = Effect.gen(function* () {
71
75
  decisionPublished: false,
72
76
  launchRetry: undefined,
73
77
  stage: "needs-human",
78
+ supersededDecisions:
79
+ previous === undefined || superseded.some((receipt) => receipt.published.questionId === previous.questionId)
80
+ ? stored.value.supersededDecisions
81
+ : [...superseded, { published: previous, supersededAt: policy.now() }],
74
82
  });
75
83
  const published = yield* board.decision(stored.value.workId, value, publicationWork ?? originalWork(stored.value));
76
- return yield* save(updated, { ...updated.value, decision: { ...value, published }, decisionPublished: true });
84
+ return yield* save(updated, { ...updated.value, decision: { ...value, published }, decisionPublished: true }).pipe(
85
+ Effect.flatMap(closeDecisions(state)),
86
+ );
77
87
  });
78
- return { board, current, decision, integrations, launching, launchScope, load, policy, reportInspection, save, sessions, store };
88
+ const state = { board, current, decision, integrations, launching, launchScope, load, policy, reportInspection, save, sessions, store };
89
+ return state;
79
90
  });
80
91
  export type EngineState = Effect.Success<typeof makeState>;
81
92
 
82
93
  function launchLimits(policy: FleetConfiguration, admission: LaunchAdmission): AdmissionLimits {
83
94
  const concurrency = admission.overLimit ? undefined : policy.executionConcurrency;
84
95
  return {
85
- ...(admission.ignoreAreas ? {} : { scheduling: { areaMergeWaitMs: policy.areaMergeWaitMs ?? DEFAULT_AREA_MERGE_WAIT_MS, now: policy.now() } }),
96
+ ...(admission.ignoreAreas
97
+ ? {}
98
+ : {
99
+ scheduling: {
100
+ areaMergeWaitMs: policy.areaMergeWaitMs ?? DEFAULT_AREA_MERGE_WAIT_MS,
101
+ now: policy.now(),
102
+ waiters: admission.areaWaiters,
103
+ },
104
+ }),
86
105
  ...(admission.quota.available === undefined ? {} : { quota: { available: admission.quota.available, observedAt: admission.quota.observedAt } }),
87
106
  ...(concurrency === undefined ? {} : { maxExecuting: concurrency }),
88
107
  ...(admission.role !== "worker" || admission.overLimit || policy.deliveryBacklog === undefined ? {} : { maxBacklog: policy.deliveryBacklog }),
@@ -31,8 +31,6 @@ export const awaitHumanMerge = Effect.fn("Fleet.awaitHumanMerge")(function* (
31
31
  "reviewed-pr-ready",
32
32
  "Reviewed PR is ready to merge",
33
33
  "Merge the reviewed, green PR, or choose retry with an overall response to request changes on the same branch and PR",
34
- undefined,
35
- "maintainer",
36
34
  );
37
35
  });
38
36
 
@@ -0,0 +1,24 @@
1
+ import { Effect } from "effect";
2
+ import type { EngineState } from "#engine/makeState.ts";
3
+ import { releaseFinishedWork } from "#engine/releaseFinishedWork.ts";
4
+ import { executing, type FleetRecord } from "#model.ts";
5
+ import { BoardFailure } from "#policy.ts";
6
+ import type { Versioned } from "#storage/model.ts";
7
+
8
+ export function missingBoardItem(error: unknown, workId?: string): boolean {
9
+ return error instanceof BoardFailure && error.code === "board-item-missing" && (workId === undefined || error.workId === workId);
10
+ }
11
+
12
+ export const releaseMissingBoardWork = Effect.fn("Fleet.releaseMissingBoardWork")(function* (
13
+ state: EngineState,
14
+ stored: Versioned<FleetRecord>,
15
+ error: unknown,
16
+ ) {
17
+ const record = stored.value;
18
+ if (!missingBoardItem(error, record.workId) || ["completed", "released"].includes(record.stage) || executing(record)) {
19
+ return undefined;
20
+ }
21
+ const released = yield* releaseFinishedWork(state, stored, `Board item no longer exists: ${record.workId}`);
22
+ yield* Effect.logInfo("Fleet released missing Board item").pipe(Effect.annotateLogs({ workId: record.workId }));
23
+ return released;
24
+ });
@@ -78,7 +78,7 @@ export function obtainReview(state: EngineState) {
78
78
  mergeReadyAt: undefined,
79
79
  mergeReadyHead: undefined,
80
80
  },
81
- { quota, role: "reviewer" },
81
+ { areaWaiters: [], quota, role: "reviewer" },
82
82
  );
83
83
  const input = {
84
84
  access: "read-only",
@@ -9,8 +9,15 @@ export function pendingAcknowledgements(record: FleetRecord) {
9
9
  readonly input: BoardDecisionAcknowledgement;
10
10
  }[] = [];
11
11
  const cycles = [...(record.history ?? []), record];
12
+ const answered = new Set(
13
+ cycles.flatMap((value) =>
14
+ (value.responses ?? []).flatMap((response) =>
15
+ response.action !== undefined && response.published !== undefined ? [response.published.questionId] : [],
16
+ ),
17
+ ),
18
+ );
12
19
  for (const [cycle, value] of cycles.entries()) {
13
- pending.push(...supersededAcknowledgements(value, cycle));
20
+ pending.push(...supersededAcknowledgements(value, cycle).filter((entry) => !answered.has(entry.input.decision.questionId)));
14
21
  for (const [response, receipt] of (value.responses ?? []).entries()) {
15
22
  if (
16
23
  receipt.action !== undefined
@@ -28,6 +35,7 @@ export function pendingAcknowledgements(record: FleetRecord) {
28
35
  if (
29
36
  "archivedAt" in value
30
37
  && value.decision?.published !== undefined
38
+ && !answered.has(value.decision.published.questionId)
31
39
  && !value.decisionAcknowledged
32
40
  && value.decision.boardAcknowledgementDisposition === undefined
33
41
  ) {
@@ -66,7 +66,7 @@ function continueReview(state: EngineState) {
66
66
  { ...policy, quota },
67
67
  board.get,
68
68
  );
69
- yield* save(stored, { ...stored.value, attempts: [...stored.value.attempts, attempt] }, { quota, role: "reviewer" });
69
+ yield* save(stored, { ...stored.value, attempts: [...stored.value.attempts, attempt] }, { areaWaiters: [], quota, role: "reviewer" });
70
70
  yield* sessions
71
71
  .continue({ access: "read-only", operationId: attempt.operationId, prompt, sessionId: receipt.sessionId, settings })
72
72
  .pipe(
@@ -1,7 +1,7 @@
1
1
  import { Effect } from "effect";
2
2
  import { BadRequest, Conflict } from "@shivaedev/platform/errors/taxonomy.ts";
3
- import type { RecordedResponse } from "@shivaedev/work-board/integration/responses.ts";
4
- import { releaseOnly } from "#engine/releaseOnly.ts";
3
+ import type { RecordedResponse } from "@shivaedev/work-board/server/integration/responses.ts";
4
+ import { releaseOnly } from "#engine/decisionCopy.ts";
5
5
  import type { BoardGateway, Decision } from "#policy.ts";
6
6
 
7
7
  export const readResolution = Effect.fn("Fleet.readResolution")(function* (
@@ -6,6 +6,7 @@ import { failureMessage } from "#engine/failureMessage.ts";
6
6
  import { failureOwner } from "#engine/failureOwner.ts";
7
7
  import type { makeAdvance } from "#engine/makeAdvance.ts";
8
8
  import type { EngineState } from "#engine/makeState.ts";
9
+ import { releaseMissingBoardWork } from "#engine/missingBoardWork.ts";
9
10
  import { persistTerminalReceipts } from "#engine/persistTerminalReceipts.ts";
10
11
  import { clearIntegrationRetry, readRetry, retryPending } from "#engine/readRetry.ts";
11
12
  import { refreshBrief } from "#engine/refreshBrief.ts";
@@ -67,7 +68,12 @@ export function reconcileCommand(state: EngineState, advance: ReturnType<typeof
67
68
  }
68
69
  return yield* advance(workId).pipe(
69
70
  Effect.flatMap((updated) => clearIntegrationRetry(state, updated)),
70
- Effect.catch((error) => handleFailure(workId, error)),
71
+ Effect.catch((error) =>
72
+ load(workId).pipe(
73
+ Effect.flatMap((stored) => releaseMissingBoardWork(state, stored, error)),
74
+ Effect.flatMap((released) => (released === undefined ? handleFailure(workId, error) : Effect.succeed(released))),
75
+ ),
76
+ ),
71
77
  Effect.flatMap(completeBoardWork(state)),
72
78
  );
73
79
  });
@@ -10,7 +10,6 @@ export function releaseFinishedWork(state: EngineState, stored: Versioned<FleetR
10
10
  return state
11
11
  .save(stored, {
12
12
  ...record,
13
- admissionReady: false,
14
13
  attentionOwner: undefined,
15
14
  blocker: undefined,
16
15
  decision: undefined,
@@ -1,6 +1,6 @@
1
1
  import { Context, Effect, Layer } from "effect";
2
2
  import { SqlClient } from "effect/sql";
3
- import { defineService } from "@shivaedev/effect-service/define-service.ts";
3
+ import { defineService } from "@shivaedev/effect-service/defineService.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";
@@ -1,13 +1,15 @@
1
1
  import { Effect } from "effect";
2
2
  import type { EngineState, LaunchAdmission } from "#engine/makeState.ts";
3
+ import { missingBoardItem } from "#engine/missingBoardWork.ts";
3
4
  import type { Attempt, FleetRecord } from "#model.ts";
4
5
  import type { BoardWork } from "#policy.ts";
6
+ import { qualifyDependencies } from "#qualifyDependencies.ts";
7
+ import { DEFAULT_AREA_MERGE_WAIT_MS, holdsAreas } from "#scheduling/areas.ts";
5
8
  import type { Versioned } from "#storage/model.ts";
6
9
 
7
10
  function launched(record: FleetRecord, attempt: Attempt): FleetRecord {
8
11
  return {
9
12
  ...record,
10
- admissionReady: true,
11
13
  attempts: [...record.attempts, attempt],
12
14
  blocker: undefined,
13
15
  launchRetry: undefined,
@@ -28,8 +30,10 @@ export const saveLaunch = Effect.fn("Fleet.saveLaunch")(function* (
28
30
  launch: Pick<LaunchAdmission, "quota" | "role"> & { readonly priority: BoardWork["priority"] },
29
31
  ) {
30
32
  const implementer = stored.value.stage === "prepared";
33
+ const ignoreAreas = implementer && stored.value.dispatchNow?.ignoreAreas === true;
31
34
  const admission: LaunchAdmission = {
32
- ignoreAreas: implementer && stored.value.dispatchNow?.ignoreAreas === true,
35
+ areaWaiters: ignoreAreas || !stored.value.areas?.length ? [] : yield* areaWaiters(state, stored.value),
36
+ ignoreAreas,
33
37
  implementer,
34
38
  quota: launch.quota,
35
39
  role: launch.role,
@@ -43,3 +47,24 @@ export const saveLaunch = Effect.fn("Fleet.saveLaunch")(function* (
43
47
  ),
44
48
  );
45
49
  });
50
+
51
+ const areaWaiters = Effect.fn("Fleet.areaWaiters")(function* (state: EngineState, record: FleetRecord) {
52
+ const policy = yield* state.current;
53
+ if (holdsAreas(record, policy.now(), policy.areaMergeWaitMs ?? DEFAULT_AREA_MERGE_WAIT_MS)) {
54
+ return [];
55
+ }
56
+ const records = (yield* state.store.list()).map(({ value }) => value);
57
+ const index = records.findIndex((entry) => entry.workId === record.workId);
58
+ const waiting = records.slice(0, index).filter((entry) => entry.stage === "prepared" && entry.areas?.some((area) => record.areas?.includes(area)));
59
+ return yield* Effect.filter(waiting, (entry) =>
60
+ state.board.get(entry.workId).pipe(
61
+ Effect.flatMap((work) =>
62
+ qualifyDependencies(work.dependsOn, records, state.board.get).pipe(
63
+ Effect.as(work.approved),
64
+ Effect.catchTag("Forbidden", () => Effect.succeed(false)),
65
+ ),
66
+ ),
67
+ Effect.catchTag("BoardFailure", (error) => (missingBoardItem(error) ? Effect.succeed(false) : Effect.fail(error))),
68
+ ),
69
+ ).pipe(Effect.map((entries) => entries.map((entry) => entry.workId)));
70
+ });
@@ -1,4 +1,4 @@
1
- import { Effect, Result } from "effect";
1
+ import { Cause, Effect, Result } from "effect";
2
2
  import { inBoardReadPass, withBoardReadPass } from "#board/readPass.ts";
3
3
  import { boardCompletionAction } from "#engine/completeBoardWork.ts";
4
4
  import { schedulerPassed } from "#engine/health.ts";
@@ -15,6 +15,9 @@ const dispatchRecords = Effect.fn("Fleet.dispatchRecords")(function* (records: r
15
15
  for (const { value } of prepared) {
16
16
  const result = yield* fleet.dispatch(value.workId).pipe(Effect.result);
17
17
  dispatched.push(result);
18
+ if (Result.isFailure(result)) {
19
+ yield* Effect.logWarning("Fleet dispatch failed", Cause.fail(result.failure)).pipe(Effect.annotateLogs({ workId: value.workId }));
20
+ }
18
21
  if ((Result.isSuccess(result) && result.success.value.launchRetry !== undefined) || (yield* fleet.hasLaunchRetry())) {
19
22
  break;
20
23
  }
@@ -0,0 +1,36 @@
1
+ export interface Choice {
2
+ readonly label: string;
3
+ readonly outcome: string;
4
+ }
5
+
6
+ export interface Situation {
7
+ readonly details?: boolean;
8
+ readonly happened: string;
9
+ readonly question?: string;
10
+ readonly recommendation: string;
11
+ readonly release?: Choice;
12
+ readonly retry?: Choice;
13
+ }
14
+
15
+ export const RELEASE: Choice = {
16
+ label: "Stop and hand back",
17
+ outcome: "Fleet stops working on this task and hands it back to you. An open PR stays open.",
18
+ };
19
+ export const TRY_AGAIN: Choice = { label: "Try again", outcome: "Fleet repeats the step that stopped and continues the same work." };
20
+ export const RUN_AGAIN: Choice = { label: "Run the step again", outcome: "Fleet starts the step again and continues the same work." };
21
+ export const FRESH_WORKER: Choice = {
22
+ label: "Start a fresh worker",
23
+ outcome: "Fleet starts a new worker session with the same task. An existing branch and PR stay in use.",
24
+ };
25
+ export const CORRECT_REPORT: Choice = {
26
+ label: "Ask for a corrected report",
27
+ outcome: "Fleet asks the same worker to send its final report again in the expected format.",
28
+ };
29
+
30
+ export function blocked(happened: string, recommendation: string): Situation {
31
+ return { details: true, happened, recommendation, retry: TRY_AGAIN };
32
+ }
33
+
34
+ export function stopOnly(happened: string, recommendation: string): Situation {
35
+ return { happened, recommendation };
36
+ }
@@ -0,0 +1,82 @@
1
+ import type { DecisionCode } from "#DecisionCode.ts";
2
+ import { blocked, FRESH_WORKER, RUN_AGAIN, type Situation, TRY_AGAIN } from "#engine/situations/choices.ts";
3
+
4
+ export const serviceSituations = {
5
+ "board-failure": blocked(
6
+ "Fleet could not read or update the Board.",
7
+ "Fleet needs the Board files readable again. Fix the cause in the details, then let Fleet try again.",
8
+ ),
9
+ "fleet-denied": blocked(
10
+ "Fleet is not allowed to take the next step.",
11
+ "Fleet needs the blocker in the details resolved. Then let Fleet try again, or stop here.",
12
+ ),
13
+ "fleet-integration": blocked(
14
+ "A service Fleet depends on is unavailable or not set up.",
15
+ "Fleet needs that service working. Fix it, then let Fleet try again, or stop here.",
16
+ ),
17
+ "fleet-invalid": blocked("Fleet received data it cannot use.", "Fix the problem in the details, then let Fleet try again, or stop here."),
18
+ "fleet-missing": blocked(
19
+ "Fleet could not find something this work needs.",
20
+ "Restore what the details name, then let Fleet try again, or stop here.",
21
+ ),
22
+ "fleet-stale": blocked(
23
+ "Something changed while Fleet was working on this task.",
24
+ "Fleet recommends trying again from the current state. Stop here if the task should not go on.",
25
+ ),
26
+ "integration-failure": blocked(
27
+ "Fleet hit an unexpected error.",
28
+ "Check the details. If the cause is fixed, let Fleet try again. Otherwise stop here.",
29
+ ),
30
+ "provider-quota-unavailable": {
31
+ happened: "The worker service has no usage quota left for Fleet.",
32
+ recommendation: "Fleet needs fresh quota to start workers. Try again once quota is available.",
33
+ retry: { label: "Try again", outcome: "Fleet checks the quota again and starts the work once quota is available." },
34
+ },
35
+ "session-active-turn": {
36
+ happened: "The worker was still busy with an earlier step, so Fleet could not send the next one.",
37
+ recommendation: "Fleet recommends trying again once the worker is free.",
38
+ retry: { label: "Try again", outcome: "Fleet sends the step to the same worker again." },
39
+ },
40
+ "session-active-turn-exhausted": {
41
+ happened: "The worker stayed busy with an earlier step through several attempts.",
42
+ recommendation: "Fleet recommends starting over with a fresh worker.",
43
+ retry: FRESH_WORKER,
44
+ },
45
+ "session-ambiguous": {
46
+ details: true,
47
+ happened: "Fleet lost contact with the worker service and cannot tell whether the last step started.",
48
+ recommendation: "Fleet recommends trying again once the worker service is reachable. Fleet checks what already ran before it sends anything.",
49
+ retry: { label: "Try again", outcome: "Fleet checks what the worker already did and continues from there." },
50
+ },
51
+ "session-persistence": blocked(
52
+ "Fleet could not save the state of the worker's run.",
53
+ "Fleet needs its database working. Fix the cause in the details, then let Fleet try again.",
54
+ ),
55
+ "session-protocol": blocked(
56
+ "The worker service sent an answer Fleet does not understand.",
57
+ "Check the details. Let Fleet try again once the cause is fixed, or stop here.",
58
+ ),
59
+ "session-queue-full": {
60
+ happened: "The worker service is too busy to accept new work.",
61
+ recommendation: "Fleet recommends trying again later.",
62
+ retry: TRY_AGAIN,
63
+ },
64
+ "session-rejected": blocked(
65
+ "The worker service rejected Fleet's request.",
66
+ "Check the details. Let Fleet try again once the cause is fixed, or stop here.",
67
+ ),
68
+ "session-stalled": {
69
+ happened: "The worker stopped making progress, and nudging and interrupting it did not help.",
70
+ recommendation: "Fleet recommends starting over with a fresh worker.",
71
+ retry: FRESH_WORKER,
72
+ },
73
+ "session-turn-missing": {
74
+ happened: "The worker's run can no longer be found, even after Fleet resumed it once.",
75
+ recommendation: "Fleet recommends running the step again.",
76
+ retry: RUN_AGAIN,
77
+ },
78
+ "session-unavailable": blocked(
79
+ "Fleet could not reach the worker service.",
80
+ "Fleet needs the worker service reachable. Let Fleet try again once it is back, or stop here.",
81
+ ),
82
+ } satisfies Partial<Record<DecisionCode, Situation>>;
@@ -0,0 +1,60 @@
1
+ import type { DecisionCode } from "#DecisionCode.ts";
2
+ import { type Situation, stopOnly } from "#engine/situations/choices.ts";
3
+
4
+ export const stopSituations = {
5
+ "checks-result-invalid": stopOnly(
6
+ "Fleet could not read check results because this work has no valid PR or commit.",
7
+ "Trying again cannot fix this. Stop here so the task can be prepared again with a valid PR.",
8
+ ),
9
+ "delivery-pr-required": stopOnly(
10
+ "Fleet has no valid GitHub PR for this work.",
11
+ "Trying again cannot fix this. Stop here, check who owns the branch, and prepare the task again.",
12
+ ),
13
+ "duplicate-turns": stopOnly(
14
+ "The worker service shows several runs for the same step, so Fleet cannot tell which result is right.",
15
+ "Fleet cannot pick a result itself. Stop here once every one of those runs has finished.",
16
+ ),
17
+ "foreign-pr": stopOnly(
18
+ "The reported PR belongs to another repository.",
19
+ "Fleet cannot move a PR between repositories. Stop here so the task can be prepared again in the right repository.",
20
+ ),
21
+ "incomplete-context": {
22
+ details: true,
23
+ happened: "The task needs information the worker cannot reach.",
24
+ recommendation:
25
+ "Trying again cannot fill in the missing information. Stop here, change the task to use data from the repository, and prepare it again.",
26
+ },
27
+ "incomplete-observation": {
28
+ details: true,
29
+ happened: "Fleet could not get a complete view of the Board or the repository.",
30
+ recommendation: "Fleet cannot continue from an incomplete view. Stop here so the task can be prepared again.",
31
+ },
32
+ "no-change-checks-unconfigured": stopOnly(
33
+ "The worker changed nothing, and this Fleet setup cannot check a result without changes.",
34
+ "Trying again cannot verify this result here. Stop here so the task can run where such results can be checked.",
35
+ ),
36
+ "not-ancestor": stopOnly(
37
+ "The main branch no longer contains the commit this work was prepared on.",
38
+ "Fleet cannot move the work onto the new history. Stop here so the task can be prepared again on the current main branch.",
39
+ ),
40
+ "relevant-change": stopOnly(
41
+ "Files this work depends on changed on the main branch after it was prepared.",
42
+ "Fleet cannot refresh the preparation itself. Stop here so the task can be prepared again on the current main branch.",
43
+ ),
44
+ "report-published": stopOnly(
45
+ "The report worker published to GitHub, which a report task must not do.",
46
+ "Fleet cannot undo the publication. Stop here and check what was published.",
47
+ ),
48
+ "report-too-large": stopOnly(
49
+ "The worker's report is too large for the Board.",
50
+ "Fleet cannot shorten a finished report. Stop here so a worker can write a shorter report.",
51
+ ),
52
+ "result-identity-changed": stopOnly(
53
+ "The PR or branch for this work was replaced during review.",
54
+ "Fleet cannot take over a different result. Stop here and check the replacement before preparing the task again.",
55
+ ),
56
+ "worker-receipt-missing": stopOnly(
57
+ "Fleet lost the record of which worker run produced this result.",
58
+ "Fleet cannot prove who owns this result. Stop here and check the branch before preparing the task again.",
59
+ ),
60
+ } satisfies Partial<Record<DecisionCode, Situation>>;