[GH-ISSUE #4603] [Bug] JEB acquisition cleanup failure lacks live retained-owner status #2390

Closed
opened 2026-10-17 21:04:04 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @morluto on GitHub (Oct 16, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4603

Before submitting

  • Searched open/closed JEB cleanup, timeout and cancellation reports; #3935 concerns generic CLI cleanup and #4227 is the lifecycle audit. PR #3754 is a related prepared reconnect repair.
  • No credentials or sensitive target data included.

Area

Provider or capability discovery

Observed behavior

Source-only finding: when JEB connection acquisition fails and either SDK client/transport close also fails, the owner remains retained, but the provider maps the resulting plain AggregateError to capability unavailability without live cleanup status. Runtime fault injection has not yet been performed.

Reproduction

NOT_ENOUGH_INFO: no native or controlled runtime reproduction for this report. Inspected current main cd9252bc6:

  • JebMcpConnection.dispose keeps state when a client/transport close rejects and resets owner.disposal for retry.
  • Acquisition catches failed disposal and throws plain AggregateError with the original failure and close failure.
  • JebProvider.#providerFailure maps that aggregate to AnalysisCapabilityUnavailableError; there is no ProviderCleanupError, cleanup observation or exact lease binding.
    Proposed check: inject a catalog acquisition error and failed SDK close; require the original typed failure plus cleanupIncomplete/resources, then retry the exact owner and require the originating error's live cleanup status to resolve.

Expected behavior

Retain the primary failure and represent unresolved cleanup independently with the existing typed cleanup algebra and exact lease. Later confirmed disposal must resolve the original live cleanup status. This follows AGENTS.md ownership rules and docs/tool-design.md lifecycle contracts.

Impact and scope

P2, source-derived: callers cannot distinguish retained transport resources from an ordinary unavailable endpoint and retry guidance can hide unresolved cleanup. Actual fault frequency, real JEB behavior, CLI/MCP runtime output and measurements are NOT_ENOUGH_INFO, unverified.

REA version

cd9252bc63; unchanged transport source in ece277b30.

Runtime and platform

Source inspection on macOS arm64; no platform-specific runtime result claimed.

Target and artifact context

No target, project or JEB engine executed.

Interface

Other: shared provider/connection boundary

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

Retained disposal owner, acquisition failure composition, provider error mapping.

Analysis or suspected cause

Source-derived: resource ownership stays private to the connection, while failure composition uses a plain aggregate without a live cleanup dependency. A related source review of PR #3754 finds its failed-disposal diagnostics likewise lack live lease binding; its new awaited invalidation cleanup can also expose existing consumer-time cancellation guessing. Those PR observations are not current-main runtime reproductions.

Additional context

Related #4227, #3935 and PR #3754. Keep reconnect integration separate until primary-failure precedence, failed-disposal ownership, cleanup retry and late-abort controls are verified. Metadata-only #4597/#4600 fixes do not establish these lifecycle properties.

Originally created by @morluto on GitHub (Oct 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4603 ### Before submitting - [x] Searched open/closed JEB cleanup, timeout and cancellation reports; #3935 concerns generic CLI cleanup and #4227 is the lifecycle audit. PR #3754 is a related prepared reconnect repair. - [x] No credentials or sensitive target data included. ### Area Provider or capability discovery ### Observed behavior Source-only finding: when JEB connection acquisition fails and either SDK client/transport close also fails, the owner remains retained, but the provider maps the resulting plain AggregateError to capability unavailability without live cleanup status. Runtime fault injection has not yet been performed. ### Reproduction NOT_ENOUGH_INFO: no native or controlled runtime reproduction for this report. Inspected current main cd9252bc6: - `JebMcpConnection.dispose` keeps `state` when a client/transport close rejects and resets `owner.disposal` for retry. - Acquisition catches failed disposal and throws plain AggregateError with the original failure and close failure. - `JebProvider.#providerFailure` maps that aggregate to AnalysisCapabilityUnavailableError; there is no ProviderCleanupError, cleanup observation or exact lease binding. Proposed check: inject a catalog acquisition error and failed SDK close; require the original typed failure plus cleanupIncomplete/resources, then retry the exact owner and require the originating error's live cleanup status to resolve. ### Expected behavior Retain the primary failure and represent unresolved cleanup independently with the existing typed cleanup algebra and exact lease. Later confirmed disposal must resolve the original live cleanup status. This follows AGENTS.md ownership rules and docs/tool-design.md lifecycle contracts. ### Impact and scope P2, source-derived: callers cannot distinguish retained transport resources from an ordinary unavailable endpoint and retry guidance can hide unresolved cleanup. Actual fault frequency, real JEB behavior, CLI/MCP runtime output and measurements are NOT_ENOUGH_INFO, unverified. ### REA version cd9252bc63d86cc37cd573fb1c833ed474dc8112; unchanged transport source in ece277b30. ### Runtime and platform Source inspection on macOS arm64; no platform-specific runtime result claimed. ### Target and artifact context No target, project or JEB engine executed. ### Interface Other: shared provider/connection boundary ### Earliest failure stage Cleanup, cancellation, or lifecycle ### Relevant output or evidence [Retained disposal owner](https://github.com/morluto/rea/blob/cd9252bc63d86cc37cd573fb1c833ed474dc8112/src/jeb/JebMcpConnection.ts#L146), [acquisition failure composition](https://github.com/morluto/rea/blob/cd9252bc63d86cc37cd573fb1c833ed474dc8112/src/jeb/JebMcpConnection.ts#L217), [provider error mapping](https://github.com/morluto/rea/blob/cd9252bc63d86cc37cd573fb1c833ed474dc8112/src/jeb/JebProvider.ts#L415). ### Analysis or suspected cause Source-derived: resource ownership stays private to the connection, while failure composition uses a plain aggregate without a live cleanup dependency. A related source review of PR #3754 finds its failed-disposal diagnostics likewise lack live lease binding; its new awaited invalidation cleanup can also expose existing consumer-time cancellation guessing. Those PR observations are not current-main runtime reproductions. ### Additional context Related #4227, #3935 and PR #3754. Keep reconnect integration separate until primary-failure precedence, failed-disposal ownership, cleanup retry and late-abort controls are verified. Metadata-only #4597/#4600 fixes do not establish these lifecycle properties.
Author
Owner

@morluto commented on GitHub (Oct 16, 2026):

Controlled reproduction and repair are now available in a6e8f5269 (with timeout projection followup d74e72406).

At pinned baseline 67384b23e, 16 of 17 new production-boundary controls fail. The controls use the installed MCP SDK 2.3.1 and a real loopback HTTP fixture; SDK close faults and deterministic handoff gates are injected. No native JEB engine or target is executed.

The connection now retains exact client/transport owners through typed cleanup leases, coalesces disposal, and retries unresolved children. Original errors expose live pending resources and resolve after confirmed retry. Shared startup keeps final cleanup attached to the departing caller, joins late handshakes, and permits independent peer cancellation. The SDK closes its attached transport once; fallback cleanup covers unattached or failed children.

Cancellation is attributed by the identity of the producer-owned SDK abort rejection. Controls cover physical SDK catalog/HTTP failures before late abort, repeated-cursor validation, cancellation during final cleanup, null/string/Error reasons, mixed close outcomes, exact-owner retry, concurrent close, late handshake and completed partial Evidence.

After rebasing onto 1b56237ca, 189 tests across ten affected JEB/Ghidra files pass, including public CLI/MCP workflows. Static typecheck/lint, docs check (five conformance tests), formatting, test discovery (1446 files) and pre-push checks pass.

Representative completed public MCP task: two list calls, same normalized facts and three upstream tool calls in both builds. Normal transport close count changes from two to one. Four alternating warm repeats per build before the unrelated Ghidra rebase: median elapsed 0.5792/0.5532 s, CPU 0.8265/0.8067 s, sampled process-family RSS 372097024/369532928 bytes, raw reply tokens 1086/1064 (cl100k_base). Opaque IDs/ports vary; these samples do not establish a speed/token improvement. First-process samples were retained separately; true cold caches, whole-agent/catalog/request/retry tokens, fault-path costs and real-engine costs remain unmeasured.

Reconnect PR #3754 remains separate and unmerged; these checks do not verify automatic recovery, real-provider behavior or the whole JEB subsystem. The issue remains open.

<!-- gh-comment-id:6225937851 --> @morluto commented on GitHub (Oct 16, 2026): Controlled reproduction and repair are now available in a6e8f5269 (with timeout projection followup d74e72406). At pinned baseline 67384b23e, 16 of 17 new production-boundary controls fail. The controls use the installed MCP SDK 2.3.1 and a real loopback HTTP fixture; SDK close faults and deterministic handoff gates are injected. No native JEB engine or target is executed. The connection now retains exact client/transport owners through typed cleanup leases, coalesces disposal, and retries unresolved children. Original errors expose live pending resources and resolve after confirmed retry. Shared startup keeps final cleanup attached to the departing caller, joins late handshakes, and permits independent peer cancellation. The SDK closes its attached transport once; fallback cleanup covers unattached or failed children. Cancellation is attributed by the identity of the producer-owned SDK abort rejection. Controls cover physical SDK catalog/HTTP failures before late abort, repeated-cursor validation, cancellation during final cleanup, null/string/Error reasons, mixed close outcomes, exact-owner retry, concurrent close, late handshake and completed partial Evidence. After rebasing onto 1b56237ca, 189 tests across ten affected JEB/Ghidra files pass, including public CLI/MCP workflows. Static typecheck/lint, docs check (five conformance tests), formatting, test discovery (1446 files) and pre-push checks pass. Representative completed public MCP task: two list calls, same normalized facts and three upstream tool calls in both builds. Normal transport close count changes from two to one. Four alternating warm repeats per build before the unrelated Ghidra rebase: median elapsed 0.5792/0.5532 s, CPU 0.8265/0.8067 s, sampled process-family RSS 372097024/369532928 bytes, raw reply tokens 1086/1064 (cl100k_base). Opaque IDs/ports vary; these samples do not establish a speed/token improvement. First-process samples were retained separately; true cold caches, whole-agent/catalog/request/retry tokens, fault-path costs and real-engine costs remain unmeasured. Reconnect PR #3754 remains separate and unmerged; these checks do not verify automatic recovery, real-provider behavior or the whole JEB subsystem. The issue remains open.
Author
Owner

@morluto commented on GitHub (Oct 18, 2026):

Closing as fixed on main after reconciling this report with the landed owner/consumer changes.

  • a6e8f5269: fix(jeb): retain cleanup ownership and acquisition outcomes. Attribute SDK aborts by exact owned rejection identity, preserve physical failures under late cancellation, and retain completed Evidence at the application boundary.

Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.

<!-- gh-comment-id:6255998557 --> @morluto commented on GitHub (Oct 18, 2026): <!-- rea-backlog-reconciliation-2026-10-19-4603 --> Closing as fixed on `main` after reconciling this report with the landed owner/consumer changes. - [a6e8f5269](https://github.com/morluto/rea/commit/a6e8f5269f1aee9972116909eac0207d8ff05e7a): fix(jeb): retain cleanup ownership and acquisition outcomes. Attribute SDK aborts by exact owned rejection identity, preserve physical failures under late cancellation, and retain completed Evidence at the application boundary. Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.
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#2390
No description provided.