Skip to content

fix(auto-reply): keep suppressed reply text preview truncation UTF-16 safe - #101575

Merged
steipete merged 2 commits into
openclaw:mainfrom
wm0018:fix/autoreply-preview-utf16-safe-truncation
Jul 7, 2026
Merged

steipete merged 2 commits into
openclaw:mainfrom
wm0018:fix/autoreply-preview-utf16-safe-truncation

Conversation

@wm0018

@wm0018 wm0018 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes an issue where suppressed auto-reply log previews could contain broken U+FFFD replacement characters () when reply text contained an emoji or CJK supplementary character at the 160-character log truncation boundary.

String.prototype.slice(0, 160) cuts at UTF-16 code unit boundaries. Emoji like 🚀 are surrogate pairs (2 code units). When a pair straddles position 160, the lone high surrogate renders as in log output. truncateUtf16Safe was already imported in this file (line 8) but unused at this call site.

Why This Change Was Made

Replace text.replace(...).slice(0, 160) with truncateUtf16Safe(text.replace(...), 160) — the same helper already imported in this file. One-line, no new dependencies.

User Impact

Suppressed auto-reply log previews containing emoji or CJK near the 160-character limit now display cleanly truncated text in logs.

Evidence

Tests

New tests: and .

Standalone proof (production helper, same head)

formatSuppressedReplyPayloadForLog is a private function — not exported for direct unit testing. The proof below exercises the exact truncateUtf16Safe helper at the same 160-char boundary used in the production code.

=== BEFORE fix: text.replace(/\s+/g, ' ').slice(0, 160) ===
  text.length: 161 (159 y's + surrogate-pair emoji)
  sliced last code unit: 0xd83d
  lone surrogate: true
  log would show: "yyy\ud83d" <- U+FFFD garbled

=== AFTER fix: truncateUtf16Safe(text.replace(/\s+/g, ' '), 160) ===
  safe.length: 159
  safe matches: true
  broken chars: NONE

Files Changed (2 files, +22/-1)

 src/auto-reply/reply/dispatch-from-config.test.ts | 21 +++++++++++++++++++++
 dispatch-from-config.ts      |  2 +-

Trivially safe: same helper already imported at line 8, same UTF-16-safe pattern used across all other similar fixes.

… safe

String.prototype.slice at offset 160 can split surrogate pairs in
reply text previews logged for suppressed auto-replies. Replace raw
slice(0, 160) with truncateUtf16Safe — already imported in this file.
@wm0018
wm0018 force-pushed the fix/autoreply-preview-utf16-safe-truncation branch from 96b68b8 to 5a5c7d7 Compare July 7, 2026 10:50
@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 7, 2026, 7:01 AM ET / 11:01 UTC.

Summary
The PR changes suppressed auto-reply log preview formatting to use truncateUtf16Safe and adds helper-level emoji-boundary truncation tests.

PR surface: Source 0, Tests +21. Total +21 across 2 files.

Reproducibility: yes. source inspection gives a high-confidence reproduction path: on current main, 159 BMP characters plus an emoji passed through the suppressed log preview hits .slice(0, 160) and can leave a lone high surrogate. I did not verify the full dispatch log in a live OpenClaw run.

Review metrics: none identified.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted real behavior proof showing a suppressed auto-reply log preview with an emoji at the boundary after the fix.
  • Prefer a production-path regression assertion for the suppressed log formatter or dispatch log output instead of helper-only tests.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The PR body includes standalone helper console output, but not real suppressed auto-reply log output after the patch; add redacted terminal/log proof or equivalent production-path evidence, then update the PR body to trigger re-review.

Risk before merge

  • [P1] Real behavior proof does not yet show the changed suppressed auto-reply logging path; the included transcript only demonstrates the helper boundary behavior.

Maintainer options:

  1. Decide the mitigation before merge
    Land the focused helper swap after production-path proof, ideally redacted terminal/log output or a dispatch-level assertion, confirms suppressed auto-reply previews no longer emit dangling surrogates.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] No repair job is needed right now; the remaining action is contributor-supplied real behavior proof for the changed logging path before merge.

Security
Cleared: The diff only swaps to an existing internal string helper and adds tests; it does not touch dependencies, workflows, secrets, permissions, or code-execution surfaces.

Review details

Best possible solution:

Land the focused helper swap after production-path proof, ideally redacted terminal/log output or a dispatch-level assertion, confirms suppressed auto-reply previews no longer emit dangling surrogates.

Do we have a high-confidence way to reproduce the issue?

Yes, source inspection gives a high-confidence reproduction path: on current main, 159 BMP characters plus an emoji passed through the suppressed log preview hits .slice(0, 160) and can leave a lone high surrogate. I did not verify the full dispatch log in a live OpenClaw run.

Is this the best way to solve the issue?

Yes, using the existing truncateUtf16Safe helper at the log-preview boundary is the narrowest maintainable production fix. The proof should be strengthened by exercising the suppressed logging path, not only the helper.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 16348ddec3ad.

Label changes

Label changes:

  • add P3: The PR fixes a narrow log-preview formatting edge case without changing delivery, config, provider routing, or user-visible runtime behavior.
  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The PR body includes standalone helper console output, but not real suppressed auto-reply log output after the patch; add redacted terminal/log proof or equivalent production-path evidence, then update the PR body to trigger re-review.

Label justifications:

  • P3: The PR fixes a narrow log-preview formatting edge case without changing delivery, config, provider routing, or user-visible runtime behavior.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The PR body includes standalone helper console output, but not real suppressed auto-reply log output after the patch; add redacted terminal/log proof or equivalent production-path evidence, then update the PR body to trigger re-review.
Evidence reviewed

PR surface:

Source 0, Tests +21. Total +21 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 1 1 0
Tests 1 21 0 +21
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 22 1 +21

Acceptance criteria:

  • [P1] pnpm test src/auto-reply/reply/dispatch-from-config.test.ts -- --runInBand.

What I checked:

Likely related people:

  • steipete: The current formatSuppressedReplyPayloadForLog implementation and raw slice(0, 160) preview line were introduced in commit c9c4226, authored by Peter Steinberger; root policy maps Peter to steipete. (role: introduced current behavior; confidence: high; commits: c9c4226a23a3; files: src/auto-reply/reply/dispatch-from-config.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. labels Jul 7, 2026
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Land-ready at exact head 4eb5787710334c8eb0c1cd057c4a57a1203c1626.

Maintainer review kept the one-line runtime fix and replaced the helper-only tests with a dispatch-level regression. The test configures sendPolicy: deny, captures the real logVerbose message, verifies the existing 160-code-unit preview cap drops a straddling surrogate pair cleanly, and confirms final delivery remains suppressed.

Validation:

  • canonical formatting and git diff --check
  • fresh Codex autoreview: clean, correctness confidence 0.88
  • exact-head hosted CI: 73 passing checks, no failures or pending checks
  • scripts/pr review-validate-artifacts 101575
  • OPENCLAW_TESTBOX=1 scripts/pr prepare-run 101575

No known proof gaps.

@steipete
steipete merged commit d26a842 into openclaw:main Jul 7, 2026
101 checks passed
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 8, 2026
… safe (openclaw#101575)

* fix(auto-reply): keep suppressed reply text preview truncation UTF-16 safe

String.prototype.slice at offset 160 can split surrogate pairs in
reply text previews logged for suppressed auto-replies. Replace raw
slice(0, 160) with truncateUtf16Safe — already imported in this file.

* test(auto-reply): exercise suppressed preview logging

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants