Skip to content

fix(agents): preserve ANSI sanitizer state across bash chunks#103706

Merged
steipete merged 2 commits into
openclaw:mainfrom
jincheng-xydt:fix/103668-stateful-ansi-sanitizer
Jul 19, 2026
Merged

fix(agents): preserve ANSI sanitizer state across bash chunks#103706
steipete merged 2 commits into
openclaw:mainfrom
jincheng-xydt:fix/103668-stateful-ansi-sanitizer

Conversation

@jincheng-xydt

@jincheng-xydt jincheng-xydt commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Closes #103668

What Problem This Solves

When bash output splits ANSI or OSC controls across stdout callbacks, stateless per-chunk stripping can leak control fragments into streamed output, final results, and spill files.

The maintained patch keeps a bounded incremental parser in terminal-core and preserves one instance for each bash command. One-shot stripping remains unchanged, the existing residual-control policy runs after the incremental parser without a second ANSI pass, and no new public or OutputAccumulator API is introduced.

Evidence

Exact rebased head: ab6a0de3649ce6fa4cafc26fa9462afd282fc2de

  • node scripts/run-vitest.mjs packages/terminal-core/src/ansi.test.ts src/agents/shell-utils.test.ts src/agents/sessions/bash-executor.test.ts: 82 passed, 1 skipped across two shards.
  • The executor regression proves split CSI, OSC, C1, compatibility-prefix, streamed callback, final-result, truncation, and sanitized spill-file behavior.
  • Branch autoreview completed clean with no accepted or actionable findings.
  • Blacksmith Testbox changed-surface run: https://github.com/openclaw/openclaw/actions/runs/29675777375. Scoped structure and formatting gates passed; the remaining Plugin SDK baseline failure is pre-existing on current main and limited to six unrelated config/channel modules.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: M labels Jul 10, 2026
@jincheng-xydt
jincheng-xydt force-pushed the fix/103668-stateful-ansi-sanitizer branch from 42decc9 to 4aab25d Compare July 10, 2026 13:33
@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. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 10, 2026
@clawsweeper

clawsweeper Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 19, 2026, 2:29 AM ET / 06:29 UTC.

Summary
The PR adds a bounded stateful ANSI/OSC sanitizer for bash output streams so control sequences split across stdout callbacks are removed consistently from streamed output, final results, and spill files.

PR surface: Source +237, Tests +149. Total +386 across 7 files.

Reproducibility: yes. The linked report gives a deterministic current-main callback-split probe, and the PR discussion includes an A/B result where the regression test fails against the base implementation and passes with this change.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: src/agents/sessions/bash-executor.test.ts, unknown-data-model-change: src/agents/sessions/bash-executor.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

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

Next step before merge

  • [P2] No narrow repair remains: the final hardening commit is assigned to steipete, so the remaining action is normal owner review and current-head merge/check confirmation.

Security
Cleared: The patch adds no dependency, workflow, publishing, permission, or secret-handling surface; its bounded parser state reduces the prior input-driven retention concern.

Review details

Best possible solution:

Land the bounded terminal-core sanitizer after the current-head required checks and final owner review confirm the merge result remains clean; keep the existing one-shot sanitizer behavior unchanged.

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

Yes. The linked report gives a deterministic current-main callback-split probe, and the PR discussion includes an A/B result where the regression test fails against the base implementation and passes with this change.

Is this the best way to solve the issue?

Yes. Keeping bounded parser state in terminal-core and instantiating it once per bash command is the narrowest maintainable fix because it preserves streaming, existing output bounds, and the one-shot sanitizer contract.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.

Label justifications:

  • P2: This fixes deterministic bash-output integrity leakage with bounded impact to agent shell execution and no demonstrated crash, security-boundary, or data-loss escalation.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR discussion supplies a real child-process stdout-callback transcript showing cleaned streamed/final output and sanitized spill-file behavior, supplemented by focused exact-head test evidence.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR discussion supplies a real child-process stdout-callback transcript showing cleaned streamed/final output and sanitized spill-file behavior, supplemented by focused exact-head test evidence.
Evidence reviewed

PR surface:

Source +237, Tests +149. Total +386 across 7 files.

