On cancellation/timeout the opencode backend closed the stdout read end
immediately, leaving the child writing into a closed pipe. Every write then
returns EPIPE and, per anomalyco/opencode#33653, can spin an orphaned process
at 100% CPU — surfacing as high idle CPU after a cancelled task or daemon
restart (MUL-3655).
Cleanup now runs opencode in its own process group and, on cancel, drives a
graceful group-wide SIGTERM → grace → SIGKILL, closing the stdout pipe only as
a last-resort unblock once the tree has been signalled (SIGKILL is uncatchable,
so no member can write again — no EPIPE window). The group signal also reaps
tool subprocesses opencode spawned instead of orphaning them. WaitDelay remains
the hard backstop.
Adds unix tests covering the graceful path and the SIGTERM-ignored → SIGKILL
escalation, asserting the whole process group is reaped and the run never
deadlocks on the scanner. Windows behaviour is unchanged (no process groups).
Co-authored-by: J <j@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
* fix(daemon): suppress agent terminal windows on Windows (#1471)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add hideAgentWindow to detectCLIVersion and avoid SysProcAttr overwrite
- Add missing hideAgentWindow(cmd) call in detectCLIVersion (claude.go:554)
so --version checks don't flash console windows on Windows.
- Refactor hideAgentWindow to preserve existing SysProcAttr fields
instead of overwriting the entire struct.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>