Skip to content

Prevent orphaned Harper processes after test runner crashes - #30

Draft
kriszyp wants to merge 4 commits into
mainfrom
fix/reap-harper-on-runner-death
Draft

Prevent orphaned Harper processes after test runner crashes#30
kriszyp wants to merge 4 commits into
mainfrom
fix/reap-harper-on-runner-death

Conversation

@kriszyp

@kriszyp kriszyp commented Aug 21, 2026

Copy link
Copy Markdown
Member

Detached Harper process trees are now supervised by a harness-owned process that detects runner death through a kernel pipe and reaps the tree after SIGKILL, SIGHUP, or a hard crash. This prevents orphaned Harper instances from permanently holding ports while preserving graceful killHarper teardown and the configured Node/Bun runtime.

For the human reviewer

  1. Supervisor sidecar: This uses one idle Node supervisor per Harper instance because portable Node exposes neither parent-death signals nor Windows Job Objects. A shared reaper would reduce process cost but could kill a recycled PID on Windows; changing this later would require replacing the spawn topology.
  2. Lifecycle handle identity: ctx.harper.process remains the handle lifecycle APIs consume but now identifies the supervisor; ctx.harper.harperPid exposes the managed runtime PID. A separate lifecycle-handle type would be clearer but would break existing ChildProcess consumers.
  3. Fail-closed supervision: An unhealthy supervisor kills Harper rather than allowing an unsupervised instance to continue. Reversing this policy is local, but would deliberately reopen the orphan risk.
  4. PID optionality: harperPid is optional on the context type for compatibility with hand-built contexts, even though successful package-managed startup always supplies it. Making it required would strengthen types but break existing test doubles.
  5. Verification boundary: The regression uses real OS processes, signals, descendants, and TCP listeners with a fake Harper script rather than adding a real-Harper CI dependency. The existing Windows matrix is the remaining platform proof for fd-3 pipe behavior; expanding to a real Harper smoke later is straightforward.

Verification

  • New integration route: runner SIGKILL reaps the supervised Harper tree and releases its ports launches a separate runner, supervised fake Harper, descendant, and two real TCP listeners; it asserts both PIDs disappear and both ports rebind. The same fixture covers SIGHUP, unexpected supervisor death, and graceful teardown ordering.
  • Fails-on-base: the focused SIGKILL test against origin/main fails with Harper ... should die with its runner; it passes at this head.
  • npm run check — passed.
  • npm run build — passed; package dry-run includes dist/harperSupervisor.js and its declaration.
  • npm test — 23/23 passed.
  • HARPER_RUNTIME=bun node --test --test-name-pattern='runHarperCommand resolves|runner SIGKILL reaps' test/harperLifecycle.test.ts — 2/2 passed.
  • Windows-specific pipe and taskkill /T behavior is exercised by the unskipped GitHub Actions matrix after push.

Refs #29

Co-Authored-By: GPT-5 Codex noreply@openai.com

🤖 Generated with OpenAI Codex

Complexity: complicated

Review-Coverage: authored=codex; ran=claude,gemini; declined=cursor-grok,cursor-composer,domain; rounds=3 @ bc5fbb4

Human-Review-Need: 4 @ bc5fbb4

kriszyp and others added 4 commits August 21, 2026 07:47
Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Co-Authored-By: GPT-5 Codex <noreply@openai.com>
@kriszyp
kriszyp requested a review from heskew August 21, 2026 14:08
gemini-code-assist[bot]

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant