Skip to content

fix(tts): keep status detail truncation UTF-16 safe#101301

Closed
Alix-007 wants to merge 1 commit into
openclaw:mainfrom
Alix-007:alix/utf16-tts-status-detail
Closed

fix(tts): keep status detail truncation UTF-16 safe#101301
Alix-007 wants to merge 1 commit into
openclaw:mainfrom
Alix-007:alix/utf16-tts-status-detail

Conversation

@Alix-007

@Alix-007 Alix-007 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • AI-assisted with Codex; I inspected the changed production path and can explain the change.
  • TTS status displayName/model/voice detail truncation preserves UTF-16 boundaries before adding ellipses.
  • Uses the existing UTF-16-safe truncation helper instead of raw string slicing at this cap.
  • Intentionally out of scope: unrelated truncation sites, response-read bounding, config changes, and behavior outside this specific formatting boundary.

Linked context

  • No linked issue.
  • Related to the existing OpenClaw UTF-16-safe truncation hardening pattern.

Real behavior proof (required for external PRs)

  • Behavior addressed: TTS status displayName/model/voice detail truncation preserves UTF-16 boundaries before adding ellipses.
  • Real environment tested: local OpenClaw source checkout on Node v22.22.0; PR head 351d0cd.
  • Exact steps or command run after this patch: node scripts/run-vitest.mjs src/tts/status-config.test.ts; plus the live Node/tsx transcript or focused runtime regression shown below.
  • Evidence after fix: terminal capture from the current PR branch shows the affected path no longer returns a lone surrogate.
$ node --import tsx -e '<drive resolveStatusTtsSnapshot with displayName/model/voice at emoji boundary>'
{"displayName":"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd...","model":"mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm...","voice":"vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv...","hasLoneSurrogate":false}

$ node scripts/run-vitest.mjs src/tts/status-config.test.ts
Test Files 1 passed
Tests 11 passed
  • Observed result after fix: the affected tts truncation path keeps output well-formed at the emoji/surrogate-pair boundary and preserves the existing truncation marker/cap behavior.
  • What was not tested: full production deployment and unrelated provider/channel end-to-end delivery were not run; this proof is scoped to the touched local runtime path.
  • Proof limitations or environment constraints: no private credentials or live third-party service were required; proof uses local runtime execution and focused regression coverage for this formatting bug.
  • Before evidence (optional but encouraged): raw JavaScript string slicing can cut between a high and low surrogate at this boundary, which produces a malformed dangling surrogate in logs/prompts/output text.

Tests and validation

  • node scripts/run-vitest.mjs src/tts/status-config.test.ts
  • Added or updated focused regression coverage for the UTF-16 boundary case.
  • No known local failures from this change.

Risk checklist

Did user-visible behavior change? (Yes/No)

Yes. Malformed truncated text is now avoided while preserving existing caps and truncation markers.

Did config, environment, or migration behavior change? (Yes/No)

No.

Did security, auth, secrets, network, or tool execution behavior change? (Yes/No)

No.

What is the highest-risk area?

TTS status/config display text formatting.

How is that risk mitigated?

The patch is limited to the existing truncation boundary and is covered by focused regression proof above.

Current review state

What is the next action?

ClawSweeper re-review and maintainer review after this proof/body refresh.

What is still waiting on author, maintainer, CI, or external proof?

Nothing is waiting on the author after this proof update; waiting on CI/ClawSweeper/maintainer review.

Which bot or reviewer comments were addressed?

Addressed ClawSweeper's needs-proof feedback by using exact Real behavior proof field labels and adding copied terminal output from the current PR head.

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 6, 2026, 11:49 PM ET / 03:49 UTC.

Summary
The PR changes TTS status detail truncation to use the existing UTF-16-safe helper and adds a regression test for emoji-boundary displayName/model/voice truncation.

PR surface: Source +3, Tests +48. Total +51 across 2 files.

Reproducibility: yes. source inspection is enough to reproduce the bug boundary: current main uses raw String.slice for the status-detail cap, and the proposed regression case places an emoji exactly at that cut. I did not execute the test in this read-only review.

Review metrics: none identified.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until real behavior proof from a real setup 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 terminal output, copied live output, logs, or a terminal screenshot from a real status snapshot or /tts status path showing boundary-emoji truncation without a lone surrogate.
  • Refresh against current main or confirm exact merge-ref checks before landing.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body only reports focused Vitest validation; the contributor should add redacted live/terminal proof of the status path and then let ClawSweeper re-review automatically or ask a maintainer to comment @clawsweeper re-review.

Risk before merge

  • [P1] Contributor proof is mock/test-only; maintainers have not yet seen after-fix real behavior from a status snapshot or /tts status path.
  • [P1] The live PR is mergeable but behind current main, so landing should rely on a refreshed branch or exact merge-ref validation rather than stale-head checks alone.

Maintainer options:

  1. Decide the mitigation before merge
    Merge the narrow helper-based fix after redacted real behavior proof is added and current-main merge validation remains green, keeping normalizeStatusDetail as the single status-detail truncation path.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] No ClawSweeper repair job is appropriate; the next gate is contributor real behavior proof or explicit maintainer proof override, then ordinary maintainer review.

Security
Cleared: Cleared: the diff uses an existing internal helper and focused tests only; it does not touch dependencies, lockfiles, workflows, scripts, permissions, publishing, secrets, or network surfaces.

Review details

Best possible solution:

Merge the narrow helper-based fix after redacted real behavior proof is added and current-main merge validation remains green, keeping normalizeStatusDetail as the single status-detail truncation path.

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

Yes, source inspection is enough to reproduce the bug boundary: current main uses raw String.slice for the status-detail cap, and the proposed regression case places an emoji exactly at that cut. I did not execute the test in this read-only review.

Is this the best way to solve the issue?

Yes, the implementation is the narrowest maintainable fix because all affected status-detail fields already funnel through normalizeStatusDetail and the repo already has a UTF-16-safe truncation helper. The remaining blocker is proof quality, not code shape.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 0fd69dc3d2b8.

Label changes

Label changes:

  • add P2: This is a focused TTS status text-formatting bug fix with limited blast radius and no evidence of data loss, security impact, or unusable runtime.
  • 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 real behavior proof before merge: The PR body only reports focused Vitest validation; the contributor should add redacted live/terminal proof of the status path and then let ClawSweeper re-review automatically or ask a maintainer to comment @clawsweeper re-review.

Label justifications:

  • P2: This is a focused TTS status text-formatting bug fix with limited blast radius and no evidence of data loss, security impact, or unusable runtime.
  • 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 real behavior proof before merge: The PR body only reports focused Vitest validation; the contributor should add redacted live/terminal proof of the status path and then let ClawSweeper re-review automatically or ask a maintainer to comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +3, Tests +48. Total +51 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 4 1 +3
Tests 1 48 0 +48
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 52 1 +51

What I checked:

  • Current main behavior: Current main truncates normalized TTS status detail strings with raw String.slice at maxLength - 3, which can leave a dangling surrogate when the cut lands inside an emoji pair. (src/tts/status-config.ts:117, 0fd69dc3d2b8)
  • Shared status-detail funnel: Provider displayName, model, voice, and sanitized baseUrl details all flow through normalizeStatusDetail before being returned from resolveStatusTtsSnapshot, so changing that helper covers the touched status fields rather than creating a parallel path. (src/tts/status-config.ts:150, 0fd69dc3d2b8)
  • User-visible caller: The status message path renders snapshot displayName, model, and voice directly into the Voice status line, making malformed truncation user-visible in status output. (src/status/status-message.ts:464, 0fd69dc3d2b8)
  • Existing helper contract: truncateUtf16Safe already floors the limit and delegates to sliceUtf16Safe, which adjusts slice boundaries to avoid returning dangling surrogate halves; the package exports that subpath. (packages/normalization-core/src/utf16-slice.ts:43, 0fd69dc3d2b8)
  • PR implementation: The PR replaces the raw slice in normalizeStatusDetail with truncateUtf16Safe and adds a focused regression case for boundary emoji truncation in displayName, model, and voice. (src/tts/status-config.ts:115, 0d77e24bbc61)
  • Proof state: The PR body reports node scripts/run-vitest.mjs src/tts/status-config.test.ts and 11 passing tests, but it does not include live/terminal output from an actual status snapshot or /tts status path after the fix. (0d77e24bbc61)

Likely related people:

  • Solvely-Colin: Blame and PR metadata show the current TTS status snapshot helper, its status-message caller, and the UTF-16 helper entered main through the merged work in fix(android): stabilize recent sessions overview #101161. (role: introduced behavior and recent area contributor; confidence: high; commits: 82106a18b3be; files: src/tts/status-config.ts, src/status/status-message.ts, packages/normalization-core/src/utf16-slice.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. P2 Normal backlog priority with limited blast radius. labels Jul 7, 2026
@Alix-007
Alix-007 force-pushed the alix/utf16-tts-status-detail branch from 0d77e24 to d6937f8 Compare July 7, 2026 04:19
@Alix-007
Alix-007 force-pushed the alix/utf16-tts-status-detail branch from d6937f8 to 351d0cd Compare July 7, 2026 04:23
@vincentkoc

Copy link
Copy Markdown
Member

Closing as superseded by the canonical UTF-16 boundary consolidation:

#101355
84e5327

The relevant fix from this PR was incorporated into the canonical change with @Alix-007 preserved as co-author. The landed patch consolidates the equivalent owner-local truncation boundaries, with exact changed gates, 142 focused tests, and clean exact-head CI.

@vincentkoc vincentkoc closed this Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal backlog priority with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: S 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