6f70a2832e
Closes #1441. When `@`-mentioning a file larger than the 128 KB `MAX_MENTION_FILE_BYTES` ceiling, the truncator clipped the buffer to exactly the cap — which on CJK / emoji content frequently landed mid-codepoint and left a stray U+FFFD replacement char at the cut point. The fix uses `str::from_utf8(...).error_len()` to distinguish the two ways a truncated UTF-8 buffer can fail: - `error_len() == None` means the failure is an incomplete tail sequence — exactly the boundary case we want to handle. Round `buffer.truncate()` down to `valid_up_to()` so the trailing bytes are dropped cleanly. - `error_len() == Some(_)` means the file genuinely contains invalid UTF-8 bytes (not at the truncation boundary). Leave the buffer intact so the subsequent `from_utf8(&buffer)` call surfaces the canonical "file is not UTF-8" error rather than silently dropping the invalid bytes. Collapsed the if-let-then-if pattern to `if let Err(e) = ... && e.error_len().is_none()` to satisfy the workspace's `collapsible_if` clippy gate. Harvested from PR #1495 by @CrepuscularIRIS Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>