chat: bound the wake bypass, and prove a parked deployment redeploys clean (CL-6644, part B) - #314
Merged
Conversation
…esidue CL-6644 part B: nothing sidecar-side ever resumes a parked deployment on its own since 0fd3fbc deleted the in-place park/wake handler, and the CL-6282 boot scan skips a parked record entirely rather than restoring it -- so a hub-driven wake is always a fresh agent.deploy for the address, against whatever residue a hibernate teardown left: the deployment record (kept, marked parked, not deleted) and the step-state dir (kept for a resume). This proves that redeploy completes cleanly against that residue.
…eout CL-6644 part B. `@corbits/agent-lifecycle`'s ensureAwake already bounds a wake to DEFAULT_WAKE_TIMEOUT_MS (CL-6643) -- but only when it is the one calling wakeByAddress. Three call sites bypassed that bound entirely by calling wakeByAddress directly: sendMail's no-lifecycle fallback, the exported ensureAwake hook's no-lifecycle fallback, and (regardless of whether lifecycle is configured) sendFoldedMailWithReclaimRetry's reclaim retry. A deploy round-trip the sidecar never acked wedged any of these forever instead of failing loud -- the confirmed second half of the "cold wake never completes" symptom. Also corrects wakeByAddress's stale CL-6267 comment, which still described the sidecar-side park/wake handler 0fd3fbc deleted days before CL-6282 shipped. The parked-record redeploy this comment worried about already works today (see the new sidecar test) -- the comment was just describing a mechanism that no longer exists.
This was referenced Aug 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
CL-6644 part B: the wake itself. Part A (#313) fixed diagnosability. This
picks up its own note: I traced the wake hop
(
ensureAwake/wakeByAddress/wakeFoldedRun/deployAdoptedWorkflowFromSource/sendAgentDeploy) all the way to the vendored@intx/hub-sessionsWS layer.What I ruled out.
@corbits/agent-lifecycle'sensureAwake(CL-6643,already on main) bounds a wake to 30s. The sidecar's own deploy path
(
apps/sidecar/src/workflow-host-wiring/index.ts) does not gate a freshdeploy()on a parked record's residue:activeSupervisorsis cleared onhibernate teardown, transport is unregistered unconditionally, and a
same-address slug re-claim is a defensive no-op. A new sidecar test
(
apps/sidecar/test/workflow-teardown-flavor.test.ts) proves adeploy()call for an address right after its hibernate teardown completes cleanly
against the kept parked record and step-state dir. So a parked record left
"asleep" by #288's boot scan is genuinely resumable through the ordinary
wake path -- I'm not quarantining it at boot; that would throw away state a
wake can still use.
What was actually broken. Three call sites invoke
wakeByAddressdirectly, bypassing
ensureAwake's 30s bound entirely:sendMail's no-lifecycle-configured fallbackensureAwakehook's no-lifecyclefallbacksendFoldedMailWithReclaimRetry's reclaim-retry wake (packages/chat/src/platform-adapter.ts:659) -- this one bypasses the bound regardless of whetherlifecycleis configured, since it always callswakeByAddressraw.Each is a full deploy round-trip to the sidecar with no timeout. A deploy
the sidecar never acks (dropped frame, socket hiccup, whatever) wedges the
caller -- and, for the reclaim-retry loop, every later send behind it --
forever instead of failing loud. That is the multi-minute silent hang CL-6644
describes.
Fix
wakeByAddressBounded, wrappingwakeByAddresswith the sameDEFAULT_WAKE_TIMEOUT_MSbound@corbits/agent-lifecyclealready uses,and rewired all three direct call sites onto it.
wakeByAddress's stale CL-6267 comment, which still describedthe sidecar-side park/wake handler
0fd3fbc8deleted days before Sidecar boot restore: skip parked deployments, restore live ones bounded-parallel #288shipped -- misleading enough that it's what sent chat: log the undelivered-turn cause and thread a reportError refId (CL-6644, part A) #313's investigation in
circles. The mechanism it worried about (redeploy after park) already
works; the comment was just wrong about why.
Test plan
WORKBENCH_CHECK_SINCE=origin/main bun run typecheck-- passWORKBENCH_CHECK_SINCE=origin/main bun run lint-- passWORKBENCH_CHECK_SINCE=origin/main bun run test-- pass, includingthe new sidecar parked-redeploy test
the shared stack in this timeboxed session; the fix removes the one
remaining unbounded hop in the wake path, but a live send against a
genuinely dropped
agent.deploy.ackwould be the strongest proof.Flagging for a follow-up verification pass rather than guessing.