Files
orca/src/main/daemon/daemon-automatic-work-protocol.ts
T
OrcaWinandm4air 08b65edc5c feat(serve): let the owner resume paused automatic restores (#27459)
* feat(serve): let the owner resume paused automatic restores

The terminal daemon now answers automaticWorkStatus and
resumeAutomaticWork. Resume clears a recorded same-boot crash pause or
a pressure pause, writes the cleared state durably, and wakes restores
that were waiting. The runtime exposes runtime.automaticWork.status and
runtime.automaticWork.resume (host-admin; advertised as
runtime.automatic-work.v1), the CLI adds 'orca serve restore resume',
and a sleeping pane paused by its host offers 'Resume automatic
restores'. A daemon that predates the requests reports no gate.

* fix(serve): a stale daemon cannot resume, and an old one says so

Resume now re-reads endpoint ownership right before it runs, so a
daemon replaced by a successor cannot rewrite the successor's run
marker. A gate-bearing daemon from before resume existed is reported as
'terminal host predates resume' instead of 'no gate'; the CLI says to
run the command again after the terminal host restarts, and a sleeping
pane still resumes when the user asks for it.

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-11 06:31:43 -07:00

35 lines
1.3 KiB
TypeScript

import { DAEMON_ENDPOINT_LOST_MESSAGE } from './daemon-endpoint-ownership'
import type { DaemonAutomaticWorkGuard } from './daemon-automatic-work-guard'
// Why request types outside DaemonRequest: the server answers them before the session router, and
// an older daemon rejects them as unknown.
export type AutomaticWorkRequestType = 'automaticWorkStatus' | 'resumeAutomaticWork'
export function automaticWorkRequestType(request: {
type: string
}): AutomaticWorkRequestType | null {
return request.type === 'automaticWorkStatus' || request.type === 'resumeAutomaticWork'
? request.type
: null
}
/**
* Answers an automatic-work request, or undefined for any other request. Why a fresh ownership
* read for resume: the loss latch trails replacement, and a resume from a replaced daemon would
* rewrite its successor's run marker.
*/
export function answerAutomaticWorkRequest(
request: { type: string },
guard: Pick<DaemonAutomaticWorkGuard, 'handle'>,
endpoint: { hasLostOwnership(): boolean }
): ReturnType<DaemonAutomaticWorkGuard['handle']> | undefined {
const type = automaticWorkRequestType(request)
if (!type) {
return undefined
}
if (type === 'resumeAutomaticWork' && endpoint.hasLostOwnership()) {
throw new Error(DAEMON_ENDPOINT_LOST_MESSAGE)
}
return guard.handle(type)
}