Skip to content

fix(qa-lab): keep capture preview truncation UTF-16 safe#102715

Closed
cxbAsDev wants to merge 1 commit into
openclaw:mainfrom
cxbAsDev:fix/qa-lab-web-capture-utf16-safe
Closed

fix(qa-lab): keep capture preview truncation UTF-16 safe#102715
cxbAsDev wants to merge 1 commit into
openclaw:mainfrom
cxbAsDev:fix/qa-lab-web-capture-utf16-safe

Conversation

@cxbAsDev

@cxbAsDev cxbAsDev commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Fixes an unsafe UTF-16 truncation in the QA Lab web UI capture preview path.

What Problem This Solves

extensions/qa-lab/web/src/ui-render.ts truncates long captured scalar values for display using raw .slice(0, 280) for the head and .slice(-80) for the tail. If the captured text contains a supplementary Unicode character (e.g. an emoji) that straddles either boundary, the preview ends up with a dangling surrogate half.

Why This Change Was Made

Replaced the two raw .slice() calls with a local sliceUtf16Safe helper that mirrors the implementation in @openclaw/normalization-core/utf16-slice. Keeping the helper local avoids importing any plugin SDK barrel into the QA Lab web bundle, so no Node.js built-ins are pulled into the Vite browser build. The scalar redactor is exported so the regression tests can exercise the exact truncation path without rendering the full UI.

User Impact

QA Lab capture previews remain valid and readable when captured request/response bodies or fields contain emoji or other non-BMP characters.

Evidence

  • Focused regression test: node scripts/run-vitest.mjs extensions/qa-lab/web/src/ui-render.test.ts --run passes (9/9 tests).
  • The new tests place an emoji immediately after the 279-code-unit head boundary and immediately before the 79-code-unit tail boundary, asserting that the result contains no dangling high/low surrogates.
  • git diff --check passes.
  • pnpm exec oxfmt --check passes for the touched files.
  • node scripts/plugin-sdk-surface-report.mjs --check passes (no plugin SDK surface budget change).
  • pnpm qa:lab:build completes successfully after the change and produces a smaller bundle:
$ pnpm qa:lab:build
$ vite build --config extensions/qa-lab/web/vite.config.ts
vite v8.1.3 building client environment for production...
✓ 17 modules transformed.
rendering chunks...
computing gzip size...
extensions/qa-lab/web/dist/index.html                   0.44 kB │ gzip:  0.27 kB
extensions/qa-lab/web/dist/assets/index-BlQ-kj4N.css   57.47 kB │ gzip:  9.70 kB
extensions/qa-lab/web/dist/assets/index-CiCf4MpC.js   145.48 kB │ gzip: 33.77 kB

✓ built in 219ms

@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 9, 2026, 8:28 AM ET / 12:28 UTC.

Summary
The PR makes QA Lab web capture scalar preview truncation UTF-16 safe and adds regression tests for head and tail surrogate-boundary truncation.

PR surface: Source +25, Tests +31. Total +56 across 2 files.

Reproducibility: yes. Current main's redactCaptureScalar uses raw fixed-boundary UTF-16 slices, so a long captured string with an emoji crossing the head or tail boundary can produce a dangling surrogate half; this was verified by source inspection rather than executing the branch locally.

Review metrics: none identified.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

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

Rank-up moves:

  • none.

Next step before merge

  • No ClawSweeper repair lane is needed because the current PR has no actionable review findings.

Security
Cleared: No security or supply-chain issue was found; the current head changes only QA Lab web rendering and tests, with no dependency or lockfile changes.

Review details

Best possible solution:

Land this browser-safe truncation fix at the QA Lab web boundary with normal exact-head merge gates; a later shared utility can be considered only if it stays dependency-free for browser bundles.

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

Yes. Current main's redactCaptureScalar uses raw fixed-boundary UTF-16 slices, so a long captured string with an emoji crossing the head or tail boundary can produce a dangling surrogate half; this was verified by source inspection rather than executing the branch locally.

Is this the best way to solve the issue?

Yes. The PR fixes the affected QA Lab web rendering boundary, avoids the prior plugin SDK/browser-bundle import problem, and adds focused regression tests for both truncation edges.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied after-fix pnpm qa:lab:build output for the browser bundle, with the changed string behavior covered by focused regression output described in the evidence.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes copied after-fix pnpm qa:lab:build output for the browser bundle, with the changed string behavior covered by focused regression output described in the evidence.

Label justifications:

  • P2: The PR is a focused QA Lab web UI correctness fix with limited blast radius.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes copied after-fix pnpm qa:lab:build output for the browser bundle, with the changed string behavior covered by focused regression output described in the evidence.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied after-fix pnpm qa:lab:build output for the browser bundle, with the changed string behavior covered by focused regression output described in the evidence.
Evidence reviewed

PR surface:

Source +25, Tests +31. Total +56 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 27 2 +25
Tests 1 32 1 +31
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 59 3 +56

What I checked:

  • Repository policy applied: Root and extensions policy were read fully; extension boundary guidance supports avoiding core/private plugin SDK imports from bundled plugin web code. (extensions/AGENTS.md:22, 053567908316)
  • Current main bug path: Current main truncates long capture scalar previews with raw slice(0, 280) and slice(-80), which can split UTF-16 surrogate pairs at either boundary. (extensions/qa-lab/web/src/ui-render.ts:575, 053567908316)
  • Current PR patch: Current head adds a local sliceUtf16Safe helper, exports redactCaptureScalar for tests, and replaces the raw preview slices with safe slices. (extensions/qa-lab/web/src/ui-render.ts:597, 4ae40f20e871)
  • Canonical helper comparison: The existing normalization-core helper is dependency-free and documented as browser/UI bundle safe; the PR mirrors that implementation locally to avoid broad runtime imports. (packages/normalization-core/src/utf16-slice.ts:3, 053567908316)
  • Live PR state: Live PR data shows the current head changes only two QA Lab web files, has no dependency or lockfile changes, and the dependency/security guard checks completed successfully. (4ae40f20e871)
  • Feature history: Blame and history tie the current raw preview slicing path to the commit that added the current QA Lab UI render file; older QA Lab capture/runtime history points to the capture inspector and lab split work. (extensions/qa-lab/web/src/ui-render.ts:575, 6fef79a28d02)

