Skip to content

Report a command's own output, never the rawOutput envelope - #2234

Closed
SawyerHood wants to merge 1 commit into
ws2b-acp-5b-probe-capabilitiesfrom
ws2b-acp-6-command-output-fidelity
Closed

Report a command's own output, never the rawOutput envelope#2234
SawyerHood wants to merge 1 commit into
ws2b-acp-5b-probe-capabilitiesfrom
ws2b-acp-6-command-output-fidelity

Conversation

@SawyerHood

@SawyerHood SawyerHood commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #2231.

What was wrong

Live QA on this stack — a real Cursor thread and a real grok thread in a dev app — found two places where a command row showed the agent's rawOutput envelope, rendered as JSON, instead of what the command printed.

1. A command that printed nothing. Cursor answers node -e "process.exit(3)" with {"exitCode":3,"stdout":"","stderr":""}. #2211 joined the streams, got an empty string, treated that as "no output", and fell through to the generic fallback that renders rawOutput as text. The row read:

aggregatedOutput: "{\"exitCode\":3,\"stdout\":\"\",\"stderr\":\"\"}"
exitCode: 3

2. A running command's streamed output. grok sends its whole envelope on the in_progress update. #2211's snapshot used the generic output extraction, so the row streamed:

item/commandExecution/outputDelta  delta: {"type":"Bash","output":[],"output_for_prompt":"","exit_code":0,"command":"node -e \"process.exit(3)\"",…}

— including exit_code: 0, an exit code the command had not reached yet (it ended 3).

What changed

  • An agent that reported its streams has told bb what the command printed, even when that is nothing. extractAcpCommandResult now distinguishes "the agent reported empty output" from "the agent reported no output": the first gives the row no aggregatedOutput at all, the second still falls back to the rendered rawOutput (which is all bb has for an agent that reports output only that way).
  • The streamed snapshot uses the same extraction the close uses, so it is the command's own output or nothing — never the envelope.

How I verified

  • Two new tests, each naming the live-QA symptom it pins: "shows no output for a command that printed nothing" and "streams the command's own output, never the rawOutput envelope" (which asserts that an envelope with empty output streams nothing, and that a later envelope with real output_for_prompt streams exactly "working\n").
  • test --filter=@bb/provider-bridge-acp: 16 files, 235 tests.
  • pnpm --filter @bb/provider-parity rerecord --provider acp-cursor then test --filter=@bb/provider-parity --force: 43/43. The rerecord shows the fix on the committed recordings too — four command closes in approval-allow and steer lose the bogus aggregatedOutput: "{\"exitCode\":0,…}" and keep their real exitCode.

The live QA this came from

Cursor thread thr_rk5tu74s2c — the two rows the spec asks for:

commandExecution  command: node -e "process.exit(3)"   exitCode: 3    ← the agent's own code, under an ACP status of "completed"
toolCall(fetch)   presentation.title: "Fetch https://nodejs.org/dist/index.json"   ← the URL, from the permission merge (M5)
toolCall(read)    result: {"content":"[\n{\"version\":\"v26.7.0\",…"}                ← rawOutput as result (M3)

grok thread thr_pxipc8rbbe:

commandExecution  command: node -e "process.exit(3)"   exitCode: 3   aggregatedOutput: "exit: 3\n"   ← opened AS a command (M7 dialect kind-at-open), one row, not a generic tool + a second command row
fileRead          path: /home/…/personal-workspaces/env_65nrbvvxkm/README.md          ← absolute, resolved from grok's relative "README.md" (M6)
item/commandExecution/outputDelta                                                      ← M2 streaming reaches the row

Both acp-cursor and acp-grok list with fork: false in that instance, which is what #2229/#2231 declare and what the agents answer.

AGENT GENERATED: by Claude Opus 5

Live QA on a real Cursor thread and a real grok thread found two places
where a command row showed the agent's rawOutput envelope rendered as JSON
instead of what the command printed.

A command that printed nothing: Cursor reports {exitCode: 3, stdout: "",
stderr: ""}, the empty stdout/stderr join fell through to the generic
fallback, and the row read {"exitCode":3,"stdout":"","stderr":""}. An agent
that reported its streams has said what the command printed, even when that
is nothing, so the row now shows nothing.

A running command's streamed output: grok sends its whole envelope on the
in-progress update, and the row streamed {"type":"Bash","output":[],
"exit_code":0,...} — including an exit code the command had not reached.
The snapshot now comes from the same extraction the close uses.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant