[PR #1763] [MERGED] fix(hopper): let failed one-shot commands exit while retaining a lease #4803

Closed
opened 2026-10-31 00:55:14 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1763
Author: @kaoru0822-kitauji
Created: 10/11/2026
Status: ✅ Merged
Merged: 10/11/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/hopper-failed-session-exit


📝 Commits (2)

  • 610bccb fix(hopper): let failed one-shot commands exit while retaining a lease
  • e11d131 test(hopper): remove only this test's stale lease sockets

📊 Changes

2 files changed (+132 additions, -0 deletions)

View changed files

📝 src/hopper/HopperTargetLease.ts (+4 -0)
➕ tests/boundary/cli/hopperLaunchFailureCli.test.ts (+128 -0)

📄 Description

Fixes #1751.

Problem

When Hopper startup fails and cleanup cannot be confirmed (for example, the launcher helper exits 2 with an Automation denial), REA keeps the target lease as it should. But the lease's net.Server listener stayed referenced. So rea analyze ... --provider hopper printed its final cleanup_incomplete JSON and then never exited. While that process stayed alive, every retry on the same target got "already open in REA session …".

Change

tryAcquireLease now calls unref() on the lease listener. The lease still lasts exactly as long as its owning process:

  • MCP: a live server still holds the lease, and still refuses competing opens, until cleanup succeeds or the process ends.
  • One-shot CLI: exits with status 1 and still reports cleanup_incomplete, the retained runtime root, and the launcher diagnostics.
  • Next acquirer: recovers the stale socket the exited process leaves behind, using the existing stale-lease recovery path.

No document ownership check is weakened, and nothing extra is closed or killed.

Validation

  • Reproduced the issue's failing-helper scenario on macOS arm64 against main. The CLI printed its failure and hung until the 40s alarm (exit 142). With the fix, it exits 1 with the same structured failure.
  • New tests/boundary/cli/hopperLaunchFailureCli.test.ts runs the compiled CLI twice against the same target with a failing launcher. Each run must exit 1 within 30s with the launcher diagnostics, and the retry must not be rejected as already open. It fails on main (deadline exceeded) and passes with the fix (~2s). It is skipped off macOS, where no target lease is taken on this route.
  • npm run test:focused -- tests/boundary/providers/hopper/*.test.ts tests/composition/analysis-sessions/binarySessionCleanupRetry.test.ts passes (137 passed, 2 skipped). This includes the retained-lease cleanup-retry coverage.
  • npm run check:fast passes.

Not verified: a real Hopper installation (none on this machine) and the Linux demo application lease route.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/1763 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/11/2026 **Status:** ✅ Merged **Merged:** 10/11/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/hopper-failed-session-exit` --- ### 📝 Commits (2) - [`610bccb`](https://github.com/morluto/rea/commit/610bccb7ece8addc71806580ea8b2d352a249f24) fix(hopper): let failed one-shot commands exit while retaining a lease - [`e11d131`](https://github.com/morluto/rea/commit/e11d13130de73d7cd85363c5a7b25f4bcac1b0e9) test(hopper): remove only this test's stale lease sockets ### 📊 Changes **2 files changed** (+132 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `src/hopper/HopperTargetLease.ts` (+4 -0) ➕ `tests/boundary/cli/hopperLaunchFailureCli.test.ts` (+128 -0) </details> ### 📄 Description Fixes #1751. ## Problem When Hopper startup fails and cleanup cannot be confirmed (for example, the launcher helper exits `2` with an Automation denial), REA keeps the target lease as it should. But the lease's `net.Server` listener stayed referenced. So `rea analyze ... --provider hopper` printed its final `cleanup_incomplete` JSON and then never exited. While that process stayed alive, every retry on the same target got "already open in REA session …". ## Change `tryAcquireLease` now calls `unref()` on the lease listener. The lease still lasts exactly as long as its owning process: - **MCP:** a live server still holds the lease, and still refuses competing opens, until cleanup succeeds or the process ends. - **One-shot CLI:** exits with status `1` and still reports `cleanup_incomplete`, the retained runtime root, and the launcher diagnostics. - **Next acquirer:** recovers the stale socket the exited process leaves behind, using the existing stale-lease recovery path. No document ownership check is weakened, and nothing extra is closed or killed. ## Validation - Reproduced the issue's failing-helper scenario on macOS arm64 against `main`. The CLI printed its failure and hung until the 40s alarm (exit 142). With the fix, it exits `1` with the same structured failure. - New `tests/boundary/cli/hopperLaunchFailureCli.test.ts` runs the compiled CLI twice against the same target with a failing launcher. Each run must exit `1` within 30s with the launcher diagnostics, and the retry must not be rejected as already open. It fails on `main` (deadline exceeded) and passes with the fix (~2s). It is skipped off macOS, where no target lease is taken on this route. - `npm run test:focused -- tests/boundary/providers/hopper/*.test.ts tests/composition/analysis-sessions/binarySessionCleanupRetry.test.ts` passes (137 passed, 2 skipped). This includes the retained-lease cleanup-retry coverage. - `npm run check:fast` passes. Not verified: a real Hopper installation (none on this machine) and the Linux demo application lease route. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 00:55:14 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4803
No description provided.