| 255 | }; |
| 256 | |
| 257 | const waitForReadyPort = (proc: Subprocess<"ignore", "pipe", "pipe">): Promise<number> => |
| 258 | // oxlint-disable-next-line executor/no-promise-reject -- boundary: standalone build-time smoke harness, no Effect runtime |
| 259 | new Promise((resolveReady, rejectReady) => { |
| 260 | const deadline = setTimeout(() => { |
| 261 | // oxlint-disable-next-line executor/no-promise-reject, executor/no-error-constructor -- boundary: standalone smoke harness reporting a build-time timeout |
| 262 | rejectReady(new Error(`daemon did not announce ready within ${READY_TIMEOUT_MS}ms`)); |
| 263 | }, READY_TIMEOUT_MS); |
| 264 | |
| 265 | let stdoutBuf = ""; |
| 266 | const decoder = new TextDecoder(); |
| 267 | const reader = proc.stdout.getReader(); |
| 268 | |
| 269 | const stderrReader = proc.stderr.getReader(); |
| 270 | void (async () => { |
| 271 | while (true) { |
| 272 | const { value, done } = await stderrReader.read(); |
| 273 | if (done) return; |
| 274 | process.stderr.write(`[executor-stderr] ${decoder.decode(value)}`); |
| 275 | } |
| 276 | })(); |
| 277 | |
| 278 | void (async () => { |
| 279 | while (true) { |
| 280 | const { value, done } = await reader.read(); |
| 281 | if (done) { |
| 282 | clearTimeout(deadline); |
| 283 | // oxlint-disable-next-line executor/no-promise-reject, executor/no-error-constructor -- boundary: standalone smoke harness, stdout-closed surfaced as rejection |
| 284 | rejectReady(new Error("daemon stdout closed before ready")); |
| 285 | return; |
| 286 | } |
| 287 | const chunk = decoder.decode(value); |
| 288 | process.stdout.write(`[executor-stdout] ${chunk}`); |
| 289 | stdoutBuf += chunk; |
| 290 | const match = /Daemon ready on http:\/\/(?:\[[^\]]+\]|[^:\s]+):(\d+)/.exec(stdoutBuf); |
| 291 | if (match) { |
| 292 | clearTimeout(deadline); |
| 293 | resolveReady(parseInt(match[1]!, 10)); |
| 294 | return; |
| 295 | } |
| 296 | } |
| 297 | })(); |
| 298 | }); |
| 299 | |
| 300 | const completePausedResult = async ( |
| 301 | client: Client, |