Skip to content

fix: deliver truncation notice as separate content block#7899

Merged
DOsinga merged 2 commits intoblock:mainfrom
jeffa-block:jeffa/fix-shell-truncation-notice
Mar 26, 2026
Merged

fix: deliver truncation notice as separate content block#7899
DOsinga merged 2 commits intoblock:mainfrom
jeffa-block:jeffa/fix-shell-truncation-notice

Conversation

@jeffa-block
Copy link
Copy Markdown
Contributor

Problem

When shell output exceeds the 50kB / 2000-line limit, the truncation notice ([Full output saved to /tmp/... Read it with head, tail, or sed...]) is appended directly to the preview text. This causes two issues:

  1. Model ignores the notice. The notice text becomes part of the stdout field in the structured JSON (ShellOutput). The model parses the JSON and treats the notice as command output data — it never "sees" it as an instruction to read the temp file.

  2. Unix-only commands on Windows. The notice references head, tail, and sed which are unavailable on Windows.

Fix

  • Extract a TruncateResult struct so truncate_output() returns the preview text and truncation metadata (path + reason) separately
  • Deliver the truncation notice as a separate Content block in the CallToolResult, keeping structured_content clean
  • Use platform-appropriate commands in the notice (PowerShell on Windows, head/tail/sed on Unix)

The structured ShellOutput JSON now contains only the actual command output (truncated preview), while the instruction to read the full output arrives as a distinct message the model can see and act on.

Changes

Single file: crates/goose/src/agents/platform_extensions/developer/shell.rs

  • New TruncateResult / TruncationInfo structs
  • New truncation_notice() helper with cfg!(windows) branching
  • Updated truncate_output() and render_output() return types
  • Updated shell_with_cwd() to collect notices and emit as separate Content block
  • All 34 existing tests updated and passing

Testing

cargo test -p goose -- developer
# 34 passed, 0 failed

No behavioural change for output under the limit (returns TruncateResult with truncation: None).

Fixes #7846

When shell output exceeds the 50kB / 2000-line limit, the truncation
notice (file path + read instructions) was appended directly to the
preview text. This text then became the `stdout` field in the
structured JSON output, causing the model to parse the notice as
command data rather than acting on it.

Changes:
- Extract `TruncateResult` struct so `truncate_output()` returns the
  preview text and truncation metadata separately
- Deliver the truncation notice as a separate `Content` block in the
  `CallToolResult`, keeping structured_content clean
- Use platform-appropriate commands in the notice (PowerShell on
  Windows, head/tail/sed on Unix)

The structured `ShellOutput` JSON now contains only the actual command
output (truncated preview), while the instruction to read the full
output arrives as a distinct message the model can see and act on.

Fixes block#7846
@DOsinga DOsinga marked this pull request as ready for review March 26, 2026 21:22
Copy link
Copy Markdown
Collaborator

