@shivaedev/work-fleet 0.6.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.
- package/CHANGELOG.md +17 -0
- package/README.md +6 -4
- package/dist/DecisionCode.d.ts +1 -1
- package/dist/DecisionCode.d.ts.map +1 -1
- package/dist/DecisionCode.js +1 -0
- package/dist/DecisionCode.js.map +1 -1
- package/dist/admit.d.ts +2 -2
- package/dist/board/acknowledgeDecision.d.ts.map +1 -1
- package/dist/board/acknowledgeDecision.js +7 -3
- package/dist/board/acknowledgeDecision.js.map +1 -1
- package/dist/board/briefRevision.d.ts +1 -1
- package/dist/board/briefRevision.d.ts.map +1 -1
- package/dist/board/briefRevision.js +1 -1
- package/dist/board/briefRevision.js.map +1 -1
- package/dist/board/closePublishedDecision.d.ts +22 -0
- package/dist/board/closePublishedDecision.d.ts.map +1 -0
- package/dist/board/closePublishedDecision.js +41 -0
- package/dist/board/closePublishedDecision.js.map +1 -0
- package/dist/board/decisionAnswer.d.ts +2 -2
- package/dist/board/decisionAnswer.d.ts.map +1 -1
- package/dist/board/decisionAnswer.js +8 -8
- package/dist/board/decisionAnswer.js.map +1 -1
- package/dist/board/decisionReading.js +2 -2
- package/dist/board/decisionReading.js.map +1 -1
- package/dist/board/documents.d.ts +1 -2
- package/dist/board/documents.d.ts.map +1 -1
- package/dist/board/documents.js +4 -4
- package/dist/board/documents.js.map +1 -1
- package/dist/board/fleetField.d.ts +1 -1
- package/dist/board/fleetField.d.ts.map +1 -1
- package/dist/board/markdown.d.ts.map +1 -1
- package/dist/board/markdown.js +6 -5
- package/dist/board/markdown.js.map +1 -1
- package/dist/board/publish.d.ts +1 -1
- package/dist/board/publish.d.ts.map +1 -1
- package/dist/board/publish.js +10 -8
- package/dist/board/publish.js.map +1 -1
- package/dist/board/publishReport.js +2 -2
- package/dist/board/publishReport.js.map +1 -1
- package/dist/board/readDocument.js +1 -1
- package/dist/board/readDocument.js.map +1 -1
- package/dist/board/readPass.d.ts +1 -1
- package/dist/board/readPass.d.ts.map +1 -1
- package/dist/board/readPass.js +1 -1
- package/dist/board/readPass.js.map +1 -1
- package/dist/board/reportIdentity.js +1 -1
- package/dist/board/reportIdentity.js.map +1 -1
- package/dist/board/reportLinks.js +1 -1
- package/dist/board/reportLinks.js.map +1 -1
- package/dist/board/schema.d.ts +13 -13
- package/dist/board/schema.js +2 -2
- package/dist/board/schema.js.map +1 -1
- package/dist/board/upgradeDecisionClosure.d.ts +5 -0
- package/dist/board/upgradeDecisionClosure.d.ts.map +1 -0
- package/dist/board/upgradeDecisionClosure.js +46 -0
- package/dist/board/upgradeDecisionClosure.js.map +1 -0
- package/dist/board/workRevision.js +2 -2
- package/dist/board/workRevision.js.map +1 -1
- package/dist/board/writeHealth.d.ts +1 -1
- package/dist/board/writeHealth.d.ts.map +1 -1
- package/dist/board/writeHealth.js +1 -1
- package/dist/board/writeHealth.js.map +1 -1
- package/dist/board/writePublished.d.ts +1 -1
- package/dist/board/writePublished.d.ts.map +1 -1
- package/dist/board/writePublished.js +5 -1
- package/dist/board/writePublished.js.map +1 -1
- package/dist/cli.js +11 -5
- package/dist/cli.js.map +1 -1
- package/dist/engine/abandonStalled.d.ts +530 -533
- package/dist/engine/abandonStalled.d.ts.map +1 -1
- package/dist/engine/admissionOrder.d.ts +4 -4
- package/dist/engine/applyResolution.d.ts +4 -4
- package/dist/engine/approveBrief.d.ts +6 -6
- package/dist/engine/authorizeResolution.d.ts +528 -531
- package/dist/engine/authorizeResolution.d.ts.map +1 -1
- package/dist/engine/authorizeResolution.js +1 -1
- package/dist/engine/authorizeResolution.js.map +1 -1
- package/dist/engine/boardBrief.d.ts +7 -6
- package/dist/engine/boardBrief.d.ts.map +1 -1
- package/dist/engine/boardBrief.js +3 -10
- package/dist/engine/boardBrief.js.map +1 -1
- package/dist/engine/capacityRetry.d.ts +1715 -1724
- package/dist/engine/capacityRetry.d.ts.map +1 -1
- package/dist/engine/closeDecisions.d.ts +4 -4
- package/dist/engine/completeBoardWork.d.ts +4 -4
- package/dist/engine/completeReport.d.ts +277 -280
- package/dist/engine/completeReport.d.ts.map +1 -1
- package/dist/engine/continueCommand.d.ts +2 -2
- package/dist/engine/continueWorker.d.ts +4 -4
- package/dist/engine/decisionCopy.d.ts +15 -0
- package/dist/engine/decisionCopy.d.ts.map +1 -0
- package/dist/engine/decisionCopy.js +44 -0
- package/dist/engine/decisionCopy.js.map +1 -0
- package/dist/engine/deliverPendingAnswers.d.ts +534 -537
- package/dist/engine/deliverPendingAnswers.d.ts.map +1 -1
- package/dist/engine/dispatchCommand.d.ts +2 -2
- package/dist/engine/dispatchCommand.d.ts.map +1 -1
- package/dist/engine/dispatchCommand.js +4 -27
- package/dist/engine/dispatchCommand.js.map +1 -1
- package/dist/engine/dispatchFailure.d.ts +9391 -0
- package/dist/engine/dispatchFailure.d.ts.map +1 -0
- package/dist/engine/dispatchFailure.js +24 -0
- package/dist/engine/dispatchFailure.js.map +1 -0
- package/dist/engine/ensureDecisionOwner.d.ts +4 -4
- package/dist/engine/ensurePublication.d.ts +4 -4
- package/dist/engine/failureCode.js +1 -1
- package/dist/engine/failureCode.js.map +1 -1
- package/dist/engine/health.d.ts +1 -1
- package/dist/engine/health.d.ts.map +1 -1
- package/dist/engine/inspectRenewal.d.ts +4 -4
- package/dist/engine/launchInput.d.ts +2 -2
- package/dist/engine/launchReceipt.d.ts +2 -2
- package/dist/engine/makeAdopt.d.ts +4 -4
- package/dist/engine/makeAdvance.d.ts +2 -2
- package/dist/engine/makeDeliver.d.ts +4 -4
- package/dist/engine/makeDeliver.d.ts.map +1 -1
- package/dist/engine/makeDeliver.js +5 -1
- package/dist/engine/makeDeliver.js.map +1 -1
- package/dist/engine/makeHuman.d.ts +4 -4
- package/dist/engine/makeLaunch.d.ts +4 -4
- package/dist/engine/makeObserve.d.ts +4 -4
- package/dist/engine/makeReview.d.ts +4 -4
- package/dist/engine/makeState.d.ts +533 -536
- package/dist/engine/makeState.d.ts.map +1 -1
- package/dist/engine/makeState.js +9 -2
- package/dist/engine/makeState.js.map +1 -1
- package/dist/engine/makeValidate.d.ts +4 -4
- package/dist/engine/mergeReadiness.d.ts +536 -539
- package/dist/engine/mergeReadiness.d.ts.map +1 -1
- package/dist/engine/mergeReadiness.js +1 -1
- package/dist/engine/mergeReadiness.js.map +1 -1
- package/dist/engine/missingBoardWork.d.ts +9936 -0
- package/dist/engine/missingBoardWork.d.ts.map +1 -0
- package/dist/engine/missingBoardWork.js +17 -0
- package/dist/engine/missingBoardWork.js.map +1 -0
- package/dist/engine/observeDeliveryFailure.d.ts +530 -533
- package/dist/engine/observeDeliveryFailure.d.ts.map +1 -1
- package/dist/engine/observeRenewal.d.ts +6 -6
- package/dist/engine/obtainReview.d.ts +2 -2
- package/dist/engine/operationRecord.d.ts +26 -26
- package/dist/engine/persistTerminalReceipts.d.ts +4 -4
- package/dist/engine/prepareCommand.d.ts +2 -2
- package/dist/engine/queueAnswerCommand.d.ts +2 -2
- package/dist/engine/readOrContinueReview.d.ts +2 -2
- package/dist/engine/readResolution.d.ts +1 -1
- package/dist/engine/readResolution.js +1 -1
- package/dist/engine/readResolution.js.map +1 -1
- package/dist/engine/readRetry.d.ts +1177 -1183
- package/dist/engine/readRetry.d.ts.map +1 -1
- package/dist/engine/reassignCommand.d.ts +2 -2
- package/dist/engine/reconcileAttempt.d.ts +2 -2
- package/dist/engine/reconcileCommand.d.ts +2 -2
- package/dist/engine/reconcileCommand.d.ts.map +1 -1
- package/dist/engine/reconcileCommand.js +2 -1
- package/dist/engine/reconcileCommand.js.map +1 -1
- package/dist/engine/recordResponseCommand.d.ts +2 -2
- package/dist/engine/recoverStall.d.ts +530 -533
- package/dist/engine/recoverStall.d.ts.map +1 -1
- package/dist/engine/recoverUnobservable.d.ts +530 -533
- package/dist/engine/recoverUnobservable.d.ts.map +1 -1
- package/dist/engine/refreshBrief.d.ts +1177 -1183
- package/dist/engine/refreshBrief.d.ts.map +1 -1
- package/dist/engine/refreshReviewResult.d.ts +4 -4
- package/dist/engine/releaseClosedPreparation.d.ts +530 -533
- package/dist/engine/releaseClosedPreparation.d.ts.map +1 -1
- package/dist/engine/releaseExecution.d.ts +530 -533
- package/dist/engine/releaseExecution.d.ts.map +1 -1
- package/dist/engine/releaseFinishedWork.d.ts +2 -2
- package/dist/engine/repository.d.ts +24 -24
- package/dist/engine/repository.js +1 -1
- package/dist/engine/repository.js.map +1 -1
- package/dist/engine/requestConflictRepair.d.ts +530 -533
- package/dist/engine/requestConflictRepair.d.ts.map +1 -1
- package/dist/engine/requestRework.d.ts +4 -4
- package/dist/engine/resolveCommand.d.ts +2 -2
- package/dist/engine/resolveExecution.d.ts +530 -533
- package/dist/engine/resolveExecution.d.ts.map +1 -1
- package/dist/engine/resumeAttempt.d.ts +530 -533
- package/dist/engine/resumeAttempt.d.ts.map +1 -1
- package/dist/engine/retireUnacknowledged.d.ts +4 -4
- package/dist/engine/retryTerminal.d.ts +528 -531
- package/dist/engine/retryTerminal.d.ts.map +1 -1
- package/dist/engine/saveLaunch.d.ts +532 -535
- package/dist/engine/saveLaunch.d.ts.map +1 -1
- package/dist/engine/saveLaunch.js +2 -1
- package/dist/engine/saveLaunch.js.map +1 -1
- package/dist/engine/scheduler.d.ts +4 -4
- package/dist/engine/scheduler.d.ts.map +1 -1
- package/dist/engine/scheduler.js +4 -1
- package/dist/engine/scheduler.js.map +1 -1
- package/dist/engine/sessionCleanup.d.ts +4 -4
- package/dist/engine/settleMergedDelivery.d.ts +530 -533
- package/dist/engine/settleMergedDelivery.d.ts.map +1 -1
- package/dist/engine/situations/choices.d.ts +20 -0
- package/dist/engine/situations/choices.d.ts.map +1 -0
- package/dist/engine/situations/choices.js +21 -0
- package/dist/engine/situations/choices.js.map +1 -0
- package/dist/engine/situations/service.d.ts +60 -0
- package/dist/engine/situations/service.d.ts.map +1 -0
- package/dist/engine/situations/service.js +51 -0
- package/dist/engine/situations/service.js.map +1 -0
- package/dist/engine/situations/stop.d.ts +25 -0
- package/dist/engine/situations/stop.d.ts.map +1 -0
- package/dist/engine/situations/stop.js +25 -0
- package/dist/engine/situations/stop.js.map +1 -0
- package/dist/engine/situations/work.d.ts +114 -0
- package/dist/engine/situations/work.d.ts.map +1 -0
- package/dist/engine/situations/work.js +91 -0
- package/dist/engine/situations/work.js.map +1 -0
- package/dist/engine/steerBrief.d.ts +532 -535
- package/dist/engine/steerBrief.d.ts.map +1 -1
- package/dist/engine/submissionFailure.d.ts +526 -529
- package/dist/engine/submissionFailure.d.ts.map +1 -1
- package/dist/engine/submitLaunch.d.ts +528 -531
- package/dist/engine/submitLaunch.d.ts.map +1 -1
- package/dist/engine/threadNames.js +1 -1
- package/dist/engine/threadNames.js.map +1 -1
- package/dist/engine/workerReport.d.ts +7 -7
- package/dist/engine/workerReport.d.ts.map +1 -1
- package/dist/exposeFailure.js +1 -1
- package/dist/exposeFailure.js.map +1 -1
- package/dist/fleet.d.ts +26 -26
- package/dist/fleet.js +1 -1
- package/dist/fleet.js.map +1 -1
- package/dist/host/actionCommands.d.ts +10 -10
- package/dist/host/actionCommands.d.ts.map +1 -1
- package/dist/host/actionCommands.js +6 -6
- package/dist/host/actionCommands.js.map +1 -1
- package/dist/host/admission.d.ts +4 -4
- package/dist/host/answerWork.d.ts +4 -3
- package/dist/host/answerWork.d.ts.map +1 -1
- package/dist/host/cliOptions.d.ts +5 -1
- package/dist/host/cliOptions.d.ts.map +1 -1
- package/dist/host/cliOptions.js +6 -4
- package/dist/host/cliOptions.js.map +1 -1
- package/dist/host/commands.d.ts +1 -1
- package/dist/host/commands.d.ts.map +1 -1
- package/dist/host/configSettings.d.ts +5 -5
- package/dist/host/daemon.d.ts +133 -132
- package/dist/host/daemon.d.ts.map +1 -1
- package/dist/host/daemon.js +7 -3
- package/dist/host/daemon.js.map +1 -1
- package/dist/host/daemonClient.d.ts +28 -28
- package/dist/host/daemonClient.js +1 -1
- package/dist/host/daemonClient.js.map +1 -1
- package/dist/host/daemonContract.d.ts +146 -146
- package/dist/host/daemonContract.d.ts.map +1 -1
- package/dist/host/daemonContract.js +1 -1
- package/dist/host/daemonContract.js.map +1 -1
- package/dist/host/daemonDiagnostics.js +1 -1
- package/dist/host/daemonDiagnostics.js.map +1 -1
- package/dist/host/daemonHandlers.d.ts +1 -1
- package/dist/host/daemonHandlers.d.ts.map +1 -1
- package/dist/host/daemonPort.d.ts +6 -0
- package/dist/host/daemonPort.d.ts.map +1 -0
- package/dist/host/daemonPort.js +40 -0
- package/dist/host/daemonPort.js.map +1 -0
- package/dist/host/daemonSnapshots.d.ts +1 -1
- package/dist/host/daemonSnapshots.d.ts.map +1 -1
- package/dist/host/daemonSnapshots.js +1 -1
- package/dist/host/daemonSnapshots.js.map +1 -1
- package/dist/host/fleetStatus.d.ts +5 -5
- package/dist/host/follow.d.ts +1 -0
- package/dist/host/follow.d.ts.map +1 -1
- package/dist/host/follow.js +10 -4
- package/dist/host/follow.js.map +1 -1
- package/dist/host/followCommands.d.ts +2 -2
- package/dist/host/followCommands.d.ts.map +1 -1
- package/dist/host/followCommands.js +4 -2
- package/dist/host/followCommands.js.map +1 -1
- package/dist/host/githubApi.js +1 -1
- package/dist/host/githubApi.js.map +1 -1
- package/dist/host/githubDelivery.js +3 -1
- package/dist/host/githubDelivery.js.map +1 -1
- package/dist/host/healthLayer.js +1 -1
- package/dist/host/healthLayer.js.map +1 -1
- package/dist/host/integrations.js +1 -1
- package/dist/host/integrations.js.map +1 -1
- package/dist/host/mainSource.js +1 -1
- package/dist/host/mainSource.js.map +1 -1
- package/dist/host/providerHealth.js +1 -1
- package/dist/host/providerHealth.js.map +1 -1
- package/dist/host/quota.js +1 -1
- package/dist/host/quota.js.map +1 -1
- package/dist/host/recordDecisionResponse.d.ts +3 -2
- package/dist/host/recordDecisionResponse.d.ts.map +1 -1
- package/dist/host/recordDecisionResponse.js +1 -1
- package/dist/host/recordDecisionResponse.js.map +1 -1
- package/dist/host/releaseWork.d.ts +6 -5
- package/dist/host/releaseWork.d.ts.map +1 -1
- package/dist/host/releaseWork.js +2 -2
- package/dist/host/releaseWork.js.map +1 -1
- package/dist/host/renderStatus.d.ts +4 -1
- package/dist/host/renderStatus.d.ts.map +1 -1
- package/dist/host/renderStatus.js +6 -6
- package/dist/host/renderStatus.js.map +1 -1
- package/dist/host/reportBoard.js +1 -1
- package/dist/host/reportBoard.js.map +1 -1
- package/dist/host/runtime.d.ts +2 -2
- package/dist/host/runtime.d.ts.map +1 -1
- package/dist/host/runtime.js +1 -1
- package/dist/host/runtime.js.map +1 -1
- package/dist/host/statusLayer.js +2 -2
- package/dist/host/statusLayer.js.map +1 -1
- package/dist/host/watch.d.ts.map +1 -1
- package/dist/host/watch.js +1 -1
- package/dist/host/watch.js.map +1 -1
- package/dist/model.d.ts +9 -9
- package/dist/model.js +1 -1
- package/dist/model.js.map +1 -1
- package/dist/operations.d.ts +57 -57
- package/dist/packageInfo.d.ts +1 -1
- package/dist/packageInfo.js +1 -1
- package/dist/policy.d.ts +3 -2
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +2 -1
- package/dist/policy.js.map +1 -1
- package/dist/prompt/briefEdit.js +1 -1
- package/dist/prompt/briefEdit.js.map +1 -1
- package/dist/providers/codexCloud.js +1 -1
- package/dist/providers/codexCloud.js.map +1 -1
- package/dist/providers/codexLocal.js +1 -1
- package/dist/providers/codexLocal.js.map +1 -1
- package/dist/qualifyDependencies.d.ts +2 -2
- package/dist/reportFileDirectory.js +1 -1
- package/dist/reportFileDirectory.js.map +1 -1
- package/dist/scheduling/admission.d.ts +6 -6
- package/dist/scheduling/areas.d.ts +6 -6
- package/dist/scheduling/backPressure.d.ts +6 -6
- package/dist/session/schema.d.ts +1 -1
- package/dist/session/service.js +1 -1
- package/dist/session/service.js.map +1 -1
- package/dist/storage/fleetMigrations.d.ts.map +1 -1
- package/dist/storage/fleetMigrations.js +5 -0
- package/dist/storage/fleetMigrations.js.map +1 -1
- package/dist/storage/makeFleetTransaction.d.ts +1 -1
- package/dist/storage/makeFleetTransaction.d.ts.map +1 -1
- package/dist/storage/makeFleetTransaction.js +1 -1
- package/dist/storage/makeFleetTransaction.js.map +1 -1
- package/dist/storage/makeForeignReservations.d.ts.map +1 -1
- package/dist/storage/makeForeignReservations.js +16 -4
- package/dist/storage/makeForeignReservations.js.map +1 -1
- package/package.json +8 -9
- package/src/DecisionCode.ts +1 -0
- package/src/board/acknowledgeDecision.ts +7 -3
- package/src/board/briefRevision.ts +2 -2
- package/src/board/closePublishedDecision.ts +51 -0
- package/src/board/decisionAnswer.ts +11 -9
- package/src/board/decisionReading.ts +3 -3
- package/src/board/documents.ts +5 -6
- package/src/board/fleetField.ts +1 -1
- package/src/board/markdown.ts +6 -5
- package/src/board/publish.ts +10 -8
- package/src/board/publishReport.ts +2 -2
- package/src/board/readDocument.ts +1 -1
- package/src/board/readPass.ts +2 -2
- package/src/board/reportIdentity.ts +1 -1
- package/src/board/reportLinks.ts +1 -1
- package/src/board/schema.ts +2 -2
- package/src/board/upgradeDecisionClosure.ts +61 -0
- package/src/board/workRevision.ts +2 -2
- package/src/board/writeHealth.ts +2 -2
- package/src/board/writePublished.ts +13 -4
- package/src/cli.ts +13 -5
- package/src/engine/authorizeResolution.ts +1 -1
- package/src/engine/boardBrief.ts +11 -19
- package/src/engine/decisionCopy.ts +63 -0
- package/src/engine/dispatchCommand.ts +4 -34
- package/src/engine/dispatchFailure.ts +25 -0
- package/src/engine/failureCode.ts +1 -1
- package/src/engine/health.ts +1 -1
- package/src/engine/makeDeliver.ts +5 -1
- package/src/engine/makeState.ts +14 -4
- package/src/engine/mergeReadiness.ts +0 -2
- package/src/engine/missingBoardWork.ts +24 -0
- package/src/engine/readResolution.ts +2 -2
- package/src/engine/reconcileCommand.ts +7 -1
- package/src/engine/repository.ts +1 -1
- package/src/engine/saveLaunch.ts +2 -0
- package/src/engine/scheduler.ts +4 -1
- package/src/engine/situations/choices.ts +36 -0
- package/src/engine/situations/service.ts +82 -0
- package/src/engine/situations/stop.ts +60 -0
- package/src/engine/situations/work.ts +94 -0
- package/src/engine/threadNames.ts +1 -1
- package/src/exposeFailure.ts +1 -1
- package/src/fleet.ts +1 -1
- package/src/host/actionCommands.ts +6 -6
- package/src/host/cliOptions.ts +10 -5
- package/src/host/daemon.ts +7 -3
- package/src/host/daemonClient.ts +1 -1
- package/src/host/daemonContract.ts +1 -1
- package/src/host/daemonDiagnostics.ts +1 -1
- package/src/host/daemonPort.ts +50 -0
- package/src/host/daemonSnapshots.ts +1 -1
- package/src/host/follow.ts +16 -5
- package/src/host/followCommands.ts +4 -2
- package/src/host/githubApi.ts +1 -1
- package/src/host/githubDelivery.ts +3 -1
- package/src/host/healthLayer.ts +1 -1
- package/src/host/integrations.ts +1 -1
- package/src/host/mainSource.ts +1 -1
- package/src/host/providerHealth.ts +1 -1
- package/src/host/quota.ts +1 -1
- package/src/host/recordDecisionResponse.ts +1 -1
- package/src/host/releaseWork.ts +2 -2
- package/src/host/renderStatus.ts +6 -7
- package/src/host/reportBoard.ts +1 -1
- package/src/host/runtime.ts +1 -1
- package/src/host/statusLayer.ts +3 -3
- package/src/host/watch.ts +4 -1
- package/src/model.ts +1 -1
- package/src/packageInfo.ts +1 -1
- package/src/policy.ts +2 -1
- package/src/prompt/briefEdit.ts +1 -1
- package/src/providers/codexCloud.ts +1 -1
- package/src/providers/codexLocal.ts +1 -1
- package/src/reportFileDirectory.ts +1 -1
- package/src/session/service.ts +1 -1
- package/src/storage/fleetMigrations.ts +5 -0
- package/src/storage/makeFleetTransaction.ts +2 -2
- package/src/storage/makeForeignReservations.ts +15 -4
- package/dist/engine/releaseOnly.d.ts +0 -3
- package/dist/engine/releaseOnly.d.ts.map +0 -1
- package/dist/engine/releaseOnly.js +0 -19
- package/dist/engine/releaseOnly.js.map +0 -1
- package/src/engine/releaseOnly.ts +0 -24
|
@@ -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>>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { DecisionCode } from "#DecisionCode.ts";
|
|
2
|
+
import { CORRECT_REPORT, RUN_AGAIN, type Situation } from "#engine/situations/choices.ts";
|
|
3
|
+
|
|
4
|
+
export const workSituations = {
|
|
5
|
+
"approval-required": {
|
|
6
|
+
happened: "The task is no longer approved on the Board.",
|
|
7
|
+
recommendation: "Fleet only works on approved tasks. If the task is still needed, approve it on the Board and continue. Otherwise stop here.",
|
|
8
|
+
retry: { label: "Continue after approval", outcome: "Fleet checks that the task is approved and continues the same work." },
|
|
9
|
+
},
|
|
10
|
+
"checks-repair-exhausted": {
|
|
11
|
+
details: true,
|
|
12
|
+
happened: "Required checks still fail after three repair attempts.",
|
|
13
|
+
recommendation:
|
|
14
|
+
"Fleet will not repair these checks again on its own. Look at the failing checks on the PR. If you fixed the cause, let Fleet check again. Otherwise stop here.",
|
|
15
|
+
retry: { label: "Check again", outcome: "Fleet reviews the PR and its checks again. If the same checks still fail, Fleet asks you again." },
|
|
16
|
+
},
|
|
17
|
+
"delivery-head-mismatch": {
|
|
18
|
+
happened: "The PR changed after Fleet reviewed it.",
|
|
19
|
+
recommendation: "Fleet must review the current PR before it can be merged. Fleet recommends reviewing it again.",
|
|
20
|
+
retry: { label: "Review again", outcome: "Fleet reviews the PR at its current commit and checks it again." },
|
|
21
|
+
},
|
|
22
|
+
"empty-report": {
|
|
23
|
+
happened: "The report worker returned an empty report.",
|
|
24
|
+
recommendation: "Fleet recommends running the report worker again.",
|
|
25
|
+
retry: { label: "Write the report again", outcome: "Fleet starts the report worker again." },
|
|
26
|
+
},
|
|
27
|
+
"pr-closed": {
|
|
28
|
+
happened: "The PR was closed without merging.",
|
|
29
|
+
recommendation: "Check why the PR was closed. If that was a mistake, reopen it on GitHub and let Fleet check again. Otherwise stop here.",
|
|
30
|
+
retry: { label: "Check the PR again", outcome: "Fleet checks the PR again and continues the same work if it is open." },
|
|
31
|
+
},
|
|
32
|
+
"pr-conflicting": {
|
|
33
|
+
happened: "The PR has merge conflicts with the main branch.",
|
|
34
|
+
question: "How should Fleet handle the conflicts?",
|
|
35
|
+
recommendation: "Fleet recommends letting the worker resolve the conflicts. Add notes for the worker in your answer if needed.",
|
|
36
|
+
retry: {
|
|
37
|
+
label: "Resolve the conflicts",
|
|
38
|
+
outcome: "The worker merges main into the same branch, resolves the conflicts and updates the same PR. Your notes go along.",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
"pr-head-moved": {
|
|
42
|
+
happened: "New commits reached the PR after Fleet reviewed it.",
|
|
43
|
+
recommendation: "Fleet must review the new commits before the PR can be merged. Fleet recommends reviewing again.",
|
|
44
|
+
retry: { label: "Review the new commits", outcome: "Fleet reviews the PR again at its latest commit." },
|
|
45
|
+
},
|
|
46
|
+
"reviewed-pr-ready": {
|
|
47
|
+
happened: "The PR passed review and all required checks. It is ready to merge.",
|
|
48
|
+
question: "Do you want changes before merging?",
|
|
49
|
+
recommendation:
|
|
50
|
+
"Merge the PR on GitHub when you are happy with it. Fleet notices the merge and finishes the task. Answer here only to request changes or to stop.",
|
|
51
|
+
release: { label: "Stop and hand back", outcome: "Fleet stops watching this PR and hands the task back to you. The PR stays open." },
|
|
52
|
+
retry: {
|
|
53
|
+
label: "Request changes",
|
|
54
|
+
outcome: "Write the changes in your answer. The worker makes them on the same branch and PR, then Fleet reviews and checks the PR again.",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
"reviewer-terminal": {
|
|
58
|
+
happened: "The review stopped before it finished.",
|
|
59
|
+
recommendation: "Fleet recommends running the review again.",
|
|
60
|
+
retry: { label: "Review again", outcome: "Fleet starts a new review of the same PR." },
|
|
61
|
+
},
|
|
62
|
+
"worker-question": {
|
|
63
|
+
details: true,
|
|
64
|
+
happened: "The worker asked a question.",
|
|
65
|
+
recommendation: "Fleet recommends running the step again.",
|
|
66
|
+
retry: RUN_AGAIN,
|
|
67
|
+
},
|
|
68
|
+
"worker-report-head-invalid": {
|
|
69
|
+
happened: "The worker's final report does not name the exact commit it pushed.",
|
|
70
|
+
recommendation: "Fleet recommends asking the worker to fix its report.",
|
|
71
|
+
retry: CORRECT_REPORT,
|
|
72
|
+
},
|
|
73
|
+
"worker-report-head-moved": {
|
|
74
|
+
happened: "The PR changed after the worker reported its final commit.",
|
|
75
|
+
recommendation: "Fleet recommends asking the worker to report the PR's current commit.",
|
|
76
|
+
retry: CORRECT_REPORT,
|
|
77
|
+
},
|
|
78
|
+
"worker-report-merged-head-mismatch": {
|
|
79
|
+
happened: "The PR was merged at a different commit than the worker reported.",
|
|
80
|
+
recommendation: "Check what was merged on GitHub. Then ask the worker to correct its report, or stop here.",
|
|
81
|
+
retry: CORRECT_REPORT,
|
|
82
|
+
},
|
|
83
|
+
"worker-report-pr-invalid": {
|
|
84
|
+
happened: "The worker's final report does not contain a valid PR link.",
|
|
85
|
+
recommendation: "Fleet recommends asking the worker to fix its report.",
|
|
86
|
+
retry: CORRECT_REPORT,
|
|
87
|
+
},
|
|
88
|
+
"worker-terminal": {
|
|
89
|
+
details: true,
|
|
90
|
+
happened: "The worker's run stopped before it finished.",
|
|
91
|
+
recommendation: "Fleet recommends running the step again.",
|
|
92
|
+
retry: RUN_AGAIN,
|
|
93
|
+
},
|
|
94
|
+
} satisfies Partial<Record<DecisionCode, Situation>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { board as boardApi } from "@shivaedev/work-board/integration/board.ts";
|
|
1
|
+
import { board as boardApi } from "@shivaedev/work-board/server/integration/board.ts";
|
|
2
2
|
import type { Attempt, FleetRecord } from "#model.ts";
|
|
3
3
|
|
|
4
4
|
function headingAt(line: string, next: string): string | undefined {
|
package/src/exposeFailure.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { Conflict, Forbidden, ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
3
|
-
import { rpcBoundary } from "@shivaedev/platform/rpc-server/boundary.ts";
|
|
3
|
+
import { rpcBoundary } from "@shivaedev/platform/server/rpc-server/boundary.ts";
|
|
4
4
|
import { failureMessage } from "#engine/failureMessage.ts";
|
|
5
5
|
import { FleetError, isFleetError } from "#errors.ts";
|
|
6
6
|
import { StorageAdmission, StorageCapacity, StorageConflict, StorageQuota } from "#storage/errors.ts";
|
package/src/fleet.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { defineService } from "@shivaedev/effect-service/
|
|
2
|
+
import { defineService } from "@shivaedev/effect-service/defineService.ts";
|
|
3
3
|
import { admissionOrder } from "#engine/admissionOrder.ts";
|
|
4
4
|
import { closeDecisions } from "#engine/closeDecisions.ts";
|
|
5
5
|
import { continueCommand } from "#engine/continueCommand.ts";
|
|
@@ -3,7 +3,7 @@ import * as Argument from "effect/cli/Argument";
|
|
|
3
3
|
import * as Command from "effect/cli/Command";
|
|
4
4
|
import * as Flag from "effect/cli/Flag";
|
|
5
5
|
import { answerText } from "#host/answerText.ts";
|
|
6
|
-
import { board, config, port } from "#host/cliOptions.ts";
|
|
6
|
+
import { board, clientPort, config, port } from "#host/cliOptions.ts";
|
|
7
7
|
import { continuationMessage } from "#host/continuationMessage.ts";
|
|
8
8
|
import { daemonRequest } from "#host/daemonClient.ts";
|
|
9
9
|
|
|
@@ -13,7 +13,7 @@ export const continueCommand = Command.make(
|
|
|
13
13
|
Effect.fn("WorkFleetCli.continue")(function* (input) {
|
|
14
14
|
const message = yield* continuationMessage(Option.getOrUndefined(input.args[1]));
|
|
15
15
|
const value = yield* daemonRequest(
|
|
16
|
-
input
|
|
16
|
+
yield* clientPort(input),
|
|
17
17
|
(client) => client("fleet.continue", { message, workId: input.args[0] }),
|
|
18
18
|
`continue ${input.args[0]}`,
|
|
19
19
|
);
|
|
@@ -28,7 +28,7 @@ export const releaseCommand = Command.make(
|
|
|
28
28
|
{ board, config, port, workIds: Argument.String("id").pipe(Argument.variadic({ min: 1 })) },
|
|
29
29
|
Effect.fn("WorkFleetCli.release")(function* (input) {
|
|
30
30
|
const released = yield* daemonRequest(
|
|
31
|
-
input
|
|
31
|
+
yield* clientPort(input),
|
|
32
32
|
(client) => client("daemon.release", { workIds: input.workIds }),
|
|
33
33
|
`release ${input.workIds.join(", ")}`,
|
|
34
34
|
);
|
|
@@ -50,7 +50,7 @@ export const reassignCommand = Command.make(
|
|
|
50
50
|
},
|
|
51
51
|
Effect.fn("WorkFleetCli.reassign")(function* (input) {
|
|
52
52
|
const value = yield* daemonRequest(
|
|
53
|
-
input
|
|
53
|
+
yield* clientPort(input),
|
|
54
54
|
(client) => client("fleet.reassign", { attentionOwner: input.to, decisionId: input.question, workId: input.id }),
|
|
55
55
|
`reassign ${input.id}`,
|
|
56
56
|
);
|
|
@@ -62,7 +62,7 @@ export const nameThreadsCommand = Command.make(
|
|
|
62
62
|
"name-threads",
|
|
63
63
|
{ board, config, port },
|
|
64
64
|
Effect.fn("WorkFleetCli.nameThreads")(function* (input) {
|
|
65
|
-
const results = yield* daemonRequest(input
|
|
65
|
+
const results = yield* daemonRequest(yield* clientPort(input), (client) => client("daemon.name-threads", {}), "name-threads");
|
|
66
66
|
for (const result of results) {
|
|
67
67
|
yield* result.error ? Console.error(result.message) : Console.log(result.message);
|
|
68
68
|
}
|
|
@@ -82,7 +82,7 @@ export const answerCommand = Command.make(
|
|
|
82
82
|
const supplied = Option.getOrUndefined(input.args[1]);
|
|
83
83
|
const text = input.release && supplied === undefined ? "" : yield* answerText(supplied);
|
|
84
84
|
const value = yield* daemonRequest(
|
|
85
|
-
input
|
|
85
|
+
yield* clientPort(input),
|
|
86
86
|
(client) => client("daemon.answer", { release: input.release, text, workId: input.args[0] }),
|
|
87
87
|
`answer ${input.args[0]}`,
|
|
88
88
|
);
|
package/src/host/cliOptions.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import * as Flag from "effect/cli/Flag";
|
|
2
2
|
import * as Option from "effect/Option";
|
|
3
|
-
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
4
3
|
import { loadHost } from "#host/configFile.ts";
|
|
4
|
+
import { readDaemonPort } from "#host/daemonPort.ts";
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
export const board = Flag.Directory("board").pipe(
|
|
7
|
+
Flag.withDefault(".work"),
|
|
8
|
+
Flag.withDescription("Board folder holding Fleet configuration and daemon port"),
|
|
9
|
+
);
|
|
9
10
|
export const config = Flag.File("config").pipe(Flag.optional, Flag.withDescription("Host configuration instead of <board>/fleet.config.json"));
|
|
10
11
|
|
|
11
12
|
export function host(folder: string, file: Option.Option<string>) {
|
|
12
13
|
return loadHost(folder, Option.getOrUndefined(file));
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
export const port = Flag.Int("port").pipe(Flag.
|
|
16
|
+
export const port = Flag.Int("port").pipe(Flag.optional, Flag.withDescription("Override the local Fleet daemon port"));
|
|
17
|
+
|
|
18
|
+
export function clientPort(input: { readonly board: string; readonly port: Option.Option<number> }) {
|
|
19
|
+
return readDaemonPort(input.board, Option.getOrUndefined(input.port));
|
|
20
|
+
}
|
package/src/host/daemon.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Context, Effect, Fiber, Layer } from "effect";
|
|
2
|
-
import { appHost } from "@shivaedev/platform/appHost.ts";
|
|
3
|
-
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
2
|
+
import { appHost } from "@shivaedev/platform/server/appHost.ts";
|
|
3
|
+
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
4
4
|
import { type HostParts, hostLayer, hostScheduler, productionParts } from "#host/commands.ts";
|
|
5
5
|
import type { FleetHost } from "#host/config.ts";
|
|
6
6
|
import { DaemonContract, RPC_PATH } from "#host/daemonContract.ts";
|
|
7
7
|
import { daemonHandlers } from "#host/daemonHandlers.ts";
|
|
8
|
+
import { publishDaemonPort } from "#host/daemonPort.ts";
|
|
8
9
|
import { watchedConfig } from "#host/liveConfig.ts";
|
|
9
10
|
import { fleetHandlers } from "#operations.ts";
|
|
10
11
|
|
|
@@ -17,6 +18,7 @@ class Scheduler extends Context.Service<Scheduler, Fiber.Fiber<void, unknown>>()
|
|
|
17
18
|
|
|
18
19
|
export function daemonHostOptions(host: FleetHost, parts: HostParts = productionParts(host), port: number = DAEMON_PORT) {
|
|
19
20
|
return {
|
|
21
|
+
boardDir: host.boardDir,
|
|
20
22
|
config: { disablePreemptiveShutdown: true, host: DAEMON_HOST, port },
|
|
21
23
|
group: DaemonContract,
|
|
22
24
|
handlers: Layer.merge(fleetHandlers, Layer.unwrap(daemonHandlers(host))),
|
|
@@ -33,7 +35,9 @@ export function daemonLayer(host: FleetHost, parts: HostParts = productionParts(
|
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
export function daemonHttpLayer(options: ReturnType<typeof daemonHostOptions>) {
|
|
36
|
-
|
|
38
|
+
const { boardDir, ...http } = options;
|
|
39
|
+
const server = appHost({ ...http, services: Layer.empty }).pipe(Layer.provideMerge(options.services));
|
|
40
|
+
return Layer.effectDiscard(publishDaemonPort(boardDir)).pipe(Layer.provideMerge(server));
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
export function serveFleet(host: FleetHost, parts: HostParts = productionParts(host), port: number = DAEMON_PORT) {
|
package/src/host/daemonClient.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { FetchHttpClient } from "effect/http";
|
|
|
3
3
|
import { RpcClient, RpcSerialization } from "effect/rpc";
|
|
4
4
|
import { RpcClientError } from "effect/rpc/RpcClientError";
|
|
5
5
|
import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
6
|
-
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
6
|
+
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
7
7
|
import { isFleetError } from "#errors.ts";
|
|
8
8
|
import { DaemonContract, RPC_PATH } from "#host/daemonContract.ts";
|
|
9
9
|
|
|
@@ -2,7 +2,7 @@ import { Schema } from "effect";
|
|
|
2
2
|
import { contract } from "@shivaedev/effect-contract/contract.ts";
|
|
3
3
|
import { command, query, stream } from "@shivaedev/effect-contract/operation.ts";
|
|
4
4
|
import { RequestTracing } from "@shivaedev/platform/rpc/middleware.ts";
|
|
5
|
-
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
5
|
+
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
6
6
|
import { DispatchRequest } from "#DispatchRequest.ts";
|
|
7
7
|
import { fleetRejections } from "#errors.ts";
|
|
8
8
|
import { DaemonStatus } from "#host/configSettings.ts";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
3
|
-
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
3
|
+
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
4
4
|
import { failureMessage } from "#engine/failureMessage.ts";
|
|
5
5
|
import { HealthSnapshot } from "#engine/health.ts";
|
|
6
6
|
import { fleetItems } from "#host/fleetItems.ts";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Effect, FileSystem, Path, Schema } from "effect";
|
|
2
|
+
import { HttpServer } from "effect/http";
|
|
3
|
+
import * as NetAddress from "effect/net/NetAddress";
|
|
4
|
+
import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
5
|
+
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
6
|
+
|
|
7
|
+
const PORT_FILE = ".fleet-port";
|
|
8
|
+
const Port = Schema.NumberFromString.pipe(Schema.check(Schema.isInt(), Schema.isBetween({ maximum: 65_535, minimum: 1 })));
|
|
9
|
+
|
|
10
|
+
export const readDaemonPort = Effect.fn("FleetDaemon.readDaemonPort")(function* (board: string, override?: number) {
|
|
11
|
+
if (override !== undefined) {
|
|
12
|
+
return override;
|
|
13
|
+
}
|
|
14
|
+
const fs = yield* FileSystem.FileSystem;
|
|
15
|
+
const path = yield* Path.Path;
|
|
16
|
+
const file = path.join(path.resolve(board), PORT_FILE);
|
|
17
|
+
const text = yield* fs
|
|
18
|
+
.readFileString(file)
|
|
19
|
+
.pipe(
|
|
20
|
+
Effect.catchTag("PlatformError", (error) =>
|
|
21
|
+
error.reason._tag === "NotFound"
|
|
22
|
+
? Effect.succeed(String(diagnosticsApi.DAEMON_PORT))
|
|
23
|
+
: Effect.fail(new ServiceUnavailable({ message: `Cannot read Fleet daemon port from ${file}: ${error.message}` })),
|
|
24
|
+
),
|
|
25
|
+
);
|
|
26
|
+
return yield* Schema.decodeUnknownEffect(Port)(text.trim()).pipe(
|
|
27
|
+
Effect.mapError(() => new ServiceUnavailable({ message: `Invalid Fleet daemon port in ${file}` })),
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const publishDaemonPort = Effect.fn("FleetDaemon.publishDaemonPort")(function* (board: string) {
|
|
32
|
+
const server = yield* HttpServer.HttpServer;
|
|
33
|
+
if (!NetAddress.isInetAddress(server.address)) {
|
|
34
|
+
return yield* Effect.die("Expected a TCP Fleet daemon");
|
|
35
|
+
}
|
|
36
|
+
const fs = yield* FileSystem.FileSystem;
|
|
37
|
+
const path = yield* Path.Path;
|
|
38
|
+
const file = path.join(board, PORT_FILE);
|
|
39
|
+
const port = String(server.address.port);
|
|
40
|
+
yield* Effect.acquireRelease(fs.writeFileString(`${file}.tmp`, `${port}\n`).pipe(Effect.andThen(fs.rename(`${file}.tmp`, file))), () =>
|
|
41
|
+
Effect.gen(function* () {
|
|
42
|
+
const current = yield* fs
|
|
43
|
+
.readFileString(file)
|
|
44
|
+
.pipe(Effect.catchTag("PlatformError", (error) => (error.reason._tag === "NotFound" ? Effect.succeed("") : Effect.fail(error))));
|
|
45
|
+
if (current.trim() === port) {
|
|
46
|
+
yield* fs.remove(file, { force: true });
|
|
47
|
+
}
|
|
48
|
+
}).pipe(Effect.orDie),
|
|
49
|
+
);
|
|
50
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Effect, Schedule, Stream } from "effect";
|
|
2
2
|
import { SqlClient } from "effect/sql";
|
|
3
|
-
import { AppChanges } from "@shivaedev/platform/appHost.ts";
|
|
4
3
|
import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
4
|
+
import { AppChanges } from "@shivaedev/platform/server/appHost.ts";
|
|
5
5
|
import type { DispatchRequest } from "#DispatchRequest.ts";
|
|
6
6
|
import { fleetRecords } from "#fleetRecords.ts";
|
|
7
7
|
import type { FleetHost } from "#host/config.ts";
|
package/src/host/follow.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import * as NodeServices from "@effect/platform-node/NodeServices";
|
|
2
|
+
import { Console, Effect, Stream } from "effect";
|
|
3
|
+
import { RpcClientError } from "effect/rpc/RpcClientError";
|
|
3
4
|
import { type FleetError, isFleetError } from "#errors.ts";
|
|
4
5
|
import { daemonClient, daemonError } from "#host/daemonClient.ts";
|
|
6
|
+
import { readDaemonPort } from "#host/daemonPort.ts";
|
|
5
7
|
import { decodeFollowState, type FollowState } from "#host/followState.ts";
|
|
6
8
|
|
|
7
|
-
const { DAEMON_PORT } = diagnosticsApi;
|
|
8
|
-
|
|
9
9
|
export interface FollowOptions {
|
|
10
|
+
readonly board?: string;
|
|
10
11
|
readonly follow?: boolean;
|
|
11
12
|
readonly intervalMs: number;
|
|
12
13
|
readonly port?: number;
|
|
@@ -14,11 +15,13 @@ export interface FollowOptions {
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export function follow(options: FollowOptions, workIds: readonly string[]) {
|
|
17
|
-
const port = options.port ?? DAEMON_PORT;
|
|
18
18
|
let ids = workIds;
|
|
19
19
|
let connected = false;
|
|
20
20
|
let failures = 0;
|
|
21
21
|
function connect(): Stream.Stream<readonly FollowState[], FleetError> {
|
|
22
|
+
return Stream.unwrap(readDaemonPort(options.board ?? ".work", options.port).pipe(Effect.provide(NodeServices.layer), Effect.map(subscribe)));
|
|
23
|
+
}
|
|
24
|
+
function subscribe(port: number): Stream.Stream<readonly FollowState[], FleetError> {
|
|
22
25
|
return Stream.unwrap(daemonClient(port).pipe(Effect.map((client) => client("daemon.follow", { follow: options.follow, workIds: ids })))).pipe(
|
|
23
26
|
Stream.scoped,
|
|
24
27
|
Stream.map((states) => states.map(decodeFollowState)),
|
|
@@ -33,6 +36,14 @@ export function follow(options: FollowOptions, workIds: readonly string[]) {
|
|
|
33
36
|
Stream.concat(Stream.fail(new Error("Fleet daemon subscription closed"))),
|
|
34
37
|
Stream.catch((error) => {
|
|
35
38
|
failures += 1;
|
|
39
|
+
if (options.follow && !isFleetError(error) && (!(error instanceof RpcClientError) || error.reason._tag === "HttpError")) {
|
|
40
|
+
return Stream.unwrap(
|
|
41
|
+
Console.error(`work-fleet: ERROR ${daemonError(error, port, "follow").message}; retrying in ${options.intervalMs / 1000}s`).pipe(
|
|
42
|
+
Effect.andThen(Effect.sleep(options.intervalMs)),
|
|
43
|
+
Effect.as(connect()),
|
|
44
|
+
),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
36
47
|
if (!connected || isFleetError(error) || failures >= 20) {
|
|
37
48
|
return Stream.fail(daemonError(error, port, "follow"));
|
|
38
49
|
}
|
|
@@ -20,8 +20,9 @@ export const waitCommand = Command.make(
|
|
|
20
20
|
Effect.fn("WorkFleetCli.wait")(function* (input) {
|
|
21
21
|
const { waitFor } = yield* Effect.promise(() => import("#host/wait.ts"));
|
|
22
22
|
const outcome = yield* waitFor({
|
|
23
|
+
board: input.board,
|
|
23
24
|
intervalMs: input.interval * 1000,
|
|
24
|
-
port:
|
|
25
|
+
...Option.match(input.port, { onNone: () => ({}), onSome: (value) => ({ port: value }) }),
|
|
25
26
|
workId: input.workId,
|
|
26
27
|
...Option.match(input.timeout, { onNone: () => ({}), onSome: (seconds) => ({ timeoutMs: seconds * 1000 }) }),
|
|
27
28
|
});
|
|
@@ -44,9 +45,10 @@ export const watchCommand = Command.make(
|
|
|
44
45
|
Effect.fn("WorkFleetCli.watch")(function* (input) {
|
|
45
46
|
const { watchFor } = yield* Effect.promise(() => import("#host/watch.ts"));
|
|
46
47
|
process.exitCode = yield* watchFor({
|
|
48
|
+
board: input.board,
|
|
47
49
|
follow: input.follow,
|
|
48
50
|
intervalMs: input.interval * 1000,
|
|
49
|
-
port:
|
|
51
|
+
...Option.match(input.port, { onNone: () => ({}), onSome: (value) => ({ port: value }) }),
|
|
50
52
|
workIds: input.workIds,
|
|
51
53
|
...Option.match(input.timeout, { onNone: () => ({}), onSome: (seconds) => ({ timeoutMs: seconds * 1000 }) }),
|
|
52
54
|
});
|
package/src/host/githubApi.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Clock, Effect, Layer } from "effect";
|
|
2
|
-
import { defineService } from "@shivaedev/effect-service/
|
|
2
|
+
import { defineService } from "@shivaedev/effect-service/defineService.ts";
|
|
3
3
|
import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
4
4
|
import {
|
|
5
5
|
type GithubObservation,
|
|
@@ -90,7 +90,9 @@ const validateDelivery = Effect.fn("FleetHost.validateDelivery")(function* (pr:
|
|
|
90
90
|
return yield* failure("Delivery observation differs from the adopted PR");
|
|
91
91
|
}
|
|
92
92
|
if (pr.state === "CLOSED" && pr.mergedAt === null && pr.mergeCommit === null) {
|
|
93
|
-
return yield* failure("PR was closed without merging; inspect the closed PR before retrying or releasing this work")
|
|
93
|
+
return yield* withFailureContext(failure("PR was closed without merging; inspect the closed PR before retrying or releasing this work"), {
|
|
94
|
+
code: "pr-closed",
|
|
95
|
+
});
|
|
94
96
|
}
|
|
95
97
|
const merged = pr.state === "MERGED" && pr.mergedAt !== null && pr.mergeCommit !== null;
|
|
96
98
|
if (!merged && (pr.state !== "OPEN" || pr.mergedAt !== null || pr.mergeCommit !== null)) {
|
package/src/host/healthLayer.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Layer, Ref, Schema } from "effect";
|
|
2
|
-
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
2
|
+
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
3
3
|
import { Health } from "#engine/health.ts";
|
|
4
4
|
import { ProviderCapacity } from "#session/schema.ts";
|
|
5
5
|
|
package/src/host/integrations.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as NodeServices from "@effect/platform-node/NodeServices";
|
|
2
2
|
import { Effect, Layer } from "effect";
|
|
3
|
-
import { defineService } from "@shivaedev/effect-service/
|
|
3
|
+
import { defineService } from "@shivaedev/effect-service/defineService.ts";
|
|
4
4
|
import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
5
5
|
import type { DecisionCode } from "#DecisionCode.ts";
|
|
6
6
|
import { withFailureContext } from "#engine/failureContext.ts";
|
package/src/host/mainSource.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
2
|
import { Clock, Context, Effect, Layer } from "effect";
|
|
3
|
-
import { defineService } from "@shivaedev/effect-service/
|
|
3
|
+
import { defineService } from "@shivaedev/effect-service/defineService.ts";
|
|
4
4
|
import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
5
5
|
import type { FleetError } from "#errors.ts";
|
|
6
6
|
import type { FleetHost } from "#host/config.ts";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Context, Effect, Layer, type Option } from "effect";
|
|
2
|
-
import { defineService } from "@shivaedev/effect-service/
|
|
2
|
+
import { defineService } from "@shivaedev/effect-service/defineService.ts";
|
|
3
3
|
import { capacityRejected, Health } from "#engine/health.ts";
|
|
4
4
|
import type { SessionFailure, SessionObservation } from "#session/schema.ts";
|
|
5
5
|
import { SessionTransport } from "#session/service.ts";
|
package/src/host/quota.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
2
|
import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
3
|
-
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
3
|
+
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
4
4
|
import type { FleetError } from "#errors.ts";
|
|
5
5
|
import type { FleetHost } from "#host/config.ts";
|
|
6
6
|
import type { FleetConfiguration } from "#policy.ts";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Clock, Effect, FileSystem, Schema } from "effect";
|
|
2
2
|
import { BadRequest, Conflict } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
3
|
-
import { responses as responsesApi } from "@shivaedev/work-board/integration/responses.ts";
|
|
3
|
+
import { responses as responsesApi } from "@shivaedev/work-board/server/integration/responses.ts";
|
|
4
4
|
import type { BoardDecision } from "#board/schema.ts";
|
|
5
5
|
import { BoardGateway, type Decision } from "#policy.ts";
|
|
6
6
|
|
package/src/host/releaseWork.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as NodeServices from "@effect/platform-node/NodeServices";
|
|
2
2
|
import { Effect, Layer } from "effect";
|
|
3
3
|
import { Conflict, Forbidden } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
4
|
-
import { board } from "@shivaedev/work-board/integration/board.ts";
|
|
5
|
-
import { responses } from "@shivaedev/work-board/integration/responses.ts";
|
|
4
|
+
import { board } from "@shivaedev/work-board/server/integration/board.ts";
|
|
5
|
+
import { responses } from "@shivaedev/work-board/server/integration/responses.ts";
|
|
6
6
|
import { Fleet } from "#fleet.ts";
|
|
7
7
|
import { type HostParts, hostLayer, productionParts } from "#host/commands.ts";
|
|
8
8
|
import type { FleetHost } from "#host/config.ts";
|
package/src/host/renderStatus.ts
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
2
1
|
import { sessionStatus } from "#engine/sessionStatus.ts";
|
|
3
2
|
import { type DaemonStatus, renderConfig } from "#host/configSettings.ts";
|
|
4
3
|
import type { FleetViews } from "#model.ts";
|
|
5
4
|
|
|
6
|
-
const { DAEMON_PORT } = diagnosticsApi;
|
|
7
|
-
|
|
8
5
|
type View = (typeof FleetViews.Type)["active"][number];
|
|
9
6
|
|
|
10
|
-
function line(view: View, waiting: boolean,
|
|
7
|
+
function line(view: View, waiting: boolean, selection: string) {
|
|
11
8
|
const reason = view.blocker ?? view.decision?.reason ?? (view.overLimit ? "launched over the limit" : undefined);
|
|
12
9
|
const detail = reason === undefined ? "" : ` ${reason}`;
|
|
13
10
|
const links = [...view.links, ...view.sessions.map(sessionStatus)];
|
|
14
|
-
const answer = waiting ? `\n work-fleet answer ${view.workId}${
|
|
11
|
+
const answer = waiting ? `\n work-fleet answer ${view.workId}${selection}` : "";
|
|
15
12
|
return ` ${view.workId} ${view.stage}${detail}${links.length === 0 ? "" : ` (${links.join(", ")})`}${answer}`;
|
|
16
13
|
}
|
|
17
14
|
|
|
18
|
-
export function renderStatus(current: typeof DaemonStatus.Type,
|
|
15
|
+
export function renderStatus(current: typeof DaemonStatus.Type, selection: { readonly board?: string; readonly port?: number } = {}): string {
|
|
16
|
+
const board = selection.board === undefined || selection.board === ".work" ? "" : ` --board '${selection.board.replaceAll("'", "'\\''")}'`;
|
|
17
|
+
const endpoint = `${board}${selection.port === undefined ? "" : ` --port ${selection.port}`}`;
|
|
19
18
|
const sections: readonly [string, readonly View[]][] = [
|
|
20
19
|
["Active", current.active],
|
|
21
20
|
["Waiting on maintainer", current.waiting.maintainer],
|
|
@@ -27,7 +26,7 @@ export function renderStatus(current: typeof DaemonStatus.Type, port: number = D
|
|
|
27
26
|
.map(([title, items]) =>
|
|
28
27
|
[
|
|
29
28
|
`${title} (${items.length})`,
|
|
30
|
-
...items.map((item) => line(item, title === "Waiting on maintainer" || title === "Waiting on orchestrator",
|
|
29
|
+
...items.map((item) => line(item, title === "Waiting on maintainer" || title === "Waiting on orchestrator", endpoint)),
|
|
31
30
|
].join("\n"),
|
|
32
31
|
)
|
|
33
32
|
.join("\n");
|
package/src/host/reportBoard.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as NodeServices from "@effect/platform-node/NodeServices";
|
|
2
2
|
import { Context, Effect, Layer } from "effect";
|
|
3
|
-
import { defineService } from "@shivaedev/effect-service/
|
|
3
|
+
import { defineService } from "@shivaedev/effect-service/defineService.ts";
|
|
4
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";
|
package/src/host/runtime.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as NodeServices from "@effect/platform-node/NodeServices";
|
|
2
2
|
import { Clock, Effect, Layer, Redacted } from "effect";
|
|
3
|
-
import { appDatabase } from "@shivaedev/platform/appHost.ts";
|
|
4
3
|
import { ServiceUnavailable } from "@shivaedev/platform/errors/taxonomy.ts";
|
|
4
|
+
import { appDatabase } from "@shivaedev/platform/server/appHost.ts";
|
|
5
5
|
import type { ReportInspection } from "#engine/ReportInspection.ts";
|
|
6
6
|
import { fleetSessionJournal, postgresFleetRepository } from "#engine/repository.ts";
|
|
7
7
|
import { Fleet } from "#fleet.ts";
|
package/src/host/statusLayer.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Clock, Console, Context, Effect, FileSystem, Layer, type Option, Ref, Semaphore } from "effect";
|
|
2
|
-
import { defineService } from "@shivaedev/effect-service/
|
|
3
|
-
import type { FleetHealth } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
4
|
-
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
2
|
+
import { defineService } from "@shivaedev/effect-service/defineService.ts";
|
|
3
|
+
import type { FleetHealth } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
4
|
+
import { diagnostics as diagnosticsApi } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
5
5
|
import { publishAfterBoardPass } from "#board/readPass.ts";
|
|
6
6
|
import { writeHealth } from "#board/writeHealth.ts";
|
|
7
7
|
import { writeStatus } from "#board/writeStatus.ts";
|
package/src/host/watch.ts
CHANGED
|
@@ -39,7 +39,10 @@ export const watchFor = Effect.fn("FleetWatch.watchFor")(function* (options: Wat
|
|
|
39
39
|
);
|
|
40
40
|
yield* options.timeoutMs === undefined
|
|
41
41
|
? consume
|
|
42
|
-
: Effect.raceFirst(
|
|
42
|
+
: Effect.raceFirst(
|
|
43
|
+
consume,
|
|
44
|
+
options.follow ? Effect.sleep(options.timeoutMs) : Deferred.await(ready).pipe(Effect.andThen(Effect.sleep(options.timeoutMs))),
|
|
45
|
+
);
|
|
43
46
|
if (!options.follow && pending?.size === 0) {
|
|
44
47
|
return WAIT_EXIT.completed;
|
|
45
48
|
}
|
package/src/model.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
-
import { diagnostics } from "@shivaedev/work-board/integration/diagnostics.ts";
|
|
2
|
+
import { diagnostics } from "@shivaedev/work-board/server/integration/diagnostics.ts";
|
|
3
3
|
import { AttentionOwner } from "#attention.ts";
|
|
4
4
|
import { BoardReport } from "#board/schema.ts";
|
|
5
5
|
import { DispatchRequest } from "#DispatchRequest.ts";
|