fix(process): UTF-8 command output corrupts at Windows byte limits#105274
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 18, 2026, 5:34 PM ET / 21:34 UTC. Summary PR surface: Source +22, Tests +68, Config 0. Total +90 across 7 files. Reproducibility: no. high-confidence current-head reproduction is available in the evidence. The source and Windows-focused tests clearly identify the bounded UTF-8 decode path, but the live terminal run predates the relevant later branch change. 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:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Retain the isolated UTF-8 runner and add a redacted Windows 2025 current-head terminal run that exercises truncated stdout and stderr plus the normal SSH identity-JSON control, then review the exact head with required checks. Do we have a high-confidence way to reproduce the issue? No high-confidence current-head reproduction is available in the evidence. The source and Windows-focused tests clearly identify the bounded UTF-8 decode path, but the live terminal run predates the relevant later branch change. Is this the best way to solve the issue? Yes, conditionally: a separate UTF-8-only runner is narrower and safer than changing the default Windows code-page-detecting path, provided current-head Windows proof confirms stdout, stderr, and the SSH JSON control. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 77a42adce4d5. Label changesLabel justifications:
Evidence reviewedPR surface: Source +22, Tests +68, Config 0. Total +90 across 7 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
Review history (13 earlier review cycles; latest 8 shown)
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
294cd8d to
983f957
Compare
|
@clawsweeper re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Co-authored-by: 杨浩宇0668001029 <[email protected]>
|
Merged via squash.
|
…penclaw#105274) * fix(process): preserve byte-capped UTF-8 output on Windows * fix(process): skip codepage probe for UTF-8 output Co-authored-by: 杨浩宇0668001029 <[email protected]> --------- Co-authored-by: Peter Steinberger <[email protected]>
Related: #106495
What Problem This Solves
Fixes an issue where byte-capped UTF-8 command output on Windows could be corrupted when the cap split a multibyte character. The retained incomplete UTF-8 prefix was passed through Windows console-code-page auto-detection, so output such as
afollowed by a partial emoji could decode with an invalid trailing character instead of the longest valid UTF-8 prefix,a.This affects the SSH node-pairing identity probe because OpenSSH returns the remote JSON stream as UTF-8 while the probe keeps only the first 64 KiB.
Why This Change Was Made
The process runner now has a narrow UTF-8-specific entry point for commands whose output encoding is defined. It applies the existing byte-boundary cleanup on every platform and decodes the retained bytes as UTF-8. The default command runner keeps its existing Windows console-code-page auto-detection, including GBK and other legacy encodings.
The SSH node-pairing probe opts into the UTF-8 path. No SSH trust, pairing eligibility, timeout, command construction, public configuration, or protocol behavior changes.
User Impact
Windows gateways no longer corrupt a byte-capped SSH identity stream when truncation lands inside a UTF-8 character. Complete legacy-code-page command output remains unchanged.
Evidence
node scripts/run-vitest.mjs src/process/exec.windows.test.tsreturned a corrupted partial character with 3 truncated bytes instead ofawith 5 truncated bytes.a测prefix remainsa测with the original auto-detecting runner.test/package-scripts.test.tsandtest/scripts/openclaw-cross-os-release-workflow.test.tspassed (20 tests).node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfopassed.oxfmt --check,run-oxlint.mjs, andgit diff --checkpassed.codex review --base upstream/mainfound the initial legacy-code-page regression; the implementation was revised to isolate UTF-8 decoding, and the final review reported no defect.pnpm test:windows:cipassed one22cfd34043e253010e2e5f83e4afb2077dda1ad: https://github.com/mushuiyu886/openclaw/actions/runs/29510723363/job/87663176141Real behavior proof
Behavior addressed: Byte-capped UTF-8 stdout and stderr on Windows retain the longest complete UTF-8 prefix instead of passing an incomplete character to console-code-page decoding.
Real environment tested: GitHub-hosted Windows 2025 (
Windows_NT 10.0.26100 x64) on exact PR heade22cfd34043e253010e2e5f83e4afb2077dda1ad. The run was manually dispatched for proof and did not use a test runner or mock subprocess for the production-runner scenario.Exact steps or command run after this patch: Installed the exact-head checkout, then used
node --import tsxto import the productionsrc/process/exec.tsfacade. The production runners spawned the real Windows Node executable for a three-byte head cap, separately exercised stdout and stderr, and ran a normal identity-JSON control. The same run then executedpnpm test:windows:ci.Evidence after fix:
head=e22cfd34043e253010e2e5f83e4afb2077dda1ad
platform=win32
os=Windows_NT 10.0.26100 x64
default_head.code_points=U+0061,U+FFFD
default_head.truncated_bytes=3
utf8_head.code_points=U+0061
utf8_head.replacement_character=false
utf8_head.truncated_bytes=5
utf8_stderr.code=7
utf8_stderr.code_points=U+0061
utf8_stderr.replacement_character=false
utf8_stderr.truncated_bytes=5
identity_json_control.code=0
identity_json_control.unchanged=true
Observed result after fix: The unchanged default path reproduced the invalid partial-character decode. The UTF-8-specific production path returned
afor both stdout and stderr, contained no replacement character, and accounted for all five omitted bytes. A normal identity JSON payload was returned unchanged with exit code 0.What was not tested: A physical Windows gateway connected to a separate SSH server or a live device-pairing approval. The changed real Windows child-process capture, UTF-8 boundary cleanup, stdout/stderr decoding, normal JSON control, and Windows CI test path were exercised directly.
Risk / Compatibility
Low and localized. Existing callers keep the same automatic Windows decoding behavior. Only callers using the new internal UTF-8 runner receive forced UTF-8 decoding and boundary cleanup; this PR changes the SSH identity probe only.