Daemon startup: wait for a live daemon instead of a fixed 15 s deadline on slow or overloaded hosts
I maintainer di solito rispondono entro 1 giorno
Una pull request collegata è già stata integrata.
- #3791 di @thymikee — integrata
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- node.js, typescript
Direzione di ricerca
Start with startLocalDaemon and waitForDaemonStartup in src/daemon-client/daemon-client-lifecycle.ts; trace how startup results, timeouts, and daemon logs are handled. Then read the existing lifecycle and startup-race tests and the daemon environment-variable documentation. Done when the completion conditions pass, including typed failure reasons, configurable timing, progress reporting, and updated help or docs.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Purpose
On a slow or overloaded host, the CLI kills a healthy daemon that is still starting. The result is daemon_startup_failed, and the run fails before any work starts. This happens on any CI that can clog: shared macOS runners, small Linux containers, Windows runners, and nested virtualization. It also happens on a developer machine under load. A slow host must make startup slower, not fail it.
#3342 records this failure class (more than 12 instances on unrelated diffs since 2026-10-08; re-runs at the same head pass). This issue is the fix contract for that class.
Current behavior (origin/main)
startLocalDaemon in src/daemon-client/daemon-client-lifecycle.ts:
- It sets one wall-clock deadline:
DAEMON_STARTUP_TIMEOUT_MS = 15_000(line 83, used at line 480). waitForDaemonStartup(line 818) polls until the daemon publishes a reachabledaemon.json, or until the process exits, or until the deadline.- At the deadline, the client retires the daemon, even when the process is alive. A
timeoutresult never retries (retryis true only forearly_exit), soDAEMON_STARTUP_ATTEMPTS = 2does not help. Every report showsstartupAttempts: 1. - No setting can change the 15 s budget.
Evidence from run 39019020372 (PR #3760, 2026-10-17):
- The step
pnpm clean:daemontook 70 s on that runner, which shows that the host was overloaded. - The CLI spawned daemon pid 6849 at 09:30:03. The client killed it 15 s later (
cleanupResults: retired / forced / exited). daemon.logwas empty (0 bytes), so the daemon did not reach its first log line. The process was alive but did not get enough CPU.- The same signature occurred on
refactor/host-environment-root(run 39008970059) andfix/provider-not-registered(run 38993655494), which do not contain that PR's commits.
Required behavior
-
Wait for a live daemon. While the spawned daemon process is alive and has not exited, the client continues to wait for registration. A slow start is not a failure.
-
Fail fast on a real failure. If the daemon process exits before it registers, the client reports the failure immediately, as it does now (
early_exit,unproven). -
Keep a hard ceiling. A daemon that stays alive but never registers must not hang the client. The client stops at a ceiling. The default ceiling must be large enough for an overloaded CI host (proposal: 120 s). Measure the slowest successful startup in CI logs before you choose the number.
-
Show progress. The daemon writes startup phase markers (for example
spawned,modules-loaded,lock-acquired,listening,registered) with timestamps, to the place the client already reads (daemon.logtail or the startup metadata). The client can then tell "slow but progressing" from "stuck". If a marker shows progress, the client keeps waiting up to the ceiling. If no marker appears for a long time, the client can stop earlier than the ceiling. Put the stall window next to the ceiling, as one constant. -
Make the budget configurable. An environment variable sets the ceiling, for example
AGENT_DEVICE_DAEMON_STARTUP_TIMEOUT_MS. It applies to the CLI, MCP, and the Node client, because all three usestartLocalDaemon(viaensureDaemon(), #3765 and #3766). Document it with the other daemon environment variables. Do not add CI auto-detection. Rule 1 makes the default safe on every host. -
Use typed failure reasons.
details.kindstaysdaemon_startup_failed. A newdetails.reasontells the caller what happened:startup-exited: the process exited before it registered.startup-stalled: the process is alive, but no progress marker appeared within the stall window.startup-ceiling: the process made progress, but did not register before the ceiling.
Each reason has its own hint. For
startup-stalledandstartup-ceiling, the hint says that the host can be overloaded, and names the environment variable. Callers branch ondetails.reason, never on the message. -
Record timings. The failure details include the time of each phase marker that the client saw, and
startupTimeoutMsshows the effective ceiling.
Example failure payload:
{
"code": "COMMAND_FAILED",
"message": "Failed to start daemon",
"details": {
"kind": "daemon_startup_failed",
"reason": "startup-stalled",
"startupTimeoutMs": 120000,
"phases": { "spawned": 0, "modules-loaded": 41250 },
"hint": "The daemon is alive but made no startup progress for 60 s. The host can be overloaded. Retry, or raise AGENT_DEVICE_DAEMON_STARTUP_TIMEOUT_MS."
}
}
Completion conditions
- A test starts a daemon that is alive but slow (for example a test-only startup delay of 20 s, longer than the old 15 s budget). Startup succeeds, and the client does not kill the daemon.
- A test starts a daemon that exits during startup. The client reports
startup-exitedwithin 1 s after the exit. - A test starts a daemon that stays alive and writes no phase marker. The client reports
startup-stalledat the stall window, not at the ceiling. - A test sets the environment variable to a small value and sees
startup-ceilingwith the newstartupTimeoutMs. - The existing lifecycle and startup-race tests pass without change in meaning.
- The
daemon-clienthelp or user docs name the environment variable and the three reasons. - After the change merges, #3342 gets a
Current state:comment. Then the iOS Smoke preflight step is observed for one week. The issue closes if nodaemon_startup_failedwith reasonstartup-stalledorstartup-ceilingappears below the new ceiling.
Out of scope
- Re-running CI lanes to hide the failure.
- The slow
pnpm clean:daemonstep in.github/workflows/ios.yml(70 s on an overloaded runner). That is a separate CI cost. Report it in #3342 if it repeats.
Dependencies
- #3342: failure-class log and evidence.
- #3765 and #3766 (merged):
ensureDaemon()and attach mode. They callstartLocalDaemon, so the change applies to all clients.
- Lingua principale
- TypeScript
- Stelle
- 5k
- Fork
- 334
- Merge medio
- 12h 2m
- PR unite (30g)
- 706
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di callstack/agent-device
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
callstack/agent-device#3792 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
macOS helper audio-probe always reports -90 dBFS: AVAudioPCMBuffer frameLength set after the copyApertabug ready-for-agent
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
callstack/agent-device#3771 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
callstack/agent-device#1869 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
callstack/agent-device#3801 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 49/100
callstack/agent-device#3800 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di callstack/agent-device
Issue simili
-
bug priority: P2
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
wayfinder:task
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
I maintainer di solito rispondono entro 1 giorno
-
bug customer-reported data-plane question Service Attention Storage
Difficoltà 2/5 1-3 ore Idoneità per principianti 69/100
Azure/azure-rest-api-specs#47397 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Claude thinking budget can shrink capped Haiku responses to 2,048 tokensForse già presa @DavyMassoneto l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
diegosouzapw/OmniRoute#17109 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
paperclipai/paperclip#16785 ·
I maintainer di solito rispondono entro 1 giorno