Skip to content

fix(core): repair truncation-severed spotlight wrapper in compaction prompt#6613

Merged
bug-ops merged 1 commit into
mainfrom
fix/6584-compaction-input-sanitizer
Jul 20, 2026
Merged

fix(core): repair truncation-severed spotlight wrapper in compaction prompt#6613
bug-ops merged 1 commit into
mainfrom
fix/6584-compaction-input-sanitizer

Conversation

@bug-ops

@bug-ops bug-ops commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • build_compression_prompt (crates/zeph-core/src/agent/tool_execution/focus.rs) truncates each message to 500 chars before handing it to the compression LLM. Untrusted tool-result content is already spotlight-wrapped (<tool-output>/<external-data>) at write time by sanitize_tool_output — the sole sanitization point for tool output — so it is not raw/unfiltered as originally assumed by the issue.
  • The blind 500-char truncation could sever the wrapper's closing tag for long untrusted content, leaving an opened-but-never-closed spotlight block in the compression prompt — the boundary marker telling the compression LLM "untrusted data ends here" would go missing exactly when it matters most.
  • A single message can bundle multiple concatenated wrappers of different kinds from one multi-tool-call turn (tier_loop.rs flattens every tool result of a turn into one message; build_tool_output_source maps different tools to different wrapper kinds). The fix checks both wrapper kinds independently by open/close tag count — not by presence, and not gated on the message's aggregate trust level — so a mixed-kind batch gets repaired correctly regardless of which wrapper was severed.
  • Adversarial review (2 rescope rounds) confirmed the original double-sanitize approach was incorrect (re-wrapping already-wrapped content); this PR implements the narrower, correctly-scoped fix instead.

Closes #6584

Test plan

  • cargo +nightly fmt --check
  • cargo clippy --profile ci --workspace --all-targets --features "desktop,ide,server,chat,pdf,scheduler,testing" -- -D warnings
  • cargo nextest run --config-file .github/nextest.toml --workspace --features "desktop,ide,server,chat,pdf,scheduler" --lib --bins (14992 passed)
  • RUSTFLAGS="-D warnings" RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc --no-deps --workspace --features "desktop,ide,server,chat,pdf,scheduler"
  • gitleaks protect --staged --no-banner --redact
  • New unit tests for repair_truncated_spotlight_wrapper: severed <tool-output> close, severed <external-data> close, mixed-batch with one balanced + one severed wrapper, trust_level None/Some(0) no-op, intact sub-500-char wrapper not double-appended

@github-actions github-actions Bot added bug Something isn't working documentation Improvements or additions to documentation rust Rust code changes core zeph-core crate size/M Medium PR (51-200 lines) and removed bug Something isn't working labels Jul 20, 2026
@bug-ops
bug-ops enabled auto-merge (squash) July 20, 2026 20:53
@bug-ops
bug-ops force-pushed the fix/6584-compaction-input-sanitizer branch from 5cd53ba to 864ad8e Compare July 20, 2026 20:54
@github-actions github-actions Bot added the bug Something isn't working label Jul 20, 2026
…prompt

build_compression_prompt truncates each message to 500 chars before
handing it to the compression LLM. Untrusted tool-result content is
already spotlight-wrapped (<tool-output>/<external-data>) at write time
by sanitize_tool_output, but the blind truncation could sever the
wrapper's closing tag for long content, leaving an opened-but-never-
closed spotlight block in the prompt. A single message can bundle
multiple concatenated wrappers of different kinds from a multi-tool-
call turn, so the repair checks both wrapper kinds independently by
open/close tag count rather than gating on the message's aggregate
trust level.
@bug-ops
bug-ops force-pushed the fix/6584-compaction-input-sanitizer branch from 864ad8e to e5bc0dd Compare July 20, 2026 20:56
@bug-ops
bug-ops merged commit cacf469 into main Jul 20, 2026
43 checks passed
@bug-ops
bug-ops deleted the fix/6584-compaction-input-sanitizer branch July 20, 2026 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working core zeph-core crate documentation Improvements or additions to documentation rust Rust code changes size/M Medium PR (51-200 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

compress_context/request_compaction input-side has no IPI/sanitizer filtering before reaching the compression LLM

1 participant