Make truncation marker honest before the size-cap blob spill - #542
Merged
TheGreatAxios merged 7 commits intoAug 23, 2026
Merged
Conversation
Tool results are truncated to MAX_RESULT_CHARS before the reactor's
size-cap transform spills the (already-truncated) text as a blob and
tells the model the full output is at tool-output:///{id}. For
oversized outputs the promised remainder never existed, so the model
reads the blob, finds it cut, and re-runs the command.
Rework the truncation marker to say the discarded remainder is not
retrievable anywhere, so the lie doesn't survive the blob spill.
Sized to stay within the ripgrep integration test's MAX_RESULT_CHARS
+ 200 allowance.
…-available-at-a-blob
…-available-at-a-blob
…-available-at-a-blob
…-available-at-a-blob
…-available-at-a-blob
…-available-at-a-blob
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Tool results are truncated to
MAX_RESULT_CHARS(80,000 chars) bysrc/plugins/result-truncation-plugin.tsin the posix chain (src/agent/posix-tool-plugins.ts) and the MCP runner (src/mcp/plugin.ts) before the reactor's size-cap transform runs (vendor/intx-inference/src/transforms/size-cap.ts). For an output over 80k, the size-cap transform spills the already-truncated text as the blob and tells the model "Full output available at tool-output:///{id} — use read_file with that URI to see the rest." That promise is false: the remainder was discarded upstream and the blob only contains the same truncated text. The model reads the blob, finds it cut in the same place, and re-runs the command — an observed loop shape in production traces.vendor/is edit-locked, so this fixes it at the source: the truncation marker inresult-truncation-plugin.tsnow tells the truth up front, so the lie doesn't get a chance to survive the size-cap spill.Tradeoff
Kept the honest-but-terse wording rather than a fuller explanation, to stay under the
MAX_RESULT_CHARS + 200char allowance asserted by the real-chain ripgrep integration test (tests/unit/ripgrep-plugin.test.ts). The marker text is:This sacrifices some guidance detail for staying inside that budget, but the load-bearing part — "NOT retrievable" / "re-running gives the same cut" — is what stops the retry loop, so it comes first.
Test plan
src/plugins/result-truncation-plugin.test.ts(new): asserts the marker never promises a retrievable remainder, and that it survives a realcreateSizeCapTransformspill (blob content ends with the marker, inline output still points attool-output:///{id})tests/unit/ripgrep-plugin.test.ts: existing real-chain oversized-grep tests still pass withinMAX_RESULT_CHARS + 200bunx prettier --check/bunx eslinton touched filesbun run typecheck,bun run buildbun test ./src ./tests ./evals(5116 pass, 1 pre-existing unrelated failure insrc/agent/lsp-availability.test.tspresent on main with nonode_modules— not touched by this change)Fixes CL-6908