View PR surface stats
Area Files Added Removed Net
Source 4 246 9 +237
Tests 3 155 6 +149
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 7 401 15 +386

What I checked:

  • Canonical parser boundary: The PR introduces AnsiSequenceStripper in terminal-core with finite state for text, escape, CSI, OSC, and compatibility control forms; its stated invariant is constant-size parser state so unterminated control payloads cannot bypass output limits. (packages/terminal-core/src/ansi-sequences.ts:39, ab6a0de3649c)
  • Bash integration: The bash executor creates one streaming sanitizer per command and applies it through the existing decoded-text transform, preserving streaming and spill-file ownership in OutputAccumulator. (src/agents/sessions/bash-executor.ts:51, ab6a0de3649c)
  • Regression coverage: The PR adds chunk-boundary coverage for CSI, OSC, C1 forms, compatibility controls, streamed callbacks, final output, truncation, and sanitized spilled output. (src/agents/sessions/bash-executor.test.ts:48, ab6a0de3649c)
  • Real behavior evidence: The discussion includes a real child_process.spawn transcript showing clean streamed and final output for split controls plus no spill-file leakage for a large unterminated OSC payload; the PR body reports focused exact-head validation for the final rebased commit. (src/agents/shell-utils.test.ts:43, ab6a0de3649c)
  • Current review provenance: The final hardening commit on this PR is authored by steipete, who is also assigned to the PR; prior completed ClawSweeper cycles found no remaining actionable patch findings. (packages/terminal-core/src/ansi-sequences.ts:39, ab6a0de3649c)

Likely related people:

  • steipete: Authored the final hardening commit that establishes the terminal-core parser boundary and is assigned to this PR. (role: recent area contributor and assigned decision owner; confidence: high; commits: ab6a0de3649c; files: packages/terminal-core/src/ansi-sequences.ts, src/agents/sessions/bash-executor.ts, src/agents/shell-utils.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 (23 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-17T17:09:56.356Z sha 665289d :: needs maintainer review before merge. :: none
  • reviewed 2026-07-17T17:54:03.797Z sha 665289d :: needs maintainer review before merge. :: none
  • reviewed 2026-07-17T19:05:48.090Z sha 96c338c :: needs maintainer review before merge. :: none
  • reviewed 2026-07-17T19:48:11.245Z sha 96c338c :: needs maintainer review before merge. :: none
  • reviewed 2026-07-17T21:13:08.327Z sha 4e8dd26 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-17T21:55:57.200Z sha 4e8dd26 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-17T23:06:53.368Z sha fd973ed :: needs maintainer review before merge. :: none
  • reviewed 2026-07-17T23:48:31.635Z sha fd973ed :: needs maintainer review before merge. :: none

@brownser

Copy link
Copy Markdown

Requesting changes at head 4aab25d7e5accef37771c33b4ce0d9dc7d131bb5.

Thanks for tackling the chunk-boundary ANSI leak. The stateful transform hook is the right boundary, but this implementation is not safe to merge yet because two P1 issues remain:

  1. Incomplete compatibility grammar across chunks. The existing one-shot stripAnsiSequences() grammar strips multi-byte non-CSI ESC forms such as ESC ( B. The new incremental scanner only buffers ESC CSI/OSC, so split input like A\x1b( + BB is not equivalent to joined one-shot sanitization.

  2. Unbounded pending output retention. After an unterminated OSC introducer, later command output stays inside pending and bypasses the OutputAccumulator truncation/spill accounting. That creates an input-driven availability risk for long-running or malicious process output.

Please replace raw pending payload accumulation with bounded parser state, cover the full existing stripAnsiSequences compatibility grammar, and add regressions for split non-CSI ESC forms plus large unterminated-control output. After that, rerun the focused tests/lint and add a real process transcript/log showing clean output when a control sequence crosses callback boundaries.

@jincheng-xydt
jincheng-xydt force-pushed the fix/103668-stateful-ansi-sanitizer branch from 4aab25d to 00ee805 Compare July 10, 2026 23:17
@jincheng-xydt

Copy link
Copy Markdown
Contributor Author

Updated this PR after the maintainer/ClawSweeper feedback.

What changed:

  • Rebases cleanly on current upstream/main (42c80df6f5).
  • Replaced raw pending-output buffering with a bounded AnsiSequenceStripper state machine:
    • split CSI/C1 CSI still sanitizes across chunks
    • split OSC drops payload until BEL / ESC ST / C1 ST without retaining the payload
    • compatibility grammar split sequences such as A ESC ( + BB now sanitize to AB
  • Kept OutputAccumulator as the byte/line bound owner; transformed spill files now receive the same sanitized stream as visible output.
  • Added regressions for:
    • chunked OSC/CSI/C1 CSI
    • chunked compatibility charset sequence ESC ( B
    • large unterminated OSC payloads not leaking into output or spill files
    • transform finish() flushing stateful transforms

Local validation on head 00ee805a93:

  • node scripts/run-vitest.mjs packages/terminal-core/src/ansi.test.ts src/agents/sessions/bash-executor.test.ts src/agents/sessions/tools/output-accumulator.test.ts -> passed; terminal-core 35 tests, bash/output accumulator 11 tests
  • ./node_modules/.bin/oxlint packages/terminal-core/src/ansi.ts packages/terminal-core/src/ansi.test.ts src/agents/sessions/bash-executor.ts src/agents/sessions/bash-executor.test.ts src/agents/sessions/tools/output-accumulator.ts src/agents/sessions/tools/output-accumulator.test.ts -> passed
  • node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.agents.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test-agents.tsbuildinfo -> passed
  • node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.non-agents.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test-non-agents.tsbuildinfo -> passed
  • git diff --check -> passed

Note: node scripts/run-oxlint.mjs ... hit a local artifact-preparation timeout (plugin-sdk boundary root shims timed out after 300000ms) before linting; the direct oxlint invocation against the changed files passed.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 10, 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.

@jincheng-xydt
jincheng-xydt force-pushed the fix/103668-stateful-ansi-sanitizer branch from 00ee805 to cb4b7dd Compare July 10, 2026 23:22
@jincheng-xydt

Copy link
Copy Markdown
Contributor Author

Added real after-fix process proof on the rebased head.

Current head: cb4b7ddba4 on top of upstream main 2f9cb92006.

Real behavior proof, outside the Vitest harness:

What this proves:

  • The proof used a real child process via , not a unit-test mock.
  • The process wrote ANSI/OSC sequences across delayed stdout callback boundaries.
  • streamed clean chunks to and returned clean final output.
  • Split compatibility grammar is sanitized across callback boundaries.
  • A large unterminated OSC payload is dropped by the streaming sanitizer and does not leak into visible output or the full-output spill file.

Validation on this rebased head:

  • -> passed; terminal-core 35 tests, bash/output accumulator 11 tests
  • -> passed
  • -> passed
  • -> passed

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 10, 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.

Re-review progress:

@jincheng-xydt

Copy link
Copy Markdown
Contributor Author

Correction for the previous proof comment: the shell interpreted Markdown backticks while posting. This is the clean proof text for the exact pushed head.

Current head: cb4b7dd on top of upstream main 2f9cb92.

Real behavior proof, outside the Vitest harness:

PROOF_OPENCLAW_BASH_STREAM_ANSI=PASS
runtime_path=executeBashWithOperations -> child_process.spawn stdout callbacks
split_stream_chunks=["A","B","C","D","E","F","G","H"]
split_result_output="ABCDEFGH"
split_result_truncated=false
unterminated_osc_output="safe\n"
unterminated_osc_truncated=false
unterminated_osc_spill_bytes=5
unterminated_osc_spill_preview="safe\n"

What this proves:

  • The proof used a real child process via child_process.spawn, not a unit-test mock.
  • The process wrote ANSI/OSC sequences across delayed stdout callback boundaries.
  • executeBashWithOperations streamed clean chunks to onChunk and returned clean final output.
  • Split compatibility grammar ESC ( B is sanitized across callback boundaries.
  • A large unterminated OSC payload is dropped by the streaming sanitizer and does not leak into visible output or the full-output spill file.

Validation on this rebased head:

  • node scripts/run-vitest.mjs packages/terminal-core/src/ansi.test.ts src/agents/sessions/bash-executor.test.ts src/agents/sessions/tools/output-accumulator.test.ts -> passed; terminal-core 35 tests, bash/output accumulator 11 tests
  • ./node_modules/.bin/oxlint packages/terminal-core/src/ansi.ts packages/terminal-core/src/ansi.test.ts src/agents/sessions/bash-executor.ts src/agents/sessions/bash-executor.test.ts src/agents/sessions/tools/output-accumulator.ts src/agents/sessions/tools/output-accumulator.test.ts -> passed
  • node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.agents.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test-agents.tsbuildinfo -> passed
  • git diff --check -> passed

@clawsweeper re-review

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed 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. labels Jul 10, 2026
@jincheng-xydt
jincheng-xydt force-pushed the fix/103668-stateful-ansi-sanitizer branch from cb4b7dd to 0b41953 Compare July 12, 2026 00:22
@jincheng-xydt

Copy link
Copy Markdown
Contributor Author

Updated the PR to address the latest ClawSweeper P1 findings.

Current head: 0b41953 on top of upstream main b5251c4.

Repairs:

  • Replaced retained incomplete compatibility bytes with finite parser state. The stream sanitizer no longer stores the raw pending control payload; it tracks only phase and parameter digit count.
  • Fixed OSC handling after a stray ESC. If ESC is followed by a non-backslash byte, that byte is still checked as a BEL or C1 ST terminator, so following command output is preserved.
  • Added regressions for large unterminated compatibility controls and OSC payloads containing ESC immediately before BEL/C1-ST terminators.

Real child-process proof on this head:

PROOF_OPENCLAW_BASH_STREAM_ANSI_REPAIR=PASS
runtime_path=executeBashWithOperations -> child_process.spawn stdout callbacks
split_stream_chunks=["A","B","C","D","E","F","G","H"]
split_result_output="ABCDEFGH"
large_compat_output="safe\n"
large_compat_truncated=false
large_compat_spill_bytes=5
large_compat_spill_preview="safe\n"
osc_stray_esc_terminators_output="AB CD"

Validation on this exact head:

  • node scripts/run-vitest.mjs packages/terminal-core/src/ansi.test.ts src/agents/sessions/bash-executor.test.ts src/agents/sessions/tools/output-accumulator.test.ts -> passed; terminal-core 38 tests, bash/output accumulator 11 tests
  • ./node_modules/.bin/oxlint packages/terminal-core/src/ansi.ts packages/terminal-core/src/ansi.test.ts src/agents/sessions/bash-executor.ts src/agents/sessions/bash-executor.test.ts src/agents/sessions/tools/output-accumulator.ts src/agents/sessions/tools/output-accumulator.test.ts -> passed
  • node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.agents.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test-agents.tsbuildinfo -> passed
  • git diff --check -> passed

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 12, 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.

Re-review progress:

@jincheng-xydt
jincheng-xydt force-pushed the fix/103668-stateful-ansi-sanitizer branch from 0b41953 to ad441fe Compare July 12, 2026 00:29
@jincheng-xydt

Copy link
Copy Markdown
Contributor Author

Rebased onto current upstream main 04f945f and force-pushed the branch.

Current head: ad441fe.

Exact-head focused validation after this rebase:

  • node scripts/run-vitest.mjs packages/terminal-core/src/ansi.test.ts src/agents/sessions/bash-executor.test.ts src/agents/sessions/tools/output-accumulator.test.ts -> passed; terminal-core 38 tests, bash/output accumulator 11 tests

The previous repair proof remains the same on this rebased head: finite parser state for incomplete compatibility controls, corrected OSC ESC+BEL/C1-ST handling, and real child_process.spawn proof for split output callbacks.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 12, 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.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and 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. labels Jul 12, 2026
@jincheng-xydt
jincheng-xydt force-pushed the fix/103668-stateful-ansi-sanitizer branch from b2eda7b to 665289d Compare July 17, 2026 17:03
@jincheng-xydt

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased onto current upstream/main. Exact head: 665289dd84f6af4170851c1ae4b066d9816c9f3e.

Evidence:

  • changed-file oxfmt --check --threads=1 passed
  • changed-file oxlint passed
  • git diff --check upstream/main...HEAD passed
  • ANSI, output-accumulator, and bash-executor suites: 3 files / 51 tests passed

@clawsweeper

clawsweeper Bot commented Jul 17, 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.

Re-review progress:

@jincheng-xydt
jincheng-xydt force-pushed the fix/103668-stateful-ansi-sanitizer branch from 665289d to 96c338c Compare July 17, 2026 19:02
@jincheng-xydt

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased onto current upstream/main. Exact head: 96c338c3bb8c1a048b6298d652def576d8444f40.

Evidence:

  • changed-file formatting, lint, and git diff --check passed
  • ANSI, output-accumulator, and bash-executor suites: 3 files / 51 tests passed

@clawsweeper

clawsweeper Bot commented Jul 17, 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.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. labels Jul 17, 2026
@jincheng-xydt
jincheng-xydt force-pushed the fix/103668-stateful-ansi-sanitizer branch from 96c338c to 4e8dd26 Compare July 17, 2026 21:09
@jincheng-xydt

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased onto current upstream/main to pick up the upstream correction for the unrelated package-acceptance workflow assertion that failed compact shard 7. Exact head: 4e8dd26a526b9ac043d59772841332a78f803dfd.

Evidence:

  • ANSI, output-accumulator, and bash-executor suites: 3 files / 51 tests passed
  • changed-file formatting, lint, and git diff --check passed
  • the prior compact-shard failure was in test/scripts/package-acceptance-workflow.test.ts, outside this PR diff; current main now matches its expected workflow expression.

@clawsweeper

clawsweeper Bot commented Jul 17, 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.

Re-review progress:

@jincheng-xydt
jincheng-xydt force-pushed the fix/103668-stateful-ansi-sanitizer branch from 4e8dd26 to fd973ed Compare July 17, 2026 23:03
@jincheng-xydt

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased onto current upstream/main. Exact head: fd973edec90978931ebb1026ea4462e298d8b6a6. The previous compact-shard failure was an unrelated timing-sensitive src/process/child-process.test.ts assertion; the changed-path scan produced no diff-policy finding. Focused ANSI/bash evidence remains 3 files / 51 tests passed.

@clawsweeper

clawsweeper Bot commented Jul 17, 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.

Re-review progress:

jincheng-xydt and others added 2 commits July 19, 2026 07:25
Keep incremental parser state in the canonical terminal owner, avoid a second sanitizer pass, and leave OutputAccumulator and public terminal APIs unchanged.\n\nCo-authored-by: Jicheng Xu <[email protected]>
@steipete
steipete force-pushed the fix/103668-stateful-ansi-sanitizer branch from fd973ed to ab6a0de Compare July 19, 2026 06:25
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jul 19, 2026
@steipete
steipete merged commit 5a81e9f into openclaw:main Jul 19, 2026
132 of 134 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

steipete pushed a commit that referenced this pull request Jul 20, 2026
…1364)

The local exec runtime sanitized each stdout/stderr chunk with the
stateless `sanitizeBinaryOutput`, so an escape sequence straddling a read
boundary was escaped into visible text instead of being consumed. The
remote bash path already uses a per-stream parser via
`createStreamingBinaryOutputSanitizer` (#103706); this applies the same
treatment to the local path, with separate parsers for stdout and stderr
so neither stream can consume the other's pending sequence.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 20, 2026
…aw#103706)

* fix(agents): preserve ANSI sanitizer state across bash chunks

* fix(agents): harden streaming ANSI sanitization

Keep incremental parser state in the canonical terminal owner, avoid a second sanitizer pass, and leave OutputAccumulator and public terminal APIs unchanged.\n\nCo-authored-by: Jicheng Xu <[email protected]>

---------

Co-authored-by: Peter Steinberger <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 20, 2026
…nclaw#111364)

The local exec runtime sanitized each stdout/stderr chunk with the
stateless `sanitizeBinaryOutput`, so an escape sequence straddling a read
boundary was escaped into visible text instead of being consumed. The
remote bash path already uses a per-stream parser via
`createStreamingBinaryOutputSanitizer` (openclaw#103706); this applies the same
treatment to the local path, with separate parsers for stdout and stderr
so neither stream can consume the other's pending sequence.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: M 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.

[Bug]: Bash ANSI sanitization leaks sequences split across output chunks

4 participants