[PR #4732] [CLOSED] fix(gdb): classify live-inferior close refusal as capability unavailable #6376

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/4732
Author: @luigiPinna
Created: 10/17/2026
Status: ❌ Closed

Base: main ← Head: fix/gdb-close-live-inferior-4653


📝 Commits (1)

  • e3a3734 fix(gdb): classify live-inferior close refusal as capability unavailable

📊 Changes

2 files changed (+26 additions, -9 deletions)

View changed files

📝 src/gdb/GdbSessionManager.ts (+7 -5)
📝 tests/boundary/providers/GdbSessionManagerCoverage.test.ts (+19 -4)

📄 Description

Summary

Fixes #4653. Closing a GDB session while a live inferior remains without a verified durable TTY is correctly refused, but the refusal was projected as invalid_request / invalid_input against session_id with "Correct the listed arguments and retry." The session_id is valid and the session stays ready; after a disposition (or kill) the same ID closes. This is a lifecycle precondition, not a rejected caller argument, so it is now an AnalysisCapabilityUnavailableError (capability_unavailable / unavailable, retryable).

Problem and expected behavior

GdbSessionManager.close returned AnalysisInputError("close_gdb_session", …, [{ path: ["session_id"], reason: "invalid_value", … }]) when -list-thread-groups reported a live group and no durable inferior TTY was verified. Projected, that is invalid_request with remediation pointing at argument correction, which misdescribes a valid session in a state that cannot yet close. The expected classification is the one this file already uses for its other GDB lifecycle refusals.

Change and scope

The branch now returns AnalysisCapabilityUnavailableError("gdb", "close_gdb_session", <reason>, { retryable: true, userMessage: … }), mirroring the existing capability-unavailable refusals in the same manager. The disposition guidance is preserved as the caller-facing userMessage; retryable is true because selecting a disposition or restarting with inferior_tty lets the same close succeed. No change to when close is refused — only its classification. The session_id-not-found refusal at the top of close keeps AnalysisInputError, since that is genuinely a bad argument.

Contract and boundary impact

  • Semantic owner and earliest changed stage: GdbSessionManager.close owns the refusal; only its projected classification changes.

  • Contribution scope fit and linked maintainer decision: ordinary correctness fix within an existing lifecycle operation; not applicable.

  • CLI and MCP/tool-catalog contract: unchanged; the error envelope for an already-refused close changes (invalid_request → capability_unavailable, category unavailable, retryable: true).

  • Provider, bridge, target-format, or platform compatibility: GDB is Linux-only; the refusal path is unchanged except for its tag.

  • Evidence, artifact, provenance, or reconstruction contract: none.

  • Generated metadata, package, or installation impact: none.

  • Read existing files or captured data.

Evidence and regression coverage

  • tests/boundary/providers/GdbSessionManagerCoverage.test.ts ("refuses to close a session while GDB reports a live target") now asserts the owner tag AnalysisCapabilityUnavailableError, that the session stays ready, and the projected projectAnalysisError fields: category: "unavailable" (not invalid_input), code: "capability_unavailable", retryable: true, message retaining the disposition guidance, and a remediation that no longer mentions arguments.
  • With src/gdb/GdbSessionManager.ts restored to main, this case fails (Invalid analysis input for close_gdb_session); with the fix it passes.

Validation performed

  • npx vitest run tests/boundary/providers/GdbSessionManagerCoverage.test.ts — 150 passed; the target case fails on main source and passes with the fix (revert reproduced).
  • npm run typecheck, npm run check:fast, oxfmt --check — clean. oxlint reports only pre-existing max-lines/complexity warnings in GdbSessionManager.ts, none at the changed lines.
  • Not run: real GNU GDB with a real inferior (the issue's repro and this test use a simulated MI provider); the classification change is provider-independent.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. A caller keying on invalid_request for this refused close now sees capability_unavailable (retryable: true); the close is still refused.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable. macOS arm64, Node 24.15; GDB path is Linux-only and exercised through the simulated MI provider.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: no change to target interaction; the message is the existing disposition guidance.

Author readiness

Human owner: @luigiPinna

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 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/4732 **Author:** [@luigiPinna](https://github.com/luigiPinna) **Created:** 10/17/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/gdb-close-live-inferior-4653` --- ### 📝 Commits (1) - [`e3a3734`](https://github.com/morluto/rea/commit/e3a3734f7a1a66f4f6fe89a95f540d76afa14608) fix(gdb): classify live-inferior close refusal as capability unavailable ### 📊 Changes **2 files changed** (+26 additions, -9 deletions) <details> <summary>View changed files</summary> 📝 `src/gdb/GdbSessionManager.ts` (+7 -5) 📝 `tests/boundary/providers/GdbSessionManagerCoverage.test.ts` (+19 -4) </details> ### 📄 Description ## Summary Fixes #4653. Closing a GDB session while a live inferior remains without a verified durable TTY is correctly refused, but the refusal was projected as `invalid_request` / `invalid_input` against `session_id` with "Correct the listed arguments and retry." The `session_id` is valid and the session stays `ready`; after a disposition (or `kill`) the same ID closes. This is a lifecycle precondition, not a rejected caller argument, so it is now an `AnalysisCapabilityUnavailableError` (`capability_unavailable` / `unavailable`, retryable). ## Problem and expected behavior `GdbSessionManager.close` returned `AnalysisInputError("close_gdb_session", …, [{ path: ["session_id"], reason: "invalid_value", … }])` when `-list-thread-groups` reported a live group and no durable inferior TTY was verified. Projected, that is `invalid_request` with remediation pointing at argument correction, which misdescribes a valid session in a state that cannot yet close. The expected classification is the one this file already uses for its other GDB lifecycle refusals. ## Change and scope The branch now returns `AnalysisCapabilityUnavailableError("gdb", "close_gdb_session", <reason>, { retryable: true, userMessage: … })`, mirroring the existing capability-unavailable refusals in the same manager. The disposition guidance is preserved as the caller-facing `userMessage`; `retryable` is true because selecting a disposition or restarting with `inferior_tty` lets the same close succeed. No change to when close is refused — only its classification. The `session_id`-not-found refusal at the top of `close` keeps `AnalysisInputError`, since that is genuinely a bad argument. ## Contract and boundary impact - Semantic owner and earliest changed stage: `GdbSessionManager.close` owns the refusal; only its projected classification changes. - Contribution scope fit and linked maintainer decision: ordinary correctness fix within an existing lifecycle operation; not applicable. - CLI and MCP/tool-catalog contract: unchanged; the error envelope for an already-refused close changes (`invalid_request` → `capability_unavailable`, category `unavailable`, `retryable: true`). - Provider, bridge, target-format, or platform compatibility: GDB is Linux-only; the refusal path is unchanged except for its tag. - Evidence, artifact, provenance, or reconstruction contract: none. - Generated metadata, package, or installation impact: none. - [x] Read existing files or captured data. ## Evidence and regression coverage - `tests/boundary/providers/GdbSessionManagerCoverage.test.ts` ("refuses to close a session while GDB reports a live target") now asserts the owner tag `AnalysisCapabilityUnavailableError`, that the session stays `ready`, and the projected `projectAnalysisError` fields: `category: "unavailable"` (not `invalid_input`), `code: "capability_unavailable"`, `retryable: true`, message retaining the disposition guidance, and a remediation that no longer mentions arguments. - With `src/gdb/GdbSessionManager.ts` restored to `main`, this case fails (`Invalid analysis input for close_gdb_session`); with the fix it passes. ## Validation performed - `npx vitest run tests/boundary/providers/GdbSessionManagerCoverage.test.ts` — 150 passed; the target case fails on `main` source and passes with the fix (revert reproduced). - `npm run typecheck`, `npm run check:fast`, `oxfmt --check` — clean. `oxlint` reports only pre-existing `max-lines`/`complexity` warnings in `GdbSessionManager.ts`, none at the changed lines. - Not run: real GNU GDB with a real inferior (the issue's repro and this test use a simulated MI provider); the classification change is provider-independent. ## Compatibility, safety, and release - Breaking changes or migration steps: none. A caller keying on `invalid_request` for this refused close now sees `capability_unavailable` (`retryable: true`); the close is still refused. - Real Hopper/Ghidra, browser, or OS coverage: not applicable. macOS arm64, Node 24.15; GDB path is Linux-only and exercised through the simulated MI provider. - Package or release metadata impact: none. - Security, privacy, process, or containment review: no change to target interaction; the message is the existing disposition guidance. ## Author readiness Human owner: @luigiPinna - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. - [ ] Related issue is linked, or the reason for not linking one is stated above. - [ ] Tests cover changed observable behavior and meaningful failure paths. - [ ] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [ ] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 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 01:14:00 +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#6376
No description provided.