fix(control-ui-assets): keep emoji / surrogate pairs intact during last-line truncation#101591
Conversation
…st-line truncation .slice(0, 239) counts UTF-16 code units; an emoji straddling the cut point produces a lone surrogate rendering as in WebUI assets. Use [...last] spread to count full code points instead. Co-Authored-By: Claude Opus 4.8 <[email protected]>
b4b422e to
8b253d4
Compare
|
Codex review: needs maintainer review before merge. Reviewed July 7, 2026, 7:28 AM ET / 11:28 UTC. Summary PR surface: Source +1, Tests +40. Total +41 across 2 files. Reproducibility: yes. source-level: current main uses Review metrics: none identified. 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 helper-based truncation and regression test once normal exact-head CI, base freshness, and maintainer review gates clear. Do we have a high-confidence way to reproduce the issue? Yes, source-level: current main uses Is this the best way to solve the issue? Yes. The latest head uses the existing AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 3901094ace58. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +1, Tests +40. Total +41 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
|
|
Land-ready at exact head Maintainer review replaced the proposed code-point truncation with the canonical UTF-16-safe helper, preserving the existing 239-code-unit payload plus ellipsis rather than allowing non-BMP input to exceed the 240-code-unit diagnostic cap. The added regression drives Validation:
The PR body was corrected to describe the actual failed-build diagnostic surface. No known proof gaps. |
|
Merged via squash.
|
…st-line truncation (openclaw#101591) * fix(control-ui-assets): keep emoji / surrogate pairs intact during last-line truncation .slice(0, 239) counts UTF-16 code units; an emoji straddling the cut point produces a lone surrogate rendering as in WebUI assets. Use [...last] spread to count full code points instead. Co-Authored-By: Claude Opus 4.8 <[email protected]> * fix(control-ui-assets): preserve diagnostic length cap --------- Co-authored-by: Claude Opus 4.8 <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
…st-line truncation (openclaw#101591) * fix(control-ui-assets): keep emoji / surrogate pairs intact during last-line truncation .slice(0, 239) counts UTF-16 code units; an emoji straddling the cut point produces a lone surrogate rendering as in WebUI assets. Use [...last] spread to count full code points instead. Co-Authored-By: Claude Opus 4.8 <[email protected]> * fix(control-ui-assets): preserve diagnostic length cap --------- Co-authored-by: Claude Opus 4.8 <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
summarizeCommandOutputinsrc/infra/control-ui-assets.tstruncates text with.slice()which counts UTF-16 code units. When a surrogate-pair character (emoji) straddles the cut boundary,.slice()produces a lone surrogate (e.g.\ud83d) that renders as `` in terminal output.This is user-visible: the truncated text reaches user-facing CLI, status, or log output, so any content containing emoji near the 238-character boundary can hit this.
Why This Change Was Made
Replace
.slice()withtruncateUtf16Safe()from@openclaw/normalization-core/utf16-sliceso the truncation counts full code points instead of UTF-16 code units. This matches the already-merged PR #101517 (session-cost-usage.ts) and the canonicalshortenTexthelper insrc/commands/text-format.ts:5.User Impact
Users will no longer see `` replacement characters in this output when emoji appear near truncation boundaries. Existing column width / character caps are preserved — the broken surrogate is dropped cleanly rather than rendered as a replacement character.
Evidence
Real environment tested: local OpenClaw source checkout, Node v24.13.1, PR head.
Exact steps after this patch:
Evidence after fix:
Observed result after fix:
truncateUtf16Safepreserves full code points; no lone surrogate reaches output. The broken surrogate pair is dropped cleanly rather than producing ``.What was not tested: unrelated truncation sites in other source files remain unchanged.
Regression Test Plan
Includes a focused regression test that verifies surrogate pair preservation at the truncation boundary.
AI-assisted.