Problem
src/runner/server.ts awaits scenario.run(ctx) with no bound. The client runner already has a 30s per-scenario timeout (src/runner/client.ts), but on the server side any scenario that blocks on a wedged server-under-test (a server that accepts the TCP connection but never responds to an initialize POST, a tools call, or an SSE read) stalls the entire suite run indefinitely.
#316 bounded one hang class (the session-termination DELETEs in teardown, via AbortSignal.timeout), but that is call-site depth: every raw fetch in every scenario would need the same treatment to cover the rest.
Proposal
Bound scenario.run at the runner layer, mirroring the client runner's per-scenario timeout (probably with the existing --timeout option applying to server mode too). Per-call bounds like #316's then become defense-in-depth rather than the only protection.
Repro
Point server --scenario server-initialize (pre-#316) at a mock that accepts connections but never responds: the run never completes.
Problem
src/runner/server.tsawaitsscenario.run(ctx)with no bound. The client runner already has a 30s per-scenario timeout (src/runner/client.ts), but on the server side any scenario that blocks on a wedged server-under-test (a server that accepts the TCP connection but never responds to an initialize POST, a tools call, or an SSE read) stalls the entire suite run indefinitely.#316 bounded one hang class (the session-termination DELETEs in teardown, via
AbortSignal.timeout), but that is call-site depth: every rawfetchin every scenario would need the same treatment to cover the rest.Proposal
Bound
scenario.runat the runner layer, mirroring the client runner's per-scenario timeout (probably with the existing--timeoutoption applying to server mode too). Per-call bounds like #316's then become defense-in-depth rather than the only protection.Repro
Point
server --scenario server-initialize(pre-#316) at a mock that accepts connections but never responds: the run never completes.