fix(matrix): truncate reply context on code-point boundaries#97471
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 28, 2026, 1:57 PM ET / 17:57 UTC. Summary PR surface: Source +1, Tests +24. Total +25 across 2 files. Reproducibility: yes. with high-confidence source-level reproduction. Current main slices Matrix reply context at raw UTF-16 index 497, and a 496-character prefix plus an emoji leaves a dangling high surrogate before the ellipsis. Review metrics: none identified. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Next step before merge
Security Review detailsBest possible solution: Land the focused reply-context safe-slice change after required checks pass; keep the merged thread-context fix as the sibling precedent. Do we have a high-confidence way to reproduce the issue? Yes, with high-confidence source-level reproduction. Current main slices Matrix reply context at raw UTF-16 index 497, and a 496-character prefix plus an emoji leaves a dangling high surrogate before the ellipsis. Is this the best way to solve the issue? Yes. Reusing the existing plugin SDK AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against a10add753189. Label changesLabel justifications:
Evidence reviewedPR surface: Source +1, Tests +24. Total +25 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
30b05f6 to
54a9e28
Compare
truncateReplyBody used a raw value.slice(0, MAX_REPLY_BODY_LENGTH - 3) to shorten long reply bodies. When the cut index fell between the two UTF-16 code units of a surrogate pair (e.g. an emoji), the slice left a lone high surrogate before the ellipsis, which renders as a broken glyph in the reply context shown to the agent. Replace the raw slice with sliceUtf16Safe from the plugin SDK so the truncation never cuts inside a surrogate pair. A normal (non-astral) body is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
54a9e28 to
0a83b7a
Compare
|
@clawsweeper re-review Branch rebased onto current main ( |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Merged via squash.
|
…w#97471) truncateReplyBody used a raw value.slice(0, MAX_REPLY_BODY_LENGTH - 3) to shorten long reply bodies. When the cut index fell between the two UTF-16 code units of a surrogate pair (e.g. an emoji), the slice left a lone high surrogate before the ellipsis, which renders as a broken glyph in the reply context shown to the agent. Replace the raw slice with sliceUtf16Safe from the plugin SDK so the truncation never cuts inside a surrogate pair. A normal (non-astral) body is unaffected. Co-authored-by: ly-wang19 <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
…w#97471) truncateReplyBody used a raw value.slice(0, MAX_REPLY_BODY_LENGTH - 3) to shorten long reply bodies. When the cut index fell between the two UTF-16 code units of a surrogate pair (e.g. an emoji), the slice left a lone high surrogate before the ellipsis, which renders as a broken glyph in the reply context shown to the agent. Replace the raw slice with sliceUtf16Safe from the plugin SDK so the truncation never cuts inside a surrogate pair. A normal (non-astral) body is unaffected. Co-authored-by: ly-wang19 <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
…w#97471) truncateReplyBody used a raw value.slice(0, MAX_REPLY_BODY_LENGTH - 3) to shorten long reply bodies. When the cut index fell between the two UTF-16 code units of a surrogate pair (e.g. an emoji), the slice left a lone high surrogate before the ellipsis, which renders as a broken glyph in the reply context shown to the agent. Replace the raw slice with sliceUtf16Safe from the plugin SDK so the truncation never cuts inside a surrogate pair. A normal (non-astral) body is unaffected. Co-authored-by: ly-wang19 <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
…w#97471) truncateReplyBody used a raw value.slice(0, MAX_REPLY_BODY_LENGTH - 3) to shorten long reply bodies. When the cut index fell between the two UTF-16 code units of a surrogate pair (e.g. an emoji), the slice left a lone high surrogate before the ellipsis, which renders as a broken glyph in the reply context shown to the agent. Replace the raw slice with sliceUtf16Safe from the plugin SDK so the truncation never cuts inside a surrogate pair. A normal (non-astral) body is unaffected. Co-authored-by: ly-wang19 <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]> (cherry picked from commit 55d7b5b)
…w#97471) truncateReplyBody used a raw value.slice(0, MAX_REPLY_BODY_LENGTH - 3) to shorten long reply bodies. When the cut index fell between the two UTF-16 code units of a surrogate pair (e.g. an emoji), the slice left a lone high surrogate before the ellipsis, which renders as a broken glyph in the reply context shown to the agent. Replace the raw slice with sliceUtf16Safe from the plugin SDK so the truncation never cuts inside a surrogate pair. A normal (non-astral) body is unaffected. Co-authored-by: ly-wang19 <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
What Problem This Solves
Matrix reply context truncation used raw UTF-16 slicing. If an emoji or other astral character straddled the reply-context limit, the quoted context could contain a dangling surrogate half before the ellipsis.
Why This Change Was Made
The Matrix reply-context truncation now uses the existing plugin SDK
sliceUtf16Safehelper, preserving the existing 500-code-unit cap while avoiding malformed text at the truncation boundary.User Impact
Matrix reply context shown to agents no longer includes replacement characters or malformed text when long messages with emoji are truncated.
Evidence
Autoreview result: clean; no accepted/actionable findings.
After-fix Proof
Boundary probe on this PR branch:
{ "usesSafeSlice": true, "inputLength": 501, "outputLength": 499, "hasLoneSurrogate": false, "outputTail": "aaa..." }The probe places an emoji across the 497-code-unit slice boundary before the ellipsis. The after-fix output drops the emoji whole and leaves no lone UTF-16 surrogate.