Likely related people:

  • snowzlmbot: Authored the merged history that added the current QA Lab UI render file containing the raw capture preview slicing path. (role: introduced behavior; confidence: medium; commits: 6fef79a28d02, 220cadd42932; files: extensions/qa-lab/web/src/ui-render.ts, extensions/qa-lab/web/src/ui-render.test.ts)
  • Takhoffman: Authored and merged the QA Lab proxy capture stack and inspector work that owns the affected capture preview surface. (role: feature owner; confidence: medium; commits: 958c34e82cdb; files: extensions/qa-lab/src, extensions/qa-lab/web/src/ui-render.ts)
  • gumadeiras: Recent QA Lab split/runtime and Matrix coverage history touched the broader QA Lab runtime area that feeds this UI surface. (role: adjacent owner; confidence: low; commits: 4db162db7f3e; files: extensions/qa-lab/src, extensions/qa-lab/web/src/ui-render.ts)
  • steipete: Merged the PR associated with the commit that added the current QA Lab UI render file and authored adjacent commits in that merged history. (role: merger and adjacent contributor; confidence: low; commits: 6fef79a28d02, 4a0b0b31a9c0; files: extensions/qa-lab/web/src/ui-render.ts, extensions/qa-lab/web/src/ui-render.test.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.
Review history (1 earlier review cycle)
  • reviewed 2026-07-09T11:32:25.120Z sha c83ee3d :: needs real behavior proof before merge. :: [P1] Keep QA Lab preview slicing browser-safe

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 9, 2026
@cxbAsDev

cxbAsDev commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Addressed the browser-bundle import concern: src/plugin-sdk/text-utility-runtime.ts now imports sliceUtf16Safe/truncateUtf16Safe directly from @openclaw/normalization-core/utf16-slice instead of re-exporting them through src/utils.js (which pulls in node:fs/node:os/node:path). This keeps the QA Lab web Vite bundle from dragging Node.js built-ins in for this helper.

Added real-behavior proof: pnpm qa:lab:build now completes successfully after the import change; the build output is in the PR body. The existing focused regression tests (9/9) still pass.

@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@cxbAsDev
cxbAsDev force-pushed the fix/qa-lab-web-capture-utf16-safe branch from 06058a7 to ed3cb8b Compare July 9, 2026 12:06
@cxbAsDev
cxbAsDev requested a review from a team as a code owner July 9, 2026 12:06
@github-actions github-actions Bot added the dependencies-changed PR changes dependency-related files label Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Dependency graph guard cleared

This PR no longer has blocked dependency graph changes. A future dependency graph change requires a fresh /allow-dependencies-change comment after the guard blocks that new head SHA.

  • Current SHA: 4ae40f20e871fa6cf053014ec23a3430eeac7f06

@cxbAsDev

cxbAsDev commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Addressed the browser-bundle import concern without touching plugin SDK core:

  • extensions/qa-lab/web/src/ui-render.ts now imports sliceUtf16Safe directly from @openclaw/normalization-core/utf16-slice (dependency-free and browser-safe).
  • Added @openclaw/normalization-core as a devDependency of @openclaw/qa-lab and updated pnpm-lock.yaml.
  • This avoids pulling openclaw/plugin-sdk/text-utility-runtime into the QA Lab web bundle, which previously dragged Node.js built-ins through src/utils.js.
  • The plugin SDK surface report still passes (no budget change), and pnpm qa:lab:build now produces a smaller bundle (145.51 kB vs 285.85 kB before).

PR body and evidence section are updated with the new build output.

@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 9, 2026
@cxbAsDev
cxbAsDev force-pushed the fix/qa-lab-web-capture-utf16-safe branch from ed3cb8b to 46dccee Compare July 9, 2026 12:09
@cxbAsDev
cxbAsDev force-pushed the fix/qa-lab-web-capture-utf16-safe branch from 46dccee to 4ae40f2 Compare July 9, 2026 12:09
@github-actions github-actions Bot removed the dependencies-changed PR changes dependency-related files label Jul 9, 2026
@cxbAsDev

cxbAsDev commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Fixed the CI failures and addressed the browser-bundle concern without adding dependencies or touching plugin SDK core:

  • Removed the @openclaw/normalization-core dependency addition (dependency guard blocked it).
  • Inlined a small sliceUtf16Safe helper in extensions/qa-lab/web/src/ui-render.ts instead of importing any plugin SDK barrel. This keeps Node.js built-ins out of the QA Lab web Vite bundle entirely.
  • Verified node scripts/plugin-sdk-surface-report.mjs --check passes with no budget change.
  • Verified pnpm qa:lab:build still succeeds and the bundle stays small (145.48 kB).

PR body is updated with the latest build output and verification commands.

@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 9, 2026
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Thanks @cxbAsDev. #102823 landed the same UTF-16-safe QA Lab capture-preview behavior in 5ef269c, using the shared slicer for both head and tail edges and testing rendered output without exporting a private helper. This branch is fully superseded, so I’m closing it.

@steipete steipete closed this Jul 9, 2026
@cxbAsDev
cxbAsDev deleted the fix/qa-lab-web-capture-utf16-safe branch July 15, 2026 03:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extensions: qa-lab P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants