Skip to content

fix(tee): keep head + tail when raw output exceeds max_file_size#1696

Open
iliaal wants to merge 1 commit intortk-ai:developfrom
iliaal:fix/tee-tail-preservation
Open

fix(tee): keep head + tail when raw output exceeds max_file_size#1696
iliaal wants to merge 1 commit intortk-ai:developfrom
iliaal:fix/tee-tail-preservation

Conversation

@iliaal
Copy link
Copy Markdown

@iliaal iliaal commented May 3, 2026

Before

write_tee_file truncated raw output at max_file_size (1MB default) by keeping the first 1MB of bytes and dropping the rest. The tee log is the recovery hatch agents fall back to when the live filter dropped a needed signal, but for tail-heavy commands the head is the part that doesn't matter.

Triggered by rtk make test on a php-src checkout: ~17000 phpt progress lines followed by a pass/fail summary. The make filter kept only the first ~16 progress lines (separate fix on feat/php-tooling). The tee log captured 1MB of progress lines and also dropped the summary. Same head-bias on a tail-heavy command, two layers down.

After

write_tee_file keeps a 25/75 head/tail slice with a --- N bytes truncated from middle --- marker between them. Default 1MB budget gives ~256KB of head plus ~768KB of tail. The slicer rounds both cuts to UTF-8 char boundaries, so multi-byte input never panics.

Tail gets the larger share because tee mostly captures build and test output, where summaries and failure trailers live at the end. The head stays because the prologue often shows the command echo and config that explain what was running.

Scope rationale

  • Not adding a config knob for head/tail/balanced selection. 25/75 beats head-only for the cases that matter; can follow up if someone asks for selectable shapes.
  • Not changing the public API: max_file_size, RTK_TEE=0, force_tee_hint behave the same.
  • Not fixing the make filter itself. Lives on feat/php-tooling because that branch already touches PHP tooling. This PR fixes the recovery layer for every tail-heavy command, not just make.

Backward compatibility: marker text changed from --- truncated at N bytes --- to --- N bytes truncated from middle ---. Visible if anyone parses tee logs programmatically.

Test plan

  • cargo test --bin rtk: 1721 passed, 0 failed
  • cargo clippy --all-targets: no new warnings
  • cargo fmt --all: no churn
  • New test_write_tee_file_keeps_tail: 3000-line phpt-style run, verifies head + marker + tail all survive
  • Updated test_write_tee_file_truncation_utf8_boundary and test_write_tee_file_truncation_emoji: new split exercised with multi-byte chars at both cuts

The tee log is the recovery hatch when filters truncate. It used head-only
truncation at max_file_size (1MB by default), which discarded exactly the
information that tail-heavy commands (test runners, build summaries,
error trailers) put at the end. So a make test run with 17000+ progress
lines would tee the first 1MB of progress and lose the pass/fail summary.

Switch to a 25/75 head/tail split: keep the first quarter of the budget
(prologue, command echo, banner) and the last three quarters (where the
useful output lives for tail-heavy commands), with a marker between
documenting how many bytes were dropped. UTF-8 char boundaries are
respected on both ends.

Updated existing UTF-8 boundary tests to exercise the new split, and
added a tail-preservation test that simulates a make test run.
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