@DOsinga DOsinga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@DOsinga DOsinga added this pull request to the merge queue Mar 26, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d9ad815eb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +183 to +186
let truncation_notices: Vec<String> = [
&stdout_result.truncation,
&stderr_result.truncation,
&render_result.truncation,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prioritize interleaved truncation notice over stream files

When output truncation happens on both streams, this order emits stdout/stderr notices before the interleaved notice even though the preview shown to the model comes from interleaved output. In that case, following the first suggested file path can hide stderr lines (or stdout/stderr ordering), which can change diagnosis for failing commands. Emitting only the interleaved notice (or at least placing it first) would avoid steering the model to incomplete logs.

Useful? React with 👍 / 👎.

Merged via the queue into block:main with commit abdeaee Mar 26, 2026
21 checks passed
michaelneale added a commit that referenced this pull request Mar 26, 2026
* main: (337 commits)
  fix: replace panics with user-friendly errors in CLI session builder (#7901)
  fix: read GOOSE_CONTEXT_LIMIT from config.yaml, not just env vars (#7900)
  fix: deliver truncation notice as separate content block (#7899)
  fix: use platform-appropriate commands in developer extension instructions (#7898)
  fix: replace any with proper SVG types in icon components (#7873)
  chore: remove debug console.log statements, stale comments, and dead code (#8142)
  feat: Gemini OAuth provider (#8129)
  chore(deps): bump picomatch from 2.3.1 to 2.3.2 in /documentation (#8123)
  feat: show installed skills in UI (#7910)
  fix(deps): gate keyring platform features behind target-specific deps (#8039)
  chore(deps): bump yaml from 2.8.2 to 2.8.3 in /evals/open-model-gym/suite (#8124)
  fix: strip message wrapper in CLI session title generation (#7996)
  fix(providers): fall back to configured models when models endpoint fetch fails (#7530)
  chore(deps): bump brace-expansion from 5.0.3 to 5.0.5 in /evals/open-model-gym/suite (#8139)
  fix: prevent Ollama provider from hanging on tool-calling requests (#7723)
  fix: VMware Tanzu Platform provider - bug fixes, streaming, UI improvements (#8126)
  feat: allow GOOSE_CLI_SHOW_THINKING to be set in config.yaml (#8097)
  fix: GitHub Copilot auth fails to open browser in Desktop app (#6957) (#8019)
  fix(ci): produce .tar.gz archives for Zed ACP registry compatibility (#8054)
  feat: add GOOSE_SHOW_FULL_OUTPUT config to disable tool output truncation (#7919)
  ...

# Conflicts:
#	crates/goose/src/providers/formats/openai.rs
michaelneale added a commit that referenced this pull request Mar 30, 2026
* origin/main: (63 commits)
  remove name from blog post (#8157)
  fix: use `overflow: clip` to not disrupt sticky ToC (#8158)
  chore(deps): bump path-to-regexp from 0.1.12 to 0.1.13 in /documentation (#8161)
  chore(deps): bump node-forge from 1.3.2 to 1.4.0 in /documentation (#8145)
  refactor: goose-acp-server -> goose binary for TUI (#8155)
  fix "View as Markdown" feature not working (#8160)
  feat(tui): UI improvements for messages, tool calls, text entry, etc (#8156)
  feat(desktop): add i18n infrastructure with react-intl (#8105)
  fix(tui): ordering of messages (#8144)
  fix: extension command with quotes in  cli (#8150)
  chore(aaif): Use Azure Artifact Signing for Windows (#8116)
  chore(aaif): Switch macOS code signing (#8076)
  Remove unused tool call json in logs (#8147)
  feat(tui): tab expand tool calls cleanly (#8136)
  fix: replace panics with user-friendly errors in CLI session builder (#7901)
  fix: read GOOSE_CONTEXT_LIMIT from config.yaml, not just env vars (#7900)
  fix: deliver truncation notice as separate content block (#7899)
  fix: use platform-appropriate commands in developer extension instructions (#7898)
  fix: replace any with proper SVG types in icon components (#7873)
  chore: remove debug console.log statements, stale comments, and dead code (#8142)
  ...
hydrosquall pushed a commit to hydrosquall/goose that referenced this pull request Mar 31, 2026
blackgirlbytes pushed a commit that referenced this pull request Apr 2, 2026
* main: (337 commits)
  fix: replace panics with user-friendly errors in CLI session builder (#7901)
  fix: read GOOSE_CONTEXT_LIMIT from config.yaml, not just env vars (#7900)
  fix: deliver truncation notice as separate content block (#7899)
  fix: use platform-appropriate commands in developer extension instructions (#7898)
  fix: replace any with proper SVG types in icon components (#7873)
  chore: remove debug console.log statements, stale comments, and dead code (#8142)
  feat: Gemini OAuth provider (#8129)
  chore(deps): bump picomatch from 2.3.1 to 2.3.2 in /documentation (#8123)
  feat: show installed skills in UI (#7910)
  fix(deps): gate keyring platform features behind target-specific deps (#8039)
  chore(deps): bump yaml from 2.8.2 to 2.8.3 in /evals/open-model-gym/suite (#8124)
  fix: strip message wrapper in CLI session title generation (#7996)
  fix(providers): fall back to configured models when models endpoint fetch fails (#7530)
  chore(deps): bump brace-expansion from 5.0.3 to 5.0.5 in /evals/open-model-gym/suite (#8139)
  fix: prevent Ollama provider from hanging on tool-calling requests (#7723)
  fix: VMware Tanzu Platform provider - bug fixes, streaming, UI improvements (#8126)
  feat: allow GOOSE_CLI_SHOW_THINKING to be set in config.yaml (#8097)
  fix: GitHub Copilot auth fails to open browser in Desktop app (#6957) (#8019)
  fix(ci): produce .tar.gz archives for Zed ACP registry compatibility (#8054)
  feat: add GOOSE_SHOW_FULL_OUTPUT config to disable tool output truncation (#7919)
  ...

# Conflicts:
#	crates/goose/src/providers/formats/openai.rs
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.

Long output to stdout is cut to 50kB and tail is lost (model not notified about temporary file).

2 participants