fix(cloud): reuse the existing agent in first-run onboarding instead of 503 dead-end during worker outage#15541
Merged
Conversation
…of dead-ending 503 during a provisioning-worker outage Native cloud onboarding provisioned+503'd for a user whose one healthy agent needed no provisioning at all (#15516 Bug B). Two stacked defects: - client: #15491 made the reuse pick running-only, so ANY transiently non-running row (starting/stopped/status churn during the very outage that 503s creates) fell through to a fresh create; the reuse branch's cold-boot wait had become unreachable dead code. The pick now prefers running, then falls back to the newest NON-TERMINAL row routed through waitForCloudAgentRunning (which kicks a resume and re-reads the fresh post-wake record — the correct guard against binding a stale pointer, preserving #15491's intent). A remembered preferAgentId is honored whenever non-terminal, so we never silently swap a user onto a different agent's conversations. - server: POST /api/v1/eliza/agents ran the provisioning-worker health gate BEFORE createAgent's idempotent reuse, so a heartbeat gap 503'd even callers whose create would have been served by reuse (no job enqueued). The route now peeks reuse candidacy (read-only repository mirror of the guard predicate) and only gates a create that would genuinely enqueue; forceCreate always stays gated. Repairs 3 pre-existing red tests in the mock-cloud connect suite (the running-only pick broke the stopped-agent reuse cases on develop) and adds coverage: remembered-agent wake, all-terminal create fall-through, and route-level gate-vs-reuse ordering (reuse-skips-gate, no-agent still 503s fail-closed, forceCreate never skips). Fixes #15516 (Bug B)
Contributor
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
7 tasks
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.
What & why (#15516 Bug B)
On a real LP3 device, native cloud onboarding provisioned + 503'd and dead-ended for a user whose one healthy agent (running/ready/pairable) needed no provisioning at all. Two stacked defects, both fixed here:
Client — the reuse pick refused every non-running agent
#15491 changed
pickPreferredCloudAgentto running-only. Any transiently non-running row (starting/stopped/status churn during the very outage that 503s creates) produced zero reuse candidates → first-run fell through to a fresh create. The reuse branch's cold-boot wait (waitForCloudAgentRunning) had become unreachable dead code — a pick was always running, so the wait never fired.Fix: pick prefers running, then falls back to the newest non-terminal row, routed through
waitForCloudAgentRunning— which kicks a resume and resolves with the fresh post-wake record (post-wake URLs). That is the correct guard against #15491's stale-pointer concern (never bind a stale row directly), instead of refusing reuse outright. Safe because shared rows are bornrunning(eliza-sandbox.tscreate:shared → "running"), so a non-running pick always has a container to wake. A rememberedpreferAgentIdis honored whenever non-terminal — silently binding a different agent would swap the user's conversations/memories.Server — the worker-health gate ran before its own reuse safety-net
POST /api/v1/eliza/agentsrancheckProvisioningWorkerHealth()beforecreateAgent's idempotent reuse — so during a heartbeat gap (real outage in the CP journal: Redis socket timeouts 20:26–20:40, key TTL 60s; zero provision jobs 20:00–21:33, all pre-enqueue rejects) even callers whose create would be served by reuse got 503.Fix: the route peeks reuse candidacy first (read-only repository mirror of the guard predicate, documented as such) and only gates a create that would genuinely enqueue.
forceCreatealways stays gated (it opts out of reuse by definition). Fail-closed behavior for no-agent orgs is unchanged.Proof
The existing mock-cloud connect suite was RED on develop — 3 tests fail on the unfixed code with the exact bug signature (create POST fired instead of reusing the stopped agent):
With this fix: 9/9 pass (incl. 2 new: remembered-agent wake priority; all-terminal → create fall-through).
Route suites (bun): 12/12 idempotency (3 new #15516 ordering tests), 5/5 orphan-cleanup, 2/2 warm-pool (per-file, matching CI; the combined-single-process run has pre-existing cross-suite mock.module interference on develop too — verified 0-pass/2-fail on untouched develop). New ordering coverage:
checkProvisioningWorkerHealthnot called)forceCreate+ reusable agent → 503 (forceCreate never skips the gate)Biome clean;
typecheckclean forpackages/ui,packages/cloud/shared,packages/cloud/api(filtered to touched files).Evidence rows
PROVISIONING_WORKER_UNHEALTHYbody).Residual (separate, flagged on #15516): the
/provisionroute's healthy-agent 200 fast-path requiresbridge_urlANDhealth_url— a healthy agent missing either still falls into the gate; that's #15477-adjacent (provisioning-durability lane).Fixes #15516 (Bug B) · root cause + tracer evidence: #15516 (comment) ·
[cloud-agent]Evidence rows
N/A - no rendered UI change (client flow-logic + API route ordering); on-device before/after is the qa device-lane re-verify per #15516.N/A - no UI surface changed.N/A - no user-visible web/desktop flow change; the LP3 on-device walkthrough is the qa device lane's re-verify step tracked on #15516.N/A - no agent/action/provider/prompt/model behavior change; control-plane transport only.N/A - no media/screenshot artifacts in this change.