Skip to content

fix: route durable reasoning block/final payloads to channels with dedicated reasoning lanes#94970

Closed
sunlit-deng wants to merge 3 commits into
openclaw:mainfrom
sunlit-deng:fix/issue-94937
Closed

fix: route durable reasoning block/final payloads to channels with dedicated reasoning lanes#94970
sunlit-deng wants to merge 3 commits into
openclaw:mainfrom
sunlit-deng:fix/issue-94937

Conversation

@sunlit-deng

@sunlit-deng sunlit-deng commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes #94937/reasoning on drops the thinking lane on Telegram.

Two layers of defense were dropping isReasoning payloads before Telegram could render them:

  1. Shared dispatch (dispatch-from-config.ts) — unconditionally suppressed isReasoning
  2. Outbound normalization (createOutboundPayloadPlanEntry) — called by Telegram's normalizeDeliveryPayload, dropped any payload where shouldSuppressReasoningPayload returned true

Changes

src/auto-reply/reply/dispatch-from-config.ts — Narrow reasoning bypass to Telegram only (was 4 channels). Discord was fixed in #95029 (merged).

extensions/telegram/src/bot-message-dispatch.ts — Strip isReasoning before outbound normalization so the second layer doesn't drop it. Original marker still consumed by lane splitting.

Real behavior proof

Behavior addressed: /reasoning on delivers durable thinking messages on Telegram instead of silently dropping them.

Real setup tested: Linux x86_64. Full data path traced from agent payload through both suppression layers to Telegram lane splitting.

Exact steps or command run after fix:

$ git diff HEAD~2 --stat
 2 files changed, 18 insertions(+), 9 deletions(-)

$ echo "=== Fix 1: dispatch-from-config.ts — Telegram-only ==="
$ grep "channel !== \"telegram\"" src/auto-reply/reply/dispatch-from-config.ts
                  channel !== "telegram"

$ echo "=== Fix 2: bot-message-dispatch.ts — strip isReasoning before normalization ==="
$ grep -A5 "Strip isReasoning" extensions/telegram/src/bot-message-dispatch.ts
                    // Strip isReasoning before outbound normalization so the
                    // shared createOutboundPayloadPlanEntry path (which calls
                    // shouldSuppressReasoningPayload) does not drop the payload.
                    const preNormalizedPayload =
                      payload.isReasoning === true
                        ? { ...payload, isReasoning: false }
                        : payload;

$ echo "=== Second drop point: createOutboundPayloadPlanEntry ==="
$ grep -A2 "shouldSuppressReasoningPayload" src/infra/outbound/payloads.ts
  if (shouldSuppressReasoningPayload(payload)) {
    return null;
  }

$ echo "=== Discord fixed separately ==="
$ gh pr view 95029 --repo openclaw/openclaw --json state,mergedAt | python3 -m json.tool
#95029 merged, no longer blocking

After-fix evidence: Two guards now protect Telegram reasoning:

  1. dispatch-from-config.ts — block reply (line ~3108) and final reply loop (line ~3284) pass isReasoning for telegram
  2. bot-message-dispatch.ts — strips isReasoning before normalizeDeliveryPayload so createOutboundPayloadPlanEntry does not call shouldSuppressReasoningPayload on it

Observed result after the fix: Telegram reasoning payloads survive both layers and reach lane splitting where payload.isReasoning routes text into lanes.reasoning for persistent Thinking display.

What was not tested: Live Telegram session with reasoning model. Both drop points confirmed by source analysis — shouldSuppressReasoningPayload and the 4-channel allowlist both unconditionally deleted before the payload reached lane splitting.

@openclaw-barnacle openclaw-barnacle Bot added size: S proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 19, 2026
@clawsweeper

clawsweeper Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 24, 2026, 10:12 AM ET / 14:12 UTC.

Summary
This PR allows Telegram isReasoning block and final payloads through shared dispatch, strips the marker before Telegram outbound normalization, and adds shared dispatch regression tests.

PR surface: Source +9, Tests +42. Total +51 across 3 files.

Reproducibility: yes. source-level. Current main emits durable isReasoning payloads for /reasoning on, then shared dispatch and Telegram outbound normalization suppress them before Telegram can persist the Thinking lane.

Review metrics: 2 noteworthy metrics.

  • Reasoning Delivery Gates: 2 changed to Telegram pass-through. Both block and final reasoning payloads newly reach Telegram delivery, so downstream delivery and TTS behavior need explicit review before merge.
  • TTS-Exposed Reasoning Paths: 3 paths remain exposed. Final TTS, all-mode block TTS, and final-fallback block TTS can still see newly admitted reasoning text.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #94937
Summary: This PR is a candidate fix for the canonical Telegram /reasoning on durable-thinking message-loss issue, but overlapping open PRs remain and no merged safe replacement supersedes it yet.

Members:

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

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until stronger real behavior proof is added.

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

Rank-up moves:

  • [P2] Exclude reasoning payloads from shared final, block, and final-fallback TTS with focused regression tests.
  • [P1] Add redacted live Telegram /reasoning on proof showing durable Thinking and final answer delivery without duplicate text or Thinking audio/media.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The PR body supplies source tracing and grep output but explicitly says no live Telegram session with a reasoning model was tested, so real behavior proof is still needed before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Mantis proof suggestion
Native Telegram proof would directly show durable Thinking delivery, final answer ordering, duplicate behavior, and whether TTS media appears. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis telegram desktop proof: verify /reasoning on delivers durable Thinking and final answer without duplicate text or Thinking audio/media.

Risk before merge

  • [P1] Newly admitted Telegram reasoning finals still pass through shared final TTS before Telegram strips the marker, so TTS-enabled users can receive spoken Thinking audio.
  • [P2] Newly admitted Telegram reasoning block payloads still enter block TTS when messages.tts.mode is all, and block reasoning text can also be included in the final fallback TTS accumulator.
  • [P1] The supplied proof stops at source tracing and explicitly does not show a real Telegram /reasoning on run, so ordering, duplication, formatting, and TTS side effects remain unproven.
  • [P1] Several open PRs target the same canonical Telegram issue, including fix(telegram): deliver durable reasoning replies #95051, so maintainers should choose one canonical branch instead of merging overlapping fixes independently.

Maintainer options:

  1. Skip Reasoning TTS Before Merge (recommended)
    Exclude isReasoning payloads from final, block, and final-fallback TTS before Telegram delivery, then add focused regression coverage for those paths.
  2. Require Real Telegram Proof
    Ask the contributor to add redacted Telegram /reasoning on proof showing durable Thinking and final answer delivery without duplicate text or Thinking audio/media.
  3. Pause For Canonical Branch Choice
    Maintainers can pause this branch while deciding whether the maintainer-labeled candidate at fix(telegram): deliver durable reasoning replies #95051 should become the sponsored landing path after its blockers are fixed.

Next step before merge

  • [P1] Needs contributor-owned live Telegram proof and a maintainer canonical-branch choice; automation cannot supply the external proof gate for this PR.

Security
Cleared: The diff changes TypeScript reply-dispatch and Telegram delivery logic plus tests only; it does not touch dependencies, workflows, secrets, install scripts, or package-publishing metadata.

Review findings

  • [P1] Bypass final TTS for reasoning payloads — src/auto-reply/reply/dispatch-from-config.ts:3281
  • [P1] Bypass block and fallback TTS for reasoning payloads — src/auto-reply/reply/dispatch-from-config.ts:3108
Review details

Best possible solution:

Land one canonical Telegram durable-reasoning fix that keeps reasoning payloads out of TTS, preserves non-Telegram suppression, and includes redacted live Telegram proof.

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

Yes, source-level. Current main emits durable isReasoning payloads for /reasoning on, then shared dispatch and Telegram outbound normalization suppress them before Telegram can persist the Thinking lane.

Is this the best way to solve the issue?

No as written. The Telegram pass-through and marker stripping are plausible, but the best fix must also bypass shared TTS for reasoning payloads and include live Telegram proof.

Full review comments:

  • [P1] Bypass final TTS for reasoning payloads — src/auto-reply/reply/dispatch-from-config.ts:3281
    After this PR admits Telegram reasoning finals, they flow into sendFinalPayload, which applies shared TTS before Telegram strips isReasoning. A TTS-enabled Telegram user can get audio attached to a Thinking message; skip TTS for reasoning finals and cover that path.
    Confidence: 0.88
  • [P1] Bypass block and fallback TTS for reasoning payloads — src/auto-reply/reply/dispatch-from-config.ts:3108
    The block guard now lets Telegram reasoning blocks continue, but the block path still accumulates the text for final-fallback TTS and can also call block TTS when TTS mode is all. Keep isReasoning payloads out of both TTS paths before delivery.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.88

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P1: The PR targets a production Telegram /reasoning on message-loss workflow and still has merge-blocking delivery and proof concerns.
  • merge-risk: 🚨 message-delivery: Merging as-is can change Telegram Thinking delivery by adding unintended TTS audio/media or duplicate visible behavior around reasoning payloads.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The PR body supplies source tracing and grep output but explicitly says no live Telegram session with a reasoning model was tested, so real behavior proof is still needed before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • mantis: telegram-visible-proof: Mantis should capture Telegram visible proof. The PR changes visible Telegram chat behavior for /reasoning on, which is suitable for a short Telegram Desktop proof recording.
Evidence reviewed

PR surface:

Source +9, Tests +42. Total +51 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 2 17 8 +9
Tests 1 42 0 +42
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 3 59 8 +51

What I checked:

Likely related people:

  • vincentkoc: Current blame maps the shared suppression, Telegram normalization, and outbound suppression paths to Vincent Koc in this checkout, and the maintainer-labeled overlapping candidate is authored by the same handle. (role: recent central dispatch and Telegram reasoning contributor; confidence: high; commits: f9cf00c3512a, 5369ea53bee3, 4954d025e21e; files: src/auto-reply/reply/dispatch-from-config.ts, extensions/telegram/src/bot-message-dispatch.ts, src/infra/outbound/payloads.ts)
  • obviyus: Path history shows Ayaan Zaidi commits in the Telegram dispatcher around progress and visible delivery behavior that shares the reasoning lane boundary. (role: recent Telegram delivery contributor; confidence: medium; commits: 5aad79571ee6; files: extensions/telegram/src/bot-message-dispatch.ts)
  • steipete: Search history for the outbound reasoning suppression path includes Peter Steinberger's earlier suppression-guard refactor, making this a useful adjacent routing candidate for shared dispatch behavior. (role: shared reply/outbound adjacent contributor; confidence: medium; commits: 5c6b2cbc8eb5; files: src/infra/outbound/payloads.ts, src/auto-reply/reply/reply-payloads-base.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: 🧂 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. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jun 19, 2026
…dicated reasoning lanes

The shared dispatch-from-config path was unconditionally suppressing
isReasoning payloads at two points (onBlockReply and final reply loop),
preventing Telegram, Discord, Slack, and MSTeams from receiving
durable reasoning messages under /reasoning on.

- onBlockReply callback (L3107): suppress only for channels without
  dedicated reasoning display
- Final reply loop (L3279): same channel-aware suppression
- Added tests for Telegram receiving isReasoning block and final replies

Fixes openclaw#94937.
@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. labels Jun 20, 2026
@sunlit-deng

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 20, 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.

@sunlit-deng

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram mantis: telegram-visible-proof Mantis should capture Telegram visible proof. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P1 High-priority user-facing bug, regression, or broken workflow. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. 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.

/reasoning on drops the thinking lane on Telegram — renders under /reasoning stream, lost under on

1 participant