feat(acp): harden resident session lifecycle - #1494
Merged
Merged
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--no-session, RPC, and print invocations client-ownedsessionDirand monotonictelemetryDisabled, and require a fresh client launch environment before replacing a failed residentRelated Linear: ENG-4600, ENG-4603, ENG-4685.
Recovery and security contract
Live residents remain reattachable from their worker identity and socket. If a worker is dead or unreachable after supervisor recovery, it remains failed until a new client supplies fresh transient launch context. A verified-current failed resident is stopped only when its stored process-start identity still matches; replaced PIDs are never signaled, and unknown identities fail closed.
Durable worker state contains routing/session identity, local worker authentication, lifecycle markers, and the two typed host-policy fields above. It excludes
launchEnv,apiKey, provider/model selection, headers, extension values, runtime metadata, and the rest ofcreateCommand.config.Validation
npm run checkmaingit diff --checkThis standalone PR supersedes the broader #1236 / #1239 stack once its own baseline checks and review complete. It intentionally does not include relay IDs/replay machinery, intercept retries, daemon discovery or shutdown CLI changes, or release cleanup behavior.
Note
High Risk
Changes span ACP completion semantics, concurrent session input admission, multi-layer daemon fencing, and persisted worker recovery—any ordering bug could mis-report turn completion or admit input during teardown.
Overview
ACP session-backed workers stay resident for normal ACP mode; only
--no-session(and non-ACP clients) use client-owned workers viaisClientOwnedDaemonSession.ACP updates are now producer-ordered and causally tagged.
AcpUpdateProducerstamps every notification withpromptTurnId, monotoniceventSequence,phase(event/responseBoundary/terminalQuiescence), andoutcome. Prompt handling emits a response boundary withterminalQuiescenceExpected, then a terminal quiescence update only after headless completion withwaitForRlmQuiescenceand an authoritative child roster with no outstanding subagents.session/newadmission is gated until the JSON-RPC response is written so buffered events cannot race ahead of the reply.Session input is fail-closed during stop/close/cancel.
acquireSessionInputPauseleases fence new turns through the session, daemon, supervisor, andDaemonAgentConnection; disconnect invalidates pauses and closes the connection.RLM child lifecycle is settlement-aware. Child runs track
settlement, quiescence abandonment, and recursivewaitForRlmQuiescence; headless completion can opt into the strong barrier. Daemon addsget_rlm_children, schema revision 19 capabilities, and always includeschildrenon attach snapshots.Recovery persistence is narrowed. Worker descriptors migrate to v2 with
durableDaemonWorkerDescriptoranddurableAgentSessionRuntimeConfig—only host routing/policy fields (e.g.sessionDir,telemetryDisabled), not models, credentials, orlaunchEnv. Failed owned workers wait for freshrecoveryConfigand launch env on reattach before relaunch; stale failed residents can be reclaimed when process identity is verified.Reviewed by Cursor Bugbot for commit 095ba1e. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Harden resident session lifecycle with input fencing, RLM quiescence, and descriptor v2 migration
waitForRlmQuiescenceblocks until all descendant child runs settle, deletion cleanup completes (or records retry), and deferred terminal notices flushsessionDir/telemetryDisabledto top level, stripping secrets fromcreateCommand/config/lastError, and redacting on both load and persistAcpUpdateProducerin acp-mode.ts that serializes session updates with producer-stampedpromptTurnId,eventSequence, and phase/outcome classification; session/new response acts as the admission barrier before any session-scoped update publishesDAEMON_SCHEMA_REVISIONto 19 in daemon-protocol.ts with new capabilities:authoritative_child_roster,owned_session_recovery_context,rlm_quiescence_barrier,session_input_pauselifecycle: 'failed'awaiting a freshrecoveryConfigon attach instead of auto-relaunching;launchEnvis always collected (not just for client-owned);isClientOwnedDaemonSessionreturns false for ACP sessions withoutnoSession; snapshot responses always include achildrenarray (possibly empty) instead of eliding the field;getRlmChildSnapshotsreturns authoritative rosters gated byauthoritative_child_rostercapability;waitForHeadlessCompletiondefaults towaitForHeadlessIdle(not fullwaitForIdle)Macroscope summarized f18de4b.