Files
orca/tests/tools/omp-relay-close-lifecycle.md
Neil 8c6ae79e94 fix(relay): stop detached tools on immediate terminal close (#20645)
* fix(relay): sweep detached tools on immediate terminal close

* test(relay): reject failed process cleanup queries
2026-09-17 20:58:27 -07:00

68 lines
4.1 KiB
Markdown

# OMP relay-host immediate-close probe (#9530)
This opt-in probe uses a real installed OMP binary and native PTYs behind production
`PtyHandler` spawn/data/shutdown handlers. The dispatcher is an in-process test
transport; no SSH connection or rendered client is exercised. OMP source is read-only.
```sh
ORCA_BACKGROUND_LAUNCH=1 ORCA_OMP_PROBE_BINARY=/absolute/path/to/omp \
ORCA_OMP_PROBE_SHELL=/bin/bash \
node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts \
tests/tools/omp-relay-close-lifecycle.test.mjs
```
The test defaults to zsh on macOS and bash on Linux. Windows is skipped. It needs
existing native node-pty dependencies; do not install or rebuild as part of the probe.
HOME, user profile, XDG roots and OMP/PI agent roots are disposable, profiles cleared,
and zsh inheritance fenced to the disposable root. No model request is made. The
probe runs `! /bin/sleep 120`, records exact shell/OMP/tool process rows, requests
immediate close, and observes those PIDs independently of the relay inventory.
Matching PID/start-time/group identities bound leftover cleanup. Reports and capped
terminal transcripts stay in `.bench-fixtures/omp-relay-close-*`.
## Measured on macOS with OMP 18.1.18
At source base `93c370246388`, bash mode leaves sleep PID 43156, PGID 43156, alive
and reparented to PID 1 after root PID 42902 and OMP PID 42949 exit. The zsh control
exits cleanly: OMP uses a headless PTY for zsh/fish user-shell tools, while bash
uses its embedded-shell subprocess path. Thus an external command alone does not
determine the process lifetime; the configured user shell matters.
With the correction, the same bash probe leaves none of its captured PIDs present.
This is detached-tool leakage, not proof of the original foreground-OMP-survives
report. The local-provider/daemon correction is PR #20642; this probe and correction
cover the separate direct-relay backend.
## Reliability contract
- Invariant: `terminal-session.explicit-close-retirement`. Explicit immediate close
captures still-parented detached descendants before root termination, preserves
the exact host owner through physical exit, and cannot attach/adopt that owner
while the close is pending. A concurrent close joins the same operation.
- Failure source/oracle: actual OMP external sleep survives the bash-mode relay
close before the fix; independently queried owned PIDs are absent afterward.
Unit tests also cover pending attachment/adoption/create replay, natural exit
during capture, signal failure/retry, retained claims during initial promotion,
and close completing while attachment awaits a source checkpoint.
- Gate: the existing experimental explicit-close gate's descendant/backend tests,
relay lifecycle suites and this opt-in real-PTY probe. Live SSH transport and
rendered client flows remain explicit validation gaps.
- Budget: one existing bounded process-table capture (one-second timeout, 32-MiB
cap), plus one bounded identity recheck after the two-second grace when there
are descendants. Same-turn captures coalesce; no recurring polling is added.
- Authority: the execution host does all process inspection/signaling. Pending-close
refusal carries no proven-exited marker; it is not evidence of process death.
No new RPC fields/opcodes or required capabilities. Older clients receive an
ordinary failed attach while close is pending, not a successful doomed attachment.
- Scope: every immediate POSIX relay close, including still-parented intentionally
detached jobs. Graceful close, disconnect grace, keep-alive and fatal-exit/dispose
policies are unchanged. Windows retains its immediate force-kill path and now
rejects attachment during the physical-exit wait. Folder workspaces and worktrees
use the same PTY identity, without repository metadata checks.
- Gaps: macOS runtime evidence only; Linux/Windows/WSL runtime, live SSH/mobile and
mixed-version clients are not exercised. Children reparented before capture and
same-second identity ambiguity retain the incumbent cleanup limitations.
Mock-PTY suites isolate the sweep: their fake PIDs often equal the test runner's PID
and must never reach the real host process table or descendant signals.