[PR #1776] [MERGED] fix(session): verify retained client liveness on open fast path #4809

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1776
Author: @sx4im
Created: 10/11/2026
Status: ✅ Merged
Merged: 10/11/2026
Merged by: @N0zoM1z0

Base: main ← Head: fix/open-binary-liveness-check


📝 Commits (6)

  • 39851cb fix(session): verify retained client liveness on open fast path
  • 1a857c2 fix(session): reject not_started clients from the open fast path
  • 2421a54 fix(hopper): preserve failed startup state through a blocked retry
  • e6ca869 fix(hopper): record all startup failures for the liveness probe
  • ec09a57 test(hopper): document BadHealthLauncher handshake assumption
  • ea2176b Merge main into fix/open-binary-liveness-check

📊 Changes

4 files changed (+533 additions, -6 deletions)

View changed files

📝 src/application/binary/BinarySession.ts (+62 -6)
➕ src/application/binary/BinarySessionLiveness.test.ts (+338 -0)
📝 tests/boundary/providers/hopper/hopperClient.cleanupRetry.test.ts (+26 -0)
📝 tests/boundary/providers/hopper/hopperClient.startupFailures.test.ts (+107 -0)

📄 Description

Summary

After an owned Hopper child exits, reopening the same target and analysis profile reported success while subsequent queries continued to fail against the retained client. open_binary now retires a retained client reporting a failed operation-health state and creates a fresh provider route. The next query starts the replacement child. A healthy retained client is reused, and an aborted probe leaves the active session intact.

Refs #1719. This fixes the reproduced retained-Hopper-client failure. It does not establish a fix for the original Ghidra snapshot report: Ghidra and IDA have no operation-health snapshot hook, so their existing health admission remains the fallback. Ghidra's lazy startup on the first query remains unchanged.

Change and scope

  • Read operationHealthSnapshot() from the retained provider before taking the same-target/profile fast path. Only idle and busy permit reuse; recorded exited, unreachable, unknown, and incomplete-startup states trigger the existing retirement path.
  • Preserve cancellation, snapshot import behavior, and the existing cleanup ownership/retry mechanism. No eager provider startup is added.
  • Add production-composed session tests for healthy reuse, dead/unknown/incomplete-startup recovery, health fallback, and cancellation, plus distinct Hopper startup and cleanup-retry health regressions.
  • CLI/MCP input and output shapes, Evidence semantics, advertised schemas, and provider authority are unchanged.

Validation

  • Exact PR head ea2176b0c0b8b8ae6e952425c3654e31b5c3800c: all 31 current checks, including CI required, passed.
  • Integrated with pinned main d802304c542b20bc86e22cc492718e89a8a5579b in a separate review branch. The resulting tree is a7520fd76c947612cc44c8e44e3a753e668692fa.
  • Fresh runtime and packaged-skill build, then the declared focused-test plan's 11 exact files: 85 passed, using one Vitest worker. The default test:focused artifact-preparation phase exceeded the private 1.5 GiB process-family limit; verification instead built the required artifacts serially and ran the same exact test plan against them. The interrupted preparation is not claimed as a passing command.
  • Actual Linux Hopper 6.4.2 demo, headless private display, official SDK stdio MCP, a 23,264-byte source-owned ELF (SHA-256 9a87b653669278120c7c207b7acf5a38e5dfe9a4394b45cd6f5d2e7932443a9b): start and query, terminate only the verified owned Hopper child through a PID-bound kernel handle, observe the transport failure, reopen the same target, query, repeat a healthy open, close, status, and ping.
  • Baseline main reproduced success from open_binary followed by provider_unavailable. The integrated fix recovered the query with a fresh run ID and launcher PID; another healthy open retained that run ID. All 13 named tool calls were validated against their output contracts and success text/structured parity.
  • Input bytes remained unchanged, the retired runtime root was absent, and the final provider/runtime directories were empty. The target was not executed. No visible desktop window or unrelated Hopper process was controlled.
  • CPU affinity was limited to two cores. Authentic Flameox V8 launcher artifacts and payload digests were retained; these do not measure child compiler, test-worker, or Hopper CPU hotspots. The real fixed workflow completed in 17.45 seconds without reaching its resource limits.

Remaining coverage

The real workflow covers Linux native Hopper child failure and recovery. macOS, saved .hop documents, Ghidra/IDA child-liveness recovery, the reporter's historical Ghidra version/25 MB PE/snapshot, and default-client-deadline behavior remain unverified by this PR. The related broader issues stay open.


🔄 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/1776 **Author:** [@sx4im](https://github.com/sx4im) **Created:** 10/11/2026 **Status:** ✅ Merged **Merged:** 10/11/2026 **Merged by:** [@N0zoM1z0](https://github.com/N0zoM1z0) **Base:** `main` ← **Head:** `fix/open-binary-liveness-check` --- ### 📝 Commits (6) - [`39851cb`](https://github.com/morluto/rea/commit/39851cb7c6792fa969ea6240e47072bbaf39d333) fix(session): verify retained client liveness on open fast path - [`1a857c2`](https://github.com/morluto/rea/commit/1a857c29ad63d93c2252683bd603a4cfcf734024) fix(session): reject not_started clients from the open fast path - [`2421a54`](https://github.com/morluto/rea/commit/2421a54a988207e2225ba1d747e2af36c55309a8) fix(hopper): preserve failed startup state through a blocked retry - [`e6ca869`](https://github.com/morluto/rea/commit/e6ca869ce0e8650057f34db850e6d33d137b347e) fix(hopper): record all startup failures for the liveness probe - [`ec09a57`](https://github.com/morluto/rea/commit/ec09a57ce6a32dd44886d709faebfa1d14cd0247) test(hopper): document BadHealthLauncher handshake assumption - [`ea2176b`](https://github.com/morluto/rea/commit/ea2176b0c0b8b8ae6e952425c3654e31b5c3800c) Merge main into fix/open-binary-liveness-check ### 📊 Changes **4 files changed** (+533 additions, -6 deletions) <details> <summary>View changed files</summary> 📝 `src/application/binary/BinarySession.ts` (+62 -6) ➕ `src/application/binary/BinarySessionLiveness.test.ts` (+338 -0) 📝 `tests/boundary/providers/hopper/hopperClient.cleanupRetry.test.ts` (+26 -0) 📝 `tests/boundary/providers/hopper/hopperClient.startupFailures.test.ts` (+107 -0) </details> ### 📄 Description ## Summary After an owned Hopper child exits, reopening the same target and analysis profile reported success while subsequent queries continued to fail against the retained client. `open_binary` now retires a retained client reporting a failed operation-health state and creates a fresh provider route. The next query starts the replacement child. A healthy retained client is reused, and an aborted probe leaves the active session intact. Refs #1719. This fixes the reproduced retained-Hopper-client failure. It does not establish a fix for the original Ghidra snapshot report: Ghidra and IDA have no operation-health snapshot hook, so their existing health admission remains the fallback. Ghidra's lazy startup on the first query remains unchanged. ## Change and scope - Read `operationHealthSnapshot()` from the retained provider before taking the same-target/profile fast path. Only `idle` and `busy` permit reuse; recorded `exited`, `unreachable`, `unknown`, and incomplete-startup states trigger the existing retirement path. - Preserve cancellation, snapshot import behavior, and the existing cleanup ownership/retry mechanism. No eager provider startup is added. - Add production-composed session tests for healthy reuse, dead/unknown/incomplete-startup recovery, health fallback, and cancellation, plus distinct Hopper startup and cleanup-retry health regressions. - CLI/MCP input and output shapes, Evidence semantics, advertised schemas, and provider authority are unchanged. ## Validation - Exact PR head `ea2176b0c0b8b8ae6e952425c3654e31b5c3800c`: all 31 current checks, including `CI required`, passed. - Integrated with pinned main `d802304c542b20bc86e22cc492718e89a8a5579b` in a separate review branch. The resulting tree is `a7520fd76c947612cc44c8e44e3a753e668692fa`. - Fresh runtime and packaged-skill build, then the declared focused-test plan's 11 exact files: **85 passed**, using one Vitest worker. The default `test:focused` artifact-preparation phase exceeded the private 1.5 GiB process-family limit; verification instead built the required artifacts serially and ran the same exact test plan against them. The interrupted preparation is not claimed as a passing command. - Actual Linux Hopper 6.4.2 demo, headless private display, official SDK stdio MCP, a 23,264-byte source-owned ELF (SHA-256 `9a87b653669278120c7c207b7acf5a38e5dfe9a4394b45cd6f5d2e7932443a9b`): start and query, terminate only the verified owned Hopper child through a PID-bound kernel handle, observe the transport failure, reopen the same target, query, repeat a healthy open, close, status, and ping. - Baseline main reproduced success from `open_binary` followed by `provider_unavailable`. The integrated fix recovered the query with a fresh run ID and launcher PID; another healthy open retained that run ID. All 13 named tool calls were validated against their output contracts and success text/structured parity. - Input bytes remained unchanged, the retired runtime root was absent, and the final provider/runtime directories were empty. The target was not executed. No visible desktop window or unrelated Hopper process was controlled. - CPU affinity was limited to two cores. Authentic Flameox V8 launcher artifacts and payload digests were retained; these do not measure child compiler, test-worker, or Hopper CPU hotspots. The real fixed workflow completed in 17.45 seconds without reaching its resource limits. ## Remaining coverage The real workflow covers Linux native Hopper child failure and recovery. macOS, saved `.hop` documents, Ghidra/IDA child-liveness recovery, the reporter's historical Ghidra version/25 MB PE/snapshot, and default-client-deadline behavior remain unverified by this PR. The related broader issues stay open. --- <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:16 +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#4809
No description provided.