fix(subprocess): tree-scoped escalation and byte-exact tails (Codex round 1)
(A1) terminate()/dispose()/service teardown keyed on direct-child settlement could leak a TERM-trapping descendant that outlived the leader (Codex reproduced it with a disowned trap-SIGTERM helper). kill()/terminate() now gate on tree liveness instead of outcome settlement; the SIGKILL escalation timer survives settle (unref'd, re-probing the tree); dispose's tier quiescence is whole-tree exit via a bounded waitForExit; the service's live set releases handles only when their tree is gone, and its teardown awaits tree exit. Three new suites pin the survivor scenarios end to end (terminate, dispose, service teardown). (A2) the escalation branch is now real tested behavior — its ignore is gone; the one remaining signalTree guard ignore states why it is unreachable through the handle verbs. (A3) docs contradictions fixed: the impl README's stale POSIX-only bullet now states the contained best-effort Windows tree story; the lsp-local README no longer claims taskkill failures stay visible (containment + the tree-liveness wait is the actual contract); the architecture tables (en+zh) list all three consumer families. (B1) OutputCollector keeps a byte-exact tail across uneven chunk boundaries (trim the head chunk instead of dropping it whole) — the LSP diagnostic-tail contract; pinned by a cross-chunk test. (B2) the subagent-acp coverage ignore is narrowed to exactly the never-settling success arm.
This commit is contained in:
@@ -20,7 +20,7 @@ No direct invalidation; the named consumers own any request-prefix changes.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **POSIX-only** — detached process groups, group kills, and SIGTERM→SIGKILL escalation are hardcoded; Windows is unsupported.
|
||||
- **Windows tree support is best-effort and untested in CI** — termination routes through `taskkill /PID <pid> /T /F` with all outcomes contained (absent tree, races, missing binary), and liveness falls back to the direct-child boundary; the suites cover the routing through an injected runner only, and `packages/subprocess/*` is excluded from the Windows test matrix.
|
||||
- **The credential scrub is a name heuristic** — `*KEY*`/`*SECRET*`/`*TOKEN*` only; differently-named secrets (e.g. `*PASSWORD*`) pass through, and a whitelist for over-scrubbed vars is noted future work.
|
||||
- **Completed spill files are not deleted** — bounded full-output recovery files (and the private per-process spill dir) accumulate under the OS tmpdir until something external cleans them; oversize incomplete spills are discarded and deletion is attempted immediately, but a cleanup failure can leave a bounded file behind.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user