Bug: synchronous worker dispatch has no timeout — hung worker hangs the step forever
Summary
step.timeout_ms is only enforced on the async path (async step polling, src/engine.zig:1611) and for agent-node turn budgets (turn_timeout_ms, src/engine.zig:1234). The synchronous HTTP dispatch path (executeTaskNode → dispatchToWorker) performs a std.http fetch with no deadline: std.http.Client.fetch in this Zig version exposes no timeout option, and none is simulated. A worker that accepts the connection and never responds hangs the step — and the run — indefinitely.
Reproduction
- Point a step at a mock worker that accepts the TCP connection and sleeps (never responds).
- Set
timeout_ms on the step.
- The step stays
executing forever; timeout_ms is ignored. The run never fails.
Expected behavior
timeout_ms must be enforced on synchronous dispatch too (thread + poll wrapper around the fetch is a known workaround for the missing deadline API).
- Two additional constraints once timeouts exist:
- A timeout is a step budget overrun, not a worker fault — it must not flow into the generic dispatch-failure path that calls
markWorkerFailure. Otherwise N over-budget runs trip the worker circuit breaker, and subsequent unrelated runs die with "no eligible worker".
- The timed-out step should fail the run (or retry per policy), not wedge it.
Bug: synchronous worker dispatch has no timeout — hung worker hangs the step forever
Summary
step.timeout_msis only enforced on the async path (async step polling,src/engine.zig:1611) and for agent-node turn budgets (turn_timeout_ms,src/engine.zig:1234). The synchronous HTTP dispatch path (executeTaskNode→dispatchToWorker) performs astd.httpfetch with no deadline:std.http.Client.fetchin this Zig version exposes no timeout option, and none is simulated. A worker that accepts the connection and never responds hangs the step — and the run — indefinitely.Reproduction
timeout_mson the step.executingforever;timeout_msis ignored. The run never fails.Expected behavior
timeout_msmust be enforced on synchronous dispatch too (thread + poll wrapper around the fetch is a known workaround for the missing deadline API).markWorkerFailure. Otherwise N over-budget runs trip the worker circuit breaker, and subsequent unrelated runs die with "no eligible worker".