Skip to content

fix(llm): stop tool-trim from re-truncating read_file's own result#105

Merged
whykusanagi merged 4 commits into
mainfrom
fix/readfile-trim-budget-collision
Jul 15, 2026
Merged

fix(llm): stop tool-trim from re-truncating read_file's own result#105
whykusanagi merged 4 commits into
mainfrom
fix/readfile-trim-budget-collision

Conversation

@whykusanagi

Copy link
Copy Markdown
Owner

Follow-up to the large-file byte-path fold-in (#103), found by smoke-testing the built binary.

The collision

The fold-in introduced two 48 KiB budgets that turned out to overlap:

  • read_file caps returned content at 48 KiB.
  • the retry/pre-flight tool-trim caps a whole tool message at 48 KiB (maxToolMsgBytes).

A capped read_file result is 48 KiB of content plus its JSON wrapper (~49.6 KiB total message) — which exceeds 48 KiB. On a minified, newline-free file the trim cut into read_file's content and dropped everything after it, including total_bytes, yielding invalid JSON. Live repro: read_file on a 427785-byte file reported total_bytes=49606.

Fix

Raise maxToolMsgBytes to 64 KiB so the per-message trim sits above read_file's max message and below the 128 KiB history cap:

48 KiB read_file content < 64 KiB per-message trim < 128 KiB history cap

The trim remains a backstop for genuinely oversized (>64 KiB) tool messages. Regression guards on both sides pin the relationship (llm side: a ~49.6 KiB read_file-shaped message passes untrimmed; builtin side: read_file's message on a 420 KB minified file stays under 64 KiB with intact metadata).

Verified live

Installed binary, read_file on the 427785-byte fixture now returns total_bytes=427785, returned_bytes=49152, truncated=true with valid JSON. Full suite + lint green.

Smoke-testing the fold-in surfaced a collision between the two new budgets: a
capped read_file result is 48 KiB of content plus its JSON wrapper (~49.6 KiB
total message), which EXCEEDED maxToolMsgBytes (also 48 KiB). On a minified,
newline-free file the pre-flight trim then cut into read_file's content and
dropped everything after it — including total_bytes — producing invalid JSON.
The model saw garbage (reported total_bytes ~49606 for a 427785-byte file).

Raise maxToolMsgBytes to 64 KiB so the per-message trim sits ABOVE read_file's
max message and BELOW the 128 KiB history cap: 48 KiB content < 64 KiB message
trim < 128 KiB history. The trim stays a backstop for genuinely oversized
(> 64 KiB) tool messages. Regression guards on both sides pin the relationship.

Verified live: read_file on a 427 KB minified file now reports total_bytes=427785,
returned_bytes=49152, truncated=true with intact JSON (was corrupt pre-fix).
The release workflow built the signed multi-platform binaries with go 1.26.2,
which is vulnerable to GO-2026-5856 (Encrypted Client Hello privacy leak in
crypto/tls) — reachable in our LLM/tools TLS paths, so not an acceptable
unreachable transitive. CI's Security Scan already runs 1.26.5; align the
release build (and the stamped manifest go-version) so shipped artifacts carry
the fix. Caught by the release checklist govulncheck gate.
…tring

celeste index status prints a Project/Files/Symbols summary; the smoke check
grepped for a literal 'index' that isn't in that output, failing a working
command. Match on 'Symbols:' which the summary always contains.
Rewrite the auto-generated 1.14.0 changelog as one hand-written entry covering
the skills browser and the whole large-file byte-path fold-in (read cap, retry
trim, splice_file, the trim/read_file collision, the Go 1.26.5 bump) instead of
two terse bullets split across Features/Bug Fixes. Add splice_file to the README
dev-tools table and bump the tool counts 44 -> 45 (9 dev tools).
@whykusanagi
whykusanagi merged commit 87709be into main Jul 15, 2026
5 checks passed
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