fix: prevent garbled emoji at remaining text limits#101685
Conversation
Co-authored-by: 0668000787 <[email protected]> Co-authored-by: ben.li <[email protected]> Co-authored-by: 廖石荣 0668000909 <[email protected]> Co-authored-by: 陈志强0668000989 <[email protected]>
|
Codex review: needs real behavior proof before merge. Reviewed July 7, 2026, 9:41 AM ET / 13:41 UTC. Summary PR surface: Source +14, Tests +254. Total +268 across 27 files. Reproducibility: yes. from source inspection. Current main and the reviewed PR head raw-slice the thread-binding intro webhook persona at the 80-code-unit boundary, so a label with a surrogate-pair emoji crossing that boundary can produce a lone surrogate. Review metrics: 1 noteworthy metric.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Copy recommended automerge instructionNext step before merge
Security Review findings
Review detailsBest possible solution: Land one canonical consolidation only after it includes the Discord thread-binding persona helper and regression test from the focused Discord PR, or keep the focused Discord PR open as the owner for that remaining path. Do we have a high-confidence way to reproduce the issue? Yes, from source inspection. Current main and the reviewed PR head raw-slice the thread-binding intro webhook persona at the 80-code-unit boundary, so a label with a surrogate-pair emoji crossing that boundary can produce a lone surrogate. Is this the best way to solve the issue? No, not yet. Reusing truncateUtf16Safe is the right fix shape, but this consolidation is incomplete until it covers the thread-binding persona helper or stops superseding the focused Discord fix. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against b95b9e448794. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +14, Tests +254. Total +268 across 27 files. View PR surface stats
Acceptance criteria:
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
Review history (1 earlier review cycle)
|
|
Land-ready proof for exact head
Dependency proof: inspected Codex app-server dynamic-tool docs/protocol/decoder and app-list error construction directly ( Known gap: no live Discord send or Codex server session was run because neither external protocol changes; exact caller tests and direct upstream contract inspection cover the bounded-text behavior. |
|
Merged via squash.
|
* fix: keep remaining bounded text UTF-16 safe Co-authored-by: 0668000787 <[email protected]> Co-authored-by: ben.li <[email protected]> Co-authored-by: 廖石荣 0668000909 <[email protected]> Co-authored-by: 陈志强0668000989 <[email protected]> * test: use tracked prompt template fixture --------- Co-authored-by: 0668000787 <[email protected]> Co-authored-by: ben.li <[email protected]> Co-authored-by: 廖石荣 0668000909 <[email protected]> Co-authored-by: 陈志强0668000989 <[email protected]>
* fix: keep remaining bounded text UTF-16 safe Co-authored-by: 0668000787 <[email protected]> Co-authored-by: ben.li <[email protected]> Co-authored-by: 廖石荣 0668000909 <[email protected]> Co-authored-by: 陈志强0668000989 <[email protected]> * test: use tracked prompt template fixture --------- Co-authored-by: 0668000787 <[email protected]> Co-authored-by: ben.li <[email protected]> Co-authored-by: 廖石荣 0668000909 <[email protected]> Co-authored-by: 陈志强0668000989 <[email protected]>
* fix(ui): keep workboard capture text truncation UTF-16 safe Replace raw .slice(0, N - 3) with truncateUtf16Safe in clampSessionCaptureText and clampSessionCaptureTitle to prevent lone surrogates when emoji cross the truncation boundary. Completes the UTF-16 hardening started in #101685, which added the import but only covered buildCardSessionLabel. * test(ui): cover workboard UTF-16 boundaries * docs(changelog): note Workboard UTF-16 fix * docs(changelog): leave release notes to release flow --------- Co-authored-by: Peter Steinberger <[email protected]>
…#102544) * fix(ui): keep workboard capture text truncation UTF-16 safe Replace raw .slice(0, N - 3) with truncateUtf16Safe in clampSessionCaptureText and clampSessionCaptureTitle to prevent lone surrogates when emoji cross the truncation boundary. Completes the UTF-16 hardening started in openclaw#101685, which added the import but only covered buildCardSessionLabel. * test(ui): cover workboard UTF-16 boundaries * docs(changelog): note Workboard UTF-16 fix * docs(changelog): leave release notes to release flow --------- Co-authored-by: Peter Steinberger <[email protected]>
Related: #101634
Related: #101640
Related: #101641
Related: #101642
Related: #101644
Related: #101646
Related: #101659
Related: #101660
What Problem This Solves
Fixes an issue where users could see a dangling replacement character or malformed text when emoji and other supplementary Unicode characters crossed length limits in Codex diagnostics, Discord persona names, TUI errors, dashboard titles, session summaries, prompt templates, and Control UI labels.
Why This Change Was Made
Uses the existing UTF-16-safe truncation primitive at the remaining distinct bounded-text call sites instead of adding per-surface helpers. The replacement also covers every bound in the embedded-agent observation pipeline and both string and structured-content session discovery paths, while omitting unrelated formatting churn and an ASCII-only sanitizer where surrogate safety is irrelevant.
The Codex adapter behavior was checked directly against upstream app-server protocol and implementation sources: dynamic-tool responses are the documented
inputText/inputImageunion, unsupported response kinds are locally rendered diagnostics, and app-list errors are arbitrary text. Discord's webhook contract retains the existing 80-code-unit username limit.User Impact
Emoji and other supplementary characters now remain well-formed when these labels, previews, diagnostics, and source inputs reach their existing length caps. Limits, fallback values, ellipsis behavior, and public configuration remain unchanged.
Evidence
tbx_01kwyae3xcaszr9ckk2z1bg0ew(tidal-crab), hydration run https://github.com/openclaw/openclaw/actions/runs/288678498128b0258c1531d890500d8594354ad1c1ab6aaa5bb: https://github.com/openclaw/openclaw/actions/runs/28870356599 (success)corepack pnpm check:changed: passed in 10m28s, including four tsgo projects, core/extensions oxlint, import-cycle checks, and architecture guardsgit diff --check: passedThe source PRs are superseded by this clean-main consolidation; contributor credit is preserved in the commit trailers.