Files
Bo 142b7ee841 Bounded, cancellable eval subprocess runner with process-group reaping (#1010)
## Summary

Bead `age-eval-subprocess-lifecycle-uf9d6` — the 2026-07-24 Go audit's
G2 program, the last OPEN High-adjacent residue. New
`cli/internal/procrun` runner, migrated onto all four unbounded sites.

**The runner:**
- Head+tail bounded capture: fixed peak memory regardless of child
output; keeps draining so the child never blocks on a full pipe;
under-cap output byte-identical; over-cap preserves true head and true
tail with a discard marker.
- `Run(ctx, ...)`: process-group start (`Setpgid` / windows process
group), cancel kills the group, 3s `WaitDelay` so `Wait` can't hang on
pipes a grandchild holds, and — post-review — the group is reaped
**unconditionally after Wait on every path**, so a descendant surviving
a normal child exit is still killed (witnessed: backgrounded no-`wait`
sleeper reaped).
- Unix ESRCH race mapped to `os.ErrProcessDone` (50×
completion-vs-cancel race under `-race`: a completed command never
reports an error). Windows `taskkill` bounded by its own 5s timeout with
the best-effort no-Job-Object guarantee documented rather than faked.

**Migrated sites:** goals `MeasureOneContext` (SIGINT child-tracker
hooks preserved), gates `ScriptRunner` (gains group-kill + WaitDelay,
4KiB LogTail preserved), eval `executeCaseCommand` and expectations
autodetect — caller ctx threaded end-to-end via
`RunSuiteContext`/`RunBaselineABContext`/`RunContextABContext` +
`CoreRuntime`; no `context.Background()` remains on these paths.
Cancellation is semantic: guards before the suite, before each case,
**and after the loop** (a cancel during the final/only case is terminal,
never scored — single-case witness), A/B never starts its second leg
cancelled. Start-failure error text verified byte-identical at all three
consumer sites. Live-runtime capture and the adapter RunStats call are
explicitly out of scope (noted in commit).

## Validation

- `go build`/`go vet` clean; full `go test ./...` green; `-race
-count=1` clean on procrun/eval/goals; golangci 0 issues on five touched
packages; `GOOS=windows` build ok
- Cross-family review two rounds: round 1 five findings all fixed
(always-reap, bounded windows cancel, ESRCH race, semantic cancellation,
error-text compat); round 2's one residual (final-case cancellation)
fixed with witness

Tracker: `age-eval-subprocess-lifecycle-uf9d6`
2026-07-29 14:28:10 +00:00
..