Spike: suspend can preserve agent identity without vendoring hub-agent - #291
Closed
TheGreatAxios wants to merge 1 commit into
Closed
Spike: suspend can preserve agent identity without vendoring hub-agent#291TheGreatAxios wants to merge 1 commit into
TheGreatAxios wants to merge 1 commit into
Conversation
…b-agent CL-6581 asks whether the idle-sleep epic is really blocked on an upstream ask (CL-6239) to make @intx/hub-agent's undeploy non-destructive. It's consumed as a published package here (no vendor/intx/hub-agent tree), but the destructive fsp.rm(agentDir) lives entirely inside it. This PoC proves against the real, unmodified package that a caller can snapshot agentDir (a stable public export) before the delete and restore it before the next deploy, and loadOrGenerateKey comes back isNew: false with the same keypair -- so the fix is a sidecar-side snapshot/restore, not a vendor or an upstream ask. Standalone proof only; wiring this into workflow-host-wiring's existing reclaimDirs-aware undeploy/deploy hooks is the actual feature build.
3 tasks
Contributor
Author
|
Superseded by #293, which wires this into the real undeploy/redeploy hooks and carries equivalent tests against the unmodified |
TheGreatAxios
added a commit
that referenced
this pull request
Aug 22, 2026
CL-6581: the published @intx/hub-agent package destroys an agent's reconnect-challenge keypair on every undeploy, hibernate or not, which is the documented root cause of CL-6203/CL-6044. These tests exercise a snapshot-before-delete/restore-before-redeploy technique (proved viable in PR #291) against the real, unmodified @intx/hub-agent key/repo stores, and end-to-end through createSidecarDeployRouter's actual undeploy/deploy hooks: a hibernate teardown must preserve the identity across a real redeploy, a reclaiming teardown must still destroy it, a broken snapshot must report loudly instead of failing silent, and an orphaned snapshot must be reaped past its retention window. The shared lifecycle fixture gains an optional real-key-store override (needed because its default fake never touches disk) and its default fake now creates a real agentDir so an unrelated hibernate-teardown test does not trip the vault's ordering-broke detector.
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
Go/no-go spike for CL-6581 (blocked on: CL-6239 — upstream ask to make
@intx/hub-agent's undeploy path non-destructive so idle-sleep can suspendan agent instead of terminate-and-relaunch).
Finding: no upstream ask, no vendoring required. A sidecar-side fix is
sufficient.
@intx/hub-agentis consumed as a published npm package (vendor/intx/hub-agentdoes not exist — only 7 other
@intx/*trees are vendored, perVENDORED.md).Its
AgentKeyStorepersists each agent's reconnect-challenge Ed25519 keypairunder
agentDir(dataDir, address)/keys/, andhandleAgentUndeploy(
ws/hub-link.js) unconditionally callssessions.deleteAgentDir→repoStore.remove→fsp.rm(agentDir, { recursive: true })on everysendAgentUndeploy, hibernate reason or not — that whole call chain livesinside the published package, unreachable from this repo without vendoring.
apps/sidecar/src/workflow-host-wiring/index.ts'sundeploy(frame)computesreclaimDirs = frame.reason !== IDLE_HIBERNATE_UNDEPLOY_REASONand uses it toskip deleting the workflow-deployment record / releasing the slug — but it has
no power over the key directory, since that deletion happens in
hub-link.jsafter this hook returns, regardless of what the hook did.
agentDir(dataDir, address)is a stable public export of@intx/hub-agent.This PoC proves, against the real unmodified package, that a caller can
snapshot the whole directory before the destructive
remove()and restore itbefore the next
deploy, andloadOrGenerateKeycomes backisNew: falsewith the identical keypair. No fork, no vendor, no upstream ask needed —
extend the existing
reclaimDirs-gated hook to snapshot/restoreagentDir.What this PR is (and isn't)
This is a standalone proof-of-concept test only — it exercises
@intx/hub-agent's real APIs against a tmp dir to establish the techniqueworks. It does not wire the snapshot/restore into the actual
workflow-host-wiringundeploy/deploy hooks, build idle-sleep, or touchlifecycle/
packages/folded-runs— that's the real feature build, owned by aseparate lane, once this go/no-go lands.
Test plan
bun test apps/sidecar/test/suspend-key-preservation.poc.test.ts— 2/2 passremove)isNew: false+ identical keypair bytes post-restoretsc --noEmitandeslintclean on the new fileLinear: CL-6581 (spike ticket, links CL-6239)