Skip to content

Restore and harden pager suppression for wait-mode commands (APP-5310) - #14946

Draft
warp-agent-staging[bot] wants to merge 2 commits into
masterfrom
factory/fix-pager-decoration-wait-until-completion
Draft

Restore and harden pager suppression for wait-mode commands (APP-5310)#14946
warp-agent-staging[bot] wants to merge 2 commits into
masterfrom
factory/fix-pager-decoration-wait-until-completion

Conversation

@warp-agent-staging

@warp-agent-staging warp-agent-staging Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Description

The agent stopped reliably suppressing pagers for gh/VCS commands. Root cause: ShellCommandExecutor::execute only decorates pager-prone commands (wrapping them so their output is piped through cat, preventing the pager from activating) when uses_pager && wait_until_completion. The server was unconditionally reporting wait_until_completion = false for the modern run_shell_command tool call, in both wait and interact modes — a bug now fixed in the companion PR warpdotdev/warp-server#14303. With that field always false, the client's decoration gate never fired even when the model correctly set uses_pager: true, letting commands like gh pr view or git log drop into the user's pager and hang or truncate.

This PR restores the client's uses_pager && wait_until_completion gate (now that the server reports the field correctly again — true for wait mode, false for interact mode), and hardens the decoration itself:

  • Mode-aware gating: only wait-style commands are decorated. interact-mode commands (REPLs, dev servers, TUIs, or a pager the subagent means to page through itself) are left alone so the subagent keeps live PTY control.
  • Exit-status preservation: piping through cat used to mask the wrapped command's real exit status (cat being the last stage of the pipe always exits 0). The decoration now re-asserts the original exit status via PIPESTATUS/pipestatus (Bash/Zsh) or a nested fish -c process (Fish).
  • Heredoc safety (CSAT-10167 class): the closing group syntax (), end) now lands on its own line, so a command ending in a bare heredoc terminator (e.g. EOF) isn't corrupted by trailing characters on that line.

Linked Issue

Linear: APP-5310

Testing

  • execute_decorates_pager_command_when_waiting_for_completion / execute_does_not_decorate_pager_command_in_interact_mode: prove the wait-vs-interact gate.
  • turn_off_pager_for_command_preserves_nonzero_exit_status_in_bash: spawns a real bash subprocess to prove a failing command's exit code survives decoration.
  • turn_off_pager_for_command_preserves_heredoc_in_bash / turn_off_pager_for_command_handles_command_without_trailing_newline_in_bash: spawn real bash subprocesses to prove heredoc-ending and no-trailing-newline commands aren't corrupted.
  • turn_off_pager_for_command_zsh_uses_pipestatus_and_safe_closer, ..._fish_uses_nested_process_for_exit_status, ..._powershell_closer_on_own_line: structural checks for the other shells (not run as real subprocesses, since Zsh/Fish/PowerShell aren't guaranteed present in CI).

Ran to completion locally:

  • cargo fmt -- --check
  • cargo clippy -p warp --tests -- -D warnings
  • cargo test -p warp --lib shell_command (11/11 passing)

On visual proof: I don't have computer-use tooling available in this environment to capture a screen recording of Agent Mode. The tests above exercise the real, observable behavior end-to-end (actual shell processes, real exit codes, real heredoc parsing), which is the strongest evidence I can produce here. If a recording is still required before merge, it needs a human or a computer-use-capable agent to capture it.

  • I have manually tested my changes locally with ./script/run

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Conversation: https://staging.warp.dev/conversation/cbb2de15-6edb-4bc9-851e-3876c7b523f3
Run: https://oz.staging.warp.dev/runs/019ff1c9-37d2-7b36-bc92-33f392a1c482

This PR was generated with Oz.

The server always sets wait_until_completion=false for the modern
run_shell_command tool call, in both 'wait' and 'interact' modes. The
client only decorated pager-prone commands (piping through `cat` to
suppress the pager) when uses_pager && wait_until_completion, so the
decoration silently never ran even when the model correctly flagged a
command as using a pager. This let commands like `gh pr view` or
`git log` drop into the user's configured pager and hang.

Base pager decoration purely on uses_pager, since wait_until_completion
is no longer a reliable signal for this tool. Add a regression test
that exercises uses_pager && !wait_until_completion.

Co-Authored-By: Warp Agent <agent@warp.dev>
@warp-agent-staging
warp-agent-staging Bot requested a review from acarl005 August 11, 2026 17:42
@cla-bot cla-bot Bot added the cla-signed label Aug 11, 2026
…edoc handling (APP-5310)

Revision based on review findings on this PR.

Findings 1-3 showed the "decorate whenever uses_pager is set" approach
from the previous commit was wrong: it also decorated `interact`-mode
commands, which need live PTY control (REPLs, dev servers, or a pager
the subagent means to page through itself), and the decoration itself
lost the wrapped command's exit status and could corrupt a command
ending in a heredoc.

The real, more surgical fix (companion change on warpdotdev/warp-server)
was to stop the server from unconditionally reporting
wait_until_completion=false for both 'wait' and 'interact' modes. Now
that the server reports it correctly (true for 'wait', false for
'interact'), this commit:

- Reverts the client's pager-decoration predicate to
  `uses_pager && wait_until_completion`, so only 'wait'-style commands
  are decorated (finding 1).
- Hardens `turn_off_pager_for_command`:
  - Splits the combined Bash/Zsh arm, since they use different
    pipeline-status variables (`PIPESTATUS` vs `pipestatus`), and
    re-asserts the wrapped command's real exit status via a trailing
    `(exit "$...")` subshell instead of letting `cat`'s own exit status
    win the pipe (finding 2).
  - Puts the closing group syntax (`)`, `end`) on its own line so a
    command ending in a bare heredoc terminator isn't corrupted
    (finding 3 / CSAT-10167 class).
  - Fish has no safe bare `exit`/PIPESTATUS-equivalent to use from the
    live shell, so it re-asserts the exit status via a nested `fish -c`
    process instead.
- Replaces the previous (now-invalidated) regression test with:
  - wait-vs-interact gating tests (finding 1).
  - Real Bash-subprocess tests proving exit-status preservation
    (finding 2) and heredoc safety, including a no-trailing-newline
    case (finding 3 / CSAT-10167).
  - Structural tests for Zsh/Fish/PowerShell decoration shape.

On finding 4 (visual proof): I do not have computer-use tooling
available in this environment to capture a recording. The regression
tests above exercise the real, observable behavior end-to-end (actual
shell processes, real exit codes, real heredoc parsing) as the
strongest evidence available to me here.

Co-Authored-By: Warp Agent <agent@warp.dev>
@warp-agent-staging warp-agent-staging Bot changed the title Decouple pager decoration from wait_until_completion (APP-5310) Restore and harden pager suppression for wait-mode commands (APP-5310) Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant