fix(engine): make global pause actually stop in-flight verification

Hitting Stop (globalPause) disposed the AI merge agent session but left
the spawned `pnpm test` / `pnpm build` child processes running until
they finished naturally. With recurring flaky-test loops at Step 5,
that meant Stop had no visible effect — new test runs kept piling up
across multiple worktrees.

Two gaps:
- project-engine.ts onGlobalPause never called mergeAbortController.abort(),
  so subsequent verification commands (gated by the signal) weren't cancelled.
- merger.ts execWithProcessGroup only listened to its own internal
  timeout — passing an AbortSignal had no effect on the in-flight
  child process group.

Fix: abort the controller on global pause, and have execWithProcessGroup
SIGTERM/SIGKILL the detached process group when its signal aborts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-26 20:51:40 -07:00
parent 642d76a9ea
commit a2f23eae29
2 changed files with 49 additions and 10 deletions

View File

@@ -1327,9 +1327,17 @@ export class ProjectEngine {
// ── Settings event listeners ──
private wireSettingsListeners(store: TaskStore): void {
// 1. Global pause — terminate active merge session
// 1. Global pause — terminate active merge session AND abort any running
// deterministic verification (pnpm test/build). The abort controller gates
// both the AI merge agent and the spawned child processes; without it,
// verification commands keep churning until they finish naturally.
const onGlobalPause = ({ settings, previous }: { settings: Settings; previous: Settings }) => {
if (settings.globalPause && !previous.globalPause) {
if (this.mergeAbortController) {
runtimeLog.log("Global pause — aborting in-flight merge verification");
this.mergeAbortController.abort();
this.mergeAbortController = null;
}
if (this.activeMergeSession) {
runtimeLog.log("Global pause — terminating active merge session");
this.activeMergeSession.dispose();