| fix(jobs): close stop() race condition; drop useless \$ escapes (#288)
* fix(benchmark): drop useless \$ escapes in tdd-eval prompt string
The h1 task description string used \${file}::\${fullName} inside a
regular "..." literal. The backslashes are no-ops (JS quietly drops
unrecognized escapes in regular strings) but trip CodeQL's
js/useless-regexp-character-escape rule. Identical resulting string,
cleaner source.
* fix(jobs): wait for actual close event after SIGKILL, not a fixed timer
stop() had two timing races. Both manifested as the same flake — the
returned snapshot's running flag could still be true even though the
test (and the user) just told us to stop the job.
1. SIGKILL phase used a fixed 800ms timer, then returned regardless of
whether the OS had reaped the process tree. Under Windows scheduler
load, taskkill /T /F on a 3-level tree (npm → node → vite) can take
over a second to propagate before Node's close event fires.
2. SIGTERM phase awaited readyPromise, which is dual-purpose: it
fires on either a startup ready-signal regex match OR child exit.
If the job had already matched a ready signal, readyPromise was
already resolved, so the SIGTERM grace race short-circuited
immediately and we'd jump to SIGKILL with zero pause.
Adds closedPromise — fires only on close/error, never on ready
signal — and uses it for both the SIGTERM grace race and the post-
SIGKILL wait, with a 5s ceiling on the latter so a wedged kernel
can't hang us indefinitely. | 23 天前 |