Skip to content

fix(line): strip internal tool-trace banners from outbound text#101708

Merged
steipete merged 3 commits into
openclaw:mainfrom
Pick-cat:fix/line-sanitize-outbound-90684
Jul 14, 2026
Merged

fix(line): strip internal tool-trace banners from outbound text#101708
steipete merged 3 commits into
openclaw:mainfrom
Pick-cat:fix/line-sanitize-outbound-90684

Conversation

@Pick-cat

@Pick-cat Pick-cat commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Part of #90684

What Problem This Solves

LINE replies could expose internal assistant tool-trace banners to end users. The normal inbound auto-reply path also bypassed the generic outbound adapter, so adding the adapter hook alone did not cover the primary LINE reply path.

Why This Change Was Made

This applies the shared sanitizeAssistantVisibleText boundary in both LINE delivery paths: the standard outbound adapter and inbound auto-reply delivery before Markdown conversion. Internal-only text is suppressed without consuming a reply token, while rich content and fenced examples remain intact.

The delivery result now carries whether visible output was actually sent, so dispatch can distinguish suppressed output from a user-visible reply. The reply-chunk fallback also tracks a successful reply-token batch and will not replay it if a later push chunk fails.

User Impact

LINE users no longer see internal tool-trace banners in bot replies. Normal prose, fenced examples, rich content, reply-token fallback, and chunked delivery remain supported. A later push failure no longer duplicates an already-delivered reply batch.

Evidence

  • Blacksmith Testbox tbx_01kxhbsb7dvp09f3qx22bjaxbc
  • Focused LINE delivery suite: 4 files, 37 tests passed
  • Full LINE suite: 27 files, 325 tests passed
  • pnpm check:changed: production TypeScript, lint, formatting, SDK baselines, storage/media/runtime guards, and import-cycle checks passed; extension-test TypeScript reproduced the untouched main failure fixed by fix(nextcloud-talk): restore replay test typecheck #107808
  • Targeted Oxfmt check passed for all eight changed files
  • Live loopback HTTP proof through the production LINE auto-reply orchestration:
    • sanitized visible reply reached the wire
    • reply batch succeeded, a later push returned HTTP 503, and the reply batch was not replayed
    • internal-only output produced zero HTTP requests
  • Fresh whole-PR autoreview after conflict resolution: no actionable findings, patch correct at 0.90 confidence
  • Hosted exact-head merge-ref CI: https://github.com/openclaw/openclaw/actions/runs/29373316329

Live proof output:

{"scenario":"LINE reply batch then failed push over HTTP","sanitizedChunkInput":"Visible answer.","wireAttemptsBeforeFailure":2,"replayedReplyBatch":false,"internalOnlyRequests":0}

Known gap: no credentialed round-trip against the external LINE service. The loopback proof exercised the production delivery orchestration and real HTTP request/failure semantics.

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 7, 2026, 10:42 AM ET / 14:42 UTC.

Summary
The PR adds a LINE outbound sanitizeText hook using sanitizeAssistantVisibleText() and a focused regression test for internal tool-trace banner stripping.

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

Reproducibility: yes. Current main is source-reproducible because the LINE adapter lacks sanitizeText, while shared delivery only applies the canonical assistant-visible sanitizer when an adapter supplies that hook.

Review metrics: 1 noteworthy metric.

  • Channel sanitizer hook: 1 added. The PR changes the LINE user-visible delivery path by adding the adapter hook that shared outbound delivery calls before sending text.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #90684
Summary: This PR is a LINE-specific candidate fix for the open cross-channel sanitizer issue; sibling PRs cover the same missing-hook invariant for other channels.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
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.

Rank-up moves:

  • none.

Risk before merge

  • [P1] The PR intentionally rewrites outbound LINE text before delivery; the canonical sanitizer and proof mitigate this, but false-positive stripping would affect user-visible messages if the sanitizer overmatches in LINE-specific content.

Maintainer options:

  1. Proceed With The Canonical Hook (recommended)
    Accept the bounded message-delivery risk because the PR uses the existing sanitizer hook pattern and includes terminal proof plus focused coverage.
  2. Require Live LINE Round Trip
    Ask for a redacted LINE client or runtime delivery proof if maintainers want client-level evidence before merging this channel change.
  3. Fold Into The Umbrella Cleanup
    Pause this PR only if maintainers decide LINE should wait for one shared sanitizer-boundary change across the remaining channels.

Next step before merge

  • No ClawSweeper repair lane is needed because the branch already makes the narrow code and test change; the remaining action is normal maintainer review and merge gating.

Security
Cleared: No security or supply-chain regression was found; the diff imports an existing SDK sanitizer and adds a colocated test without dependency, workflow, secret, or permission changes.

Review details

Best possible solution:

Land the narrow LINE hook after normal maintainer review and required checks; keep the remaining cross-channel cleanup tracked on #90684.

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

Yes. Current main is source-reproducible because the LINE adapter lacks sanitizeText, while shared delivery only applies the canonical assistant-visible sanitizer when an adapter supplies that hook.

Is this the best way to solve the issue?

Yes. This is the narrowest maintainable LINE-specific fix because it uses the existing plugin SDK hook and canonical sanitizer already accepted by sibling channels; a broader shared-boundary sanitizer can remain on the umbrella issue.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The updated PR body includes copied terminal output from the actual LINE plugin hook showing the banner stripped and ordinary prose preserved; no live LINE round trip was provided, but the affected boundary is pre-network sanitization.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The updated PR body includes copied terminal output from the actual LINE plugin hook showing the banner stripped and ordinary prose preserved; no live LINE round trip was provided, but the affected boundary is pre-network sanitization.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P1: Internal tool-trace scaffolding can leak into a real chat channel, which is an urgent user-facing channel workflow bug.
  • merge-risk: 🚨 message-delivery: The diff intentionally strips text from outbound LINE messages, so maintainers should notice the delivery-path behavior change before merge.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The updated PR body includes copied terminal output from the actual LINE plugin hook showing the banner stripped and ordinary prose preserved; no live LINE round trip was provided, but the affected boundary is pre-network sanitization.
  • proof: sufficient: Contributor real behavior proof is sufficient. The updated PR body includes copied terminal output from the actual LINE plugin hook showing the banner stripped and ordinary prose preserved; no live LINE round trip was provided, but the affected boundary is pre-network sanitization.
Evidence reviewed

PR surface:

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

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

What I checked:

Likely related people:

  • steipete: Current shallow blame points the LINE outbound adapter, shared delivery sanitizer gate, and sanitizer trace-line test at Peter Steinberger's recent current-main history. (role: recent area contributor / adjacent owner; confidence: medium; commits: 903a09ab858d; files: extensions/line/src/outbound.ts, src/infra/outbound/deliver.ts, src/shared/text/assistant-visible-text.test.ts)
  • vincentkoc: Vincent Koc merged the Google Chat sibling sanitizer PR and is also the committer on the current main tip inspected for this review. (role: sibling sanitizer merger / recent area contributor; confidence: medium; commits: 696c62400803, c8d95da14c5b; files: extensions/googlechat/src/channel.adapters.ts, extensions/googlechat/src/channel.test.ts)
  • ZengWen-DT: ZengWen-DT authored the merged Feishu sanitizer hook PR using the same sanitizeAssistantVisibleText outbound pattern under the same issue cluster. (role: sibling fix author; confidence: medium; commits: 6378d5efcc0a; files: extensions/feishu/src/channel.ts, extensions/feishu/src/outbound-tool-trace-sanitize.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-07T14:18:28.533Z sha cdf0ee3 :: needs real behavior proof before merge. :: none

@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. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jul 7, 2026
@Pick-cat

Pick-cat commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review — Evidence updated with negative control + direct node --import tsx plugin proof .

@clawsweeper

clawsweeper Bot commented Jul 7, 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. and removed 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. labels Jul 7, 2026
@steipete steipete self-assigned this Jul 14, 2026
@steipete
steipete marked this pull request as draft July 14, 2026 22:15
@steipete
steipete marked this pull request as ready for review July 14, 2026 22:15

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 80489d4894

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +91 to +92
if (replySucceeded) {
throw err;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve consumed reply-token state before rethrowing

When a later push fails after the initial reply batch succeeded (the new >5-chunk path), this rethrow means deliverLineAutoReply never returns the { replyTokenUsed: true } state for monitor.ts to adopt. The shared reply dispatcher catches delivery errors and continues the delivery chain, so any subsequent block/final payload in the same LINE turn will still think the reply token is unused and will try to reply with an already-consumed token instead of going straight to push. Surface the error only after the caller has a way to retain the consumed-token state.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the fix/line-sanitize-outbound-90684 branch from 7a1901a to e7ea781 Compare July 14, 2026 22:32
@steipete

Copy link
Copy Markdown
Contributor

Land-ready at exact head e7ea781554393669a9785c4e7d2a5035cd271a18 after maintainer refactor, one necessary conflict resolution, and full review.

What changed:

  • canonical assistant-visible sanitization now covers both the standard LINE outbound adapter and the custom inbound auto-reply path
  • internal-only output sends nothing and does not consume the reply token
  • visible-send state is propagated so dispatch distinguishes suppressed output from a user-visible reply
  • a successful reply-token batch is never replayed when a later push chunk fails
  • fenced examples, rich content, and literal low-level sends remain intact

Remote proof on Blacksmith Testbox tbx_01kxhbsb7dvp09f3qx22bjaxbc:

corepack pnpm test extensions/line/src/outbound-tool-trace-sanitize.test.ts extensions/line/src/auto-reply-delivery.test.ts extensions/line/src/reply-chunks.test.ts extensions/line/src/send.test.ts
# 4 files, 37 tests passed

corepack pnpm test extensions/line
# 27 files, 325 tests passed

corepack pnpm check:changed
# production tsgo, lint, formatting, SDK baselines, storage/media/runtime guards, and import-cycle scan passed
# extension-test tsgo reproduced the identical untouched Nextcloud failure in main CI 29372109256; #107808 fixed it immediately afterward

Targeted Oxfmt passed for all eight changed files. Fresh whole-PR autoreview found no actionable issues.

Live loopback HTTP proof exercised production LINE auto-reply orchestration: sanitized visible text reached the wire; the reply batch succeeded; the next push failed with HTTP 503; exactly two wire attempts occurred; the reply batch was not replayed; internal-only output made zero requests.

{"scenario":"LINE reply batch then failed push over HTTP","sanitizedChunkInput":"Visible answer.","wireAttemptsBeforeFailure":2,"replayedReplyBatch":false,"internalOnlyRequests":0}

Hosted exact-head merge-ref CI: https://github.com/openclaw/openclaw/actions/runs/29373316329

Known proof gap: no credentialed round-trip against the external LINE service. The loopback proof used the production orchestration and real HTTP request/failure semantics.

@steipete
steipete merged commit 30a241c into openclaw:main Jul 14, 2026
89 of 90 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 15, 2026
…claw#101708)

* fix(line): strip internal tool-trace banners from outbound text

* fix(line): sanitize inbound assistant replies

* chore: retrigger PR CI

---------

Co-authored-by: Pick-cat <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: line Channel integration: line merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary 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.

2 participants