Repository navigation
fix(channel): keep hosted runs resident while busy - #186
Merged
Merged
Conversation
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.
A hosted channel's Durable Object hibernated while a chat was busy and a workspace tool call was pending. The workspace socket is hibernatable and a silent shell sends nothing, so once no client sockets were open the object went idle. The keepalive alarm then woke a new instance. pi resumed and told the model the shell was interrupted, but the process kept running on the workspace. A later Kill could not reach it, because the new instance had no record of the old call.
Fix:
onBusyalready reports busy transitions, including the initial snapshot taken beforeharness.resume().HostedChannelnow uses those transitions to hold one pending timer while any chat is busy. Each timer re-arms itself afterKEEPALIVE, so every hold is a new, bounded operation, and the busy-to-idle transition clears it synchronously. A pending timer stops Cloudflare from hibernating the object. Idle and dormant channels have no timer and hibernate as before. The durable alarm path is unchanged and still brings back an object that the runtime resets. There are no changes to storage,packages/channel, or the workspace protocol. The architecture doc's hosted-channels section explains active-run residency vs idle hibernation.Fixes #183. Refs #176, #13.
Real Cloudflare evidence (dedicated
ace-channel-pilot/ace-directory-pilotworkers, one hosted channel on an isolated host, modelanthropic/claude-sonnet-5-5, tools on a local Mac workspace). The existing deployed services were not touched.ad3f731): a detached 75s silent shell with no cloud clients was reported to the model as "interrupted and may have partially run" about 38s in. Its PID kept running. The workspace logs show new cloud call generations (2b08a256, then387df656) and noworkspace.drop. A 120s repeat was interrupted about 30s in. Kill afterwards returned ok, but the original PID kept running and wrote its end marker.error=falseand no interruption. This passed on both the interval draft and the final timer version.ctx.abort()was injected through a temporary pilot-only wrapper that was never committed and has since been removed.bun typesandbun run cipass.Not verified here: a second physical machine, and sleep/network loss on a physical host. A plain redeploy during an active shell did not measurably reset the object, so reset coverage comes from
ctx.abort()only.Built in Ace
The following ran in the Ace operator channel
cloud-pilot-ops, using Ace's lane, shell, and file tools:cloud-pilotbun types/bun run ciCodex (outside Ace) coordinated the investigation and review, inspected local evidence, and organized the GitHub issues (#176, #183), because Ace cannot yet host the Codex harness (#9). The first repository and credential-readiness inspection and the tracker commands also ran in Codex's shell. That was an external escape, not an Ace shell limitation.