[GH-ISSUE #5098] [Bug] debug-with-gdb rejects built-in p, s and d aliases before starting GDB #3134

Closed
opened 2026-10-31 00:37:01 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

CLI

Observed behavior

At the production CLI handler boundary, p 1, s, and d 1 return invalid_request with “This command can invalidate the verified inferior output route” before the GDB manager is created. Their full spellings, print 1, step, and delete 1, pass validation and reach startup.

This was executed with a mocked manager. No real GDB, inferior, or terminal was used; successful command execution is not claimed.

Reproduction

From a source checkout at the revision below with locked dependencies available, run this standalone boundary probe. It registers the production CLI commands and supplies a manager that deliberately stops at startup. The TTY path is an inert argument and is never opened.

WORK="$(mktemp -d)"
mkdir -p "$WORK/home" "$WORK/config" "$WORK/cache" "$WORK/data" "$WORK/temp"
env -i HOME="$WORK/home" PATH="$PATH" XDG_CONFIG_HOME="$WORK/config" XDG_CACHE_HOME="$WORK/cache" XDG_DATA_HOME="$WORK/data" TMPDIR="$WORK/temp" node --import tsx --input-type=module <<'JS'
import assert from "node:assert/strict";
import pino from "pino";
import { registerReverseEngineeringCommands } from "./src/cli/reverseEngineeringCommands.ts";
import { AnalysisOutputError } from "./src/domain/analysisErrorCore.ts";
import { err } from "./src/domain/result.ts";
const commands = new Map();
const cli = { command(name, definition) { commands.set(name, definition); return cli; } };
let starts = 0;
const manager = {
  async start() { starts++; return err(new AnalysisOutputError("start_gdb_session", "probe stopped at startup")); },
  async closeAll() {},
};
registerReverseEngineeringCommands(cli, pino({ enabled: false }), {}, () => manager);
for (const command of ["p 1", "print 1", "s", "step", "d 1", "delete 1"]) {
  starts = 0;
  const result = await commands.get("debug-with-gdb").run({
    args: { command }, options: { inferiorTty: "/dev/pts/42" },
  });
  const rejected = ["p 1", "s", "d 1"].includes(command);
  assert.equal(result.code, rejected ? "invalid_request" : "unreadable_output");
  assert.equal(starts, rejected ? 0 : 1);
  if (rejected) assert.match(result.details.issues[0].message, /verified inferior output route/);
  console.log(JSON.stringify({ command, code: result.code, starts }));
}
JS

This probe exited 0 with the six results below. A focused single-worker Vitest check independently exercised the same boundary and passed.

Expected behavior

Accept ordinary built-in aliases wherever the equivalent full command spelling is accepted. The CLI declaration advertises an unrestricted console command; its validation concerns output-route invalidation. GNU GDB documents p as print, s as step, and d as delete. Literal p 1 does not invoke Python or change the inferior output route.

Impact and scope

Valid alias spellings are refused before provider startup. Full command spellings are an available workaround for this validation failure; all three reached the mocked startup boundary. End-to-end GDB success and real-world frequency are NOT_ENOUGH_INFO. One-shot GDB support is documented for Linux only; the boundary probe on macOS does not establish macOS GDB support. No target state was changed.

REA version

Current main source 3537e58c1a, package version 6.7.0. Relevant classifier, CLI and documentation files match tag rea-agents-6.7.0; the published release runtime was not separately executed.

Runtime and platform

Node v26.12.0; macOS 27.0.1; Darwin arm64; tsx 4.23.15 and Vitest 5.0.3 from the lockfile. NOT_ENOUGH_INFO for the repository-pinned Node 24.18.0 or a native Linux/GDB runtime.

Target and artifact context

Synthetic CLI arguments only. No binary, live target, GDB executable, or real TTY was selected or executed.

Interface

CLI

Earliest failure stage

Request parsing or validation

Relevant output or evidence

Observed from the standalone production-handler probe:

{"command":"p 1","code":"invalid_request","starts":0}
{"command":"print 1","code":"unreadable_output","starts":1}
{"command":"s","code":"invalid_request","starts":0}
{"command":"step","code":"unreadable_output","starts":1}
{"command":"d 1","code":"invalid_request","starts":0}
{"command":"delete 1","code":"unreadable_output","starts":1}

unreadable_output is the injected startup error in the probe; it indicates that validation admitted the full spelling. It does not indicate a failure from real GDB.

Source-derived path: handler validation before manager creation calls the classifier, which treats the first token as a prefix of restricted command names without resolving GDB's built-in aliases. These observations establish pre-start validation behavior only.

Typed outcome or recovery expected

Admit the alias to the normal session startup/execute workflow. Later GDB errors, such as absent target state for step, should retain their normal provenance instead of being replaced by an output-route validation error.

Analysis or suspected cause

Source-derived: python starts with p, source starts with s, and define starts with d; the classifier therefore mistakes the built-in aliases for potentially output-changing commands. This report does not imply that genuine source/Python/definition commands or their valid abbreviations should bypass the existing guard.

Additional context

Searched open and closed reports. #3656 discusses provider authority and one-shot containment, #3993 concerns quoted inventory parsing, and #4653 concerns close diagnostic classification; they have different triggers and recovery conditions. No known-good version was established.

Originally created by @coygeek on GitHub (Oct 18, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5098 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area CLI ## Observed behavior At the production CLI handler boundary, `p 1`, `s`, and `d 1` return `invalid_request` with “This command can invalidate the verified inferior output route” before the GDB manager is created. Their full spellings, `print 1`, `step`, and `delete 1`, pass validation and reach startup. This was executed with a mocked manager. No real GDB, inferior, or terminal was used; successful command execution is not claimed. ## Reproduction From a source checkout at the revision below with locked dependencies available, run this standalone boundary probe. It registers the production CLI commands and supplies a manager that deliberately stops at startup. The TTY path is an inert argument and is never opened. ```sh WORK="$(mktemp -d)" mkdir -p "$WORK/home" "$WORK/config" "$WORK/cache" "$WORK/data" "$WORK/temp" env -i HOME="$WORK/home" PATH="$PATH" XDG_CONFIG_HOME="$WORK/config" XDG_CACHE_HOME="$WORK/cache" XDG_DATA_HOME="$WORK/data" TMPDIR="$WORK/temp" node --import tsx --input-type=module <<'JS' import assert from "node:assert/strict"; import pino from "pino"; import { registerReverseEngineeringCommands } from "./src/cli/reverseEngineeringCommands.ts"; import { AnalysisOutputError } from "./src/domain/analysisErrorCore.ts"; import { err } from "./src/domain/result.ts"; const commands = new Map(); const cli = { command(name, definition) { commands.set(name, definition); return cli; } }; let starts = 0; const manager = { async start() { starts++; return err(new AnalysisOutputError("start_gdb_session", "probe stopped at startup")); }, async closeAll() {}, }; registerReverseEngineeringCommands(cli, pino({ enabled: false }), {}, () => manager); for (const command of ["p 1", "print 1", "s", "step", "d 1", "delete 1"]) { starts = 0; const result = await commands.get("debug-with-gdb").run({ args: { command }, options: { inferiorTty: "/dev/pts/42" }, }); const rejected = ["p 1", "s", "d 1"].includes(command); assert.equal(result.code, rejected ? "invalid_request" : "unreadable_output"); assert.equal(starts, rejected ? 0 : 1); if (rejected) assert.match(result.details.issues[0].message, /verified inferior output route/); console.log(JSON.stringify({ command, code: result.code, starts })); } JS ``` This probe exited 0 with the six results below. A focused single-worker Vitest check independently exercised the same boundary and passed. ## Expected behavior Accept ordinary built-in aliases wherever the equivalent full command spelling is accepted. The [CLI declaration](https://github.com/morluto/rea/blob/3537e58c1ab29309f06eabf50bc52adba9817a0c/src/cli/reverseEngineeringCommands.ts#L191-L205) advertises an unrestricted console command; its validation concerns output-route invalidation. GNU GDB documents [p as print](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Data.html), [s as step](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Aliases.html), and [d as delete](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Delete-Breaks.html). Literal `p 1` does not invoke Python or change the inferior output route. ## Impact and scope Valid alias spellings are refused before provider startup. Full command spellings are an available workaround for this validation failure; all three reached the mocked startup boundary. End-to-end GDB success and real-world frequency are NOT_ENOUGH_INFO. One-shot GDB support is documented for Linux only; the boundary probe on macOS does not establish macOS GDB support. No target state was changed. ## REA version Current main source 3537e58c1ab29309f06eabf50bc52adba9817a0c, package version 6.7.0. Relevant classifier, CLI and documentation files match tag `rea-agents-6.7.0`; the published release runtime was not separately executed. ## Runtime and platform Node v26.12.0; macOS 27.0.1; Darwin arm64; tsx 4.23.15 and Vitest 5.0.3 from the lockfile. NOT_ENOUGH_INFO for the repository-pinned Node 24.18.0 or a native Linux/GDB runtime. ## Target and artifact context Synthetic CLI arguments only. No binary, live target, GDB executable, or real TTY was selected or executed. ## Interface CLI ## Earliest failure stage Request parsing or validation ## Relevant output or evidence Observed from the standalone production-handler probe: ```jsonl {"command":"p 1","code":"invalid_request","starts":0} {"command":"print 1","code":"unreadable_output","starts":1} {"command":"s","code":"invalid_request","starts":0} {"command":"step","code":"unreadable_output","starts":1} {"command":"d 1","code":"invalid_request","starts":0} {"command":"delete 1","code":"unreadable_output","starts":1} ``` `unreadable_output` is the injected startup error in the probe; it indicates that validation admitted the full spelling. It does not indicate a failure from real GDB. Source-derived path: [handler validation before manager creation](https://github.com/morluto/rea/blob/3537e58c1ab29309f06eabf50bc52adba9817a0c/src/cli/reverseEngineeringCommands.ts#L208-L228) calls [the classifier](https://github.com/morluto/rea/blob/3537e58c1ab29309f06eabf50bc52adba9817a0c/src/gdb/GdbSessionManager.ts#L2175-L2193), which treats the first token as a prefix of restricted command names without resolving GDB's built-in aliases. These observations establish pre-start validation behavior only. ## Typed outcome or recovery expected Admit the alias to the normal session startup/execute workflow. Later GDB errors, such as absent target state for `step`, should retain their normal provenance instead of being replaced by an output-route validation error. ## Analysis or suspected cause Source-derived: `python` starts with `p`, `source` starts with `s`, and `define` starts with `d`; the classifier therefore mistakes the built-in aliases for potentially output-changing commands. This report does not imply that genuine source/Python/definition commands or their valid abbreviations should bypass the existing guard. ## Additional context Searched open and closed reports. [#3656](https://github.com/morluto/rea/issues/3656) discusses provider authority and one-shot containment, [#3993](https://github.com/morluto/rea/issues/3993) concerns quoted inventory parsing, and [#4653](https://github.com/morluto/rea/issues/4653) concerns close diagnostic classification; they have different triggers and recovery conditions. No known-good version was established.
Author
Owner

@XinwangTao commented on GitHub (Oct 19, 2026):

This is a genuine usability gap — GDB users reach for p/s/d out of habit and get a misleading "invalidates the verified inferior output route" error that doesn't apply to a command rejected before the manager even starts. Since the classifier apparently treats any alias mention as a route-invalidation risk, the boundary validation should recognize the built-in aliases (or at least defer that check until a real manager exists, as the linked fix does). The linked PR #5124 taking the t alias too looks complete for this.

<!-- gh-comment-id:6261329283 --> @XinwangTao commented on GitHub (Oct 19, 2026): This is a genuine usability gap — GDB users reach for p/s/d out of habit and get a misleading "invalidates the verified inferior output route" error that doesn't apply to a command rejected before the manager even starts. Since the classifier apparently treats any alias mention as a route-invalidation risk, the boundary validation should recognize the built-in aliases (or at least defer that check until a real manager exists, as the linked fix does). The linked PR #5124 taking the t alias too looks complete for this.
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#3134
No description provided.