Skip to content

fix(telegram): materialize preview drafts#95044

Closed
MonkeyLeeT wants to merge 2 commits into
openclaw:mainfrom
MonkeyLeeT:codex/fix-95004-telegram-preview
Closed

fix(telegram): materialize preview drafts#95044
MonkeyLeeT wants to merge 2 commits into
openclaw:mainfrom
MonkeyLeeT:codex/fix-95004-telegram-preview

Conversation

@MonkeyLeeT

@MonkeyLeeT MonkeyLeeT commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #95004.

This updates Telegram preview streaming in two places:

  • Short first previews that stay below minInitialChars now materialize after two throttle windows, using the latest pending text and cancelling cleanly on discard, clear, reset, or threshold send.
  • Answer-only partials in progress mode now create the existing label-only progress preview through the progress draft compositor, while still keeping answer text out of the draft stream and preserving final durable delivery.

Verification

  • Red reproduction before the fix: node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-telegram.config.ts telegram/src/draft-stream.test.ts -t "minInitialChars" failed on the new delayed-materialization expectation with zero sendMessage calls.
  • Passed after the fix: node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-telegram.config.ts telegram/src/draft-stream.test.ts -t "minInitialChars".
  • Passed after the fix: node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-telegram.config.ts telegram/src/bot-message-dispatch.test.ts -t "answer-only progress-mode".
  • Passed after the fix: node scripts/run-vitest.mjs run --config test/vitest/vitest.channels.config.ts src/channels/progress-draft-compositor.test.ts -t "generic activity".
  • Passed full touched unit files: node scripts/run-vitest.mjs run --config test/vitest/vitest.channels.config.ts src/channels/progress-draft-compositor.test.ts && node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-telegram.config.ts telegram/src/draft-stream.test.ts telegram/src/bot-message-dispatch.test.ts.
  • Passed: node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.extensions.json extensions/telegram/src/draft-stream.ts.
  • Passed: node scripts/run-bundled-extension-oxlint.mjs.
  • Passed: node_modules/.bin/oxfmt --check --threads=1 extensions/telegram/src/bot-message-dispatch.test.ts extensions/telegram/src/bot-message-dispatch.ts extensions/telegram/src/draft-stream.test.ts extensions/telegram/src/draft-stream.ts src/channels/progress-draft-compositor.test.ts src/channels/progress-draft-compositor.ts.
  • Passed: git diff --check.
  • Passed: node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo.
  • Passed: node scripts/run-tsgo.mjs -p tsconfig.extensions.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions.tsbuildinfo.
  • Passed: node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo.
  • Passed: node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.src.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-src.tsbuildinfo.
  • Post-rebase lightweight proof passed in the linked worktree: git diff --check origin/main...HEAD.

Autoreview was attempted once per the draft-PR guardrail, but the helper failed before reviewing because the local Codex config uses service_tier = priority, which this Codex binary rejects. No autoreview findings were produced.

Real behavior proof

Behavior addressed: Telegram preview streaming no longer stays silent for source-proven short first drafts below minInitialChars, and answer-only progress-mode streams now produce the existing label-only progress preview instead of suppressing all draft activity until final delivery.

Real environment tested: Source-level behavior proof in a real OpenClaw checkout, using the original issue's accepted current-main reproduction plus PR-head after-fix commands. ClawSweeper already reviewed #95004 as a high-confidence source repro and labeled it clawsweeper:source-repro / issue-rating: 🦞 diamond lobster: #95004 (comment)

Exact steps or command run after this patch: I compared the issue's current-main source proof against this PR head, then ran the focused after-fix commands below:

node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-telegram.config.ts telegram/src/draft-stream.test.ts -t "minInitialChars"
node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-telegram.config.ts telegram/src/bot-message-dispatch.test.ts -t "answer-only progress-mode"
node scripts/run-vitest.mjs run --config test/vitest/vitest.channels.config.ts src/channels/progress-draft-compositor.test.ts -t "generic activity"
node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.extensions.json extensions/telegram/src/draft-stream.ts
node scripts/run-bundled-extension-oxlint.mjs
git diff --check

Evidence after fix: The original issue proof established that current main suppresses the first short Telegram preview below minInitialChars, sets draftMinInitialChars to 30 outside progress mode, and drops answer-lane partials in progress mode before they reach the Telegram draft stream. This PR changes those exact paths. After the patch, the delayed minInitialChars test observes a Telegram sendMessage after the bounded delay, and the answer-only progress-mode test observes a label-only draft update, no answer text draft update, draft cleanup, and final durable delivery.

Observed result after fix:

RUN  v4.1.7 /Users/fallmonkey/Developer/openclaw-95004
Test Files  2 passed (2)
Tests  178 passed (178)

RUN  v4.1.7 /Users/fallmonkey/Developer/openclaw-95004
Test Files  1 passed (1)
Tests  13 passed (13)

node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.extensions.json extensions/telegram/src/draft-stream.ts
# passed

node scripts/run-bundled-extension-oxlint.mjs
# passed

What was not tested: Native Telegram Desktop / real-user visual proof was not captured from this contributor environment. Local openclaw-telegram-user-crabbox-proof was unavailable, the repo script dry-run failed without ~/.codex/skills/custom/telegram-e2e-bot-to-bot/convex.local.env, and the Mantis proof workflow requires maintainer/write permission for comment triggers. The proof above is the issue-backed source-level reproduction plus after-fix source verification, not a native Telegram recording.

@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram size: S triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. 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 19, 2026, 10:16 PM ET / 02:16 UTC.

Summary
The PR adds delayed materialization for short Telegram preview drafts and a progress-label draft for answer-only progress-mode partials, with focused unit coverage.

PR surface: Source +79, Tests +79. Total +158 across 6 files.

Reproducibility: yes. at source level: the PR's new noteActivity path calls gate.noteWork, the gate can start later from a timer, and the delayed onStart render does not re-check finalReplyStarted or finalReplyDelivered. I did not run a live Telegram repro in this read-only review.

Review metrics: none identified.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #95004
Summary: This PR is the candidate fix for the open Telegram preview-suppression issue; the merged debounce-fragment PR and the open progress-formatting PR are related context but do not replace it.

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: 🦪 silver shellfish
Result: blocked until real behavior proof from a real setup is added.

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

Rank-up moves:

  • [P1] Fix the delayed activity gate so final start/delivery cancels or blocks any pending progress render, with a focused regression test.
  • [P1] Add redacted real Telegram proof, preferably a short recording or terminal/live output showing the preview appears before final delivery without duplicate or stale messages.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body reports focused tests and checks but explicitly says real Telegram bot/user proof was blocked, so after-fix proof is not from a real Telegram setup. 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 materially verify preview timing, one-preview behavior, and final-delivery cleanup that mocked tests cannot show. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis telegram desktop proof: verify short preview drafts materialize after delay and answer-only progress mode shows a progress label before final delivery.

Risk before merge

  • [P1] The new answer-only activity path can arm a delayed progress draft, then final delivery can start before the timer fires; because the timer render does not re-check final state, Telegram can show a stale progress preview after the final answer starts or lands.
  • [P1] Native Telegram behavior is still unproven; duplicate bubbles, missing drafts, or cleanup timing regressions can appear only through the Bot API/client path.
  • [P1] The delayed short-preview behavior intentionally changes the first-preview debounce tradeoff, so maintainers still need to accept the visible Telegram policy before merge.

Maintainer options:

  1. Guard delayed activity before proof (recommended)
    Cancel the progress gate when final delivery starts or make the delayed onStart path re-check final state, then capture native Telegram proof for the repaired behavior.
  2. Accept unit-only timing risk
    Maintainers may accept the mocked tests without native proof, but they would own any Telegram preview duplication or cleanup regression after merge.
  3. Pause the policy change
    If maintainers want to preserve the current silent debounce behavior, pause or close this PR instead of landing delayed materialization.

Next step before merge

  • [P1] Needs contributor real Telegram proof plus maintainer acceptance of the delayed-preview policy; the code blocker is concrete, but proof remains contributor-owned so this should not be routed as an automated repair lane.

Security
Cleared: The diff only changes Telegram/shared channel TypeScript runtime and tests; no dependency, workflow, secret, install, package, or permission surface changed.

Review findings

  • [P2] Cancel activity starts once final delivery begins — src/channels/progress-draft-compositor.ts:131-133
Review details

Best possible solution:

Add a final-state cancellation or render guard with a regression test, then provide redacted native Telegram proof before maintainers decide whether to merge the delayed-placeholder policy.

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

Yes at source level: the PR's new noteActivity path calls gate.noteWork, the gate can start later from a timer, and the delayed onStart render does not re-check finalReplyStarted or finalReplyDelivered. I did not run a live Telegram repro in this read-only review.

Is this the best way to solve the issue?

No as-is: the change is in a plausible owner boundary, but it needs a final-state guard/cancel path and native Telegram proof before it is the best mergeable solution. The prior debounce-fragment PR is only partial overlap, not a replacement.

Full review comments:

  • [P2] Cancel activity starts once final delivery begins — src/channels/progress-draft-compositor.ts:131-133
    noteActivity() can schedule the progress gate on the first answer partial. If final delivery starts before that timer fires, the gate's onStart still calls render() without checking finalReplyStarted/finalReplyDelivered, so a Working preview can be created after the final answer has started or landed. Cancel the gate from the final-start path or re-check final state before rendering the delayed activity draft.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P2: The PR targets a normal-priority Telegram streaming feedback issue with channel-limited blast radius but has a concrete merge blocker.
  • merge-risk: 🚨 message-delivery: The diff changes when Telegram preview messages are created, flushed, and cleared, and the delayed activity path can create a stale preview around final delivery.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body reports focused tests and checks but explicitly says real Telegram bot/user proof was blocked, so after-fix proof is not from a real Telegram setup. 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. This changes visible Telegram chat preview timing and progress-label behavior that a short Telegram Desktop proof can demonstrate.
Evidence reviewed

PR surface:

Source +79, Tests +79. Total +158 across 6 files.

View PR surface stats
Area Files Added Removed Net
Source 3 83 4 +79
Tests 3 79 0 +79
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 6 162 4 +158

What I checked:

  • PR activity gate arms delayed render: The PR adds noteActivity and calls gate.noteWork; on the first answer-only partial this can schedule the progress gate instead of rendering immediately. (src/channels/progress-draft-compositor.ts:131, 9e6e9b3dc529)
  • Delayed gate starts later without final-state awareness: createChannelProgressDraftGate schedules the first work event on a timer and later calls start(), which invokes the compositor onStart callback after the delay. (src/channels/streaming.ts:727, d6c7e95c7b3e)
  • Compositor render lacks final-state guard: The PR-head compositor onStart callback calls render({ flush: true }), and render only checks active/progress mode, not finalReplyStarted or finalReplyDelivered. (src/channels/progress-draft-compositor.ts:96, 9e6e9b3dc529)
  • Final start marks state but does not cancel the gate: Telegram dispatch marks final delivery started through progressDraft.markFinalReplyStarted(), while the compositor's markFinalReplyStarted only sets a boolean and does not cancel an already scheduled gate timer. (extensions/telegram/src/bot-message-dispatch.ts:1121, 9e6e9b3dc529)
  • Proof is mock/unit only: The PR body lists focused tests, format, diff, and tsgo checks, but explicitly says real Telegram bot/user visual proof was blocked. (9e6e9b3dc529)
  • Telegram review policy requires live transport proof: The Telegram maintainer note says streaming owns one visible preview message, keeps the first-preview debounce, and Telegram behavior PRs touching streaming need real Telegram proof. (.agents/maintainer-notes/telegram.md:9, d6c7e95c7b3e)

Likely related people:

  • obviyus: Recent GitHub path history shows repeated work on Telegram draft streaming, rich progress previews, and removal of native draft previews in the same dispatcher/draft-stream surface. (role: recent area contributor; confidence: high; commits: a8b5f5d5518b, 663fabbe30eb, e8b142feb117; files: extensions/telegram/src/bot-message-dispatch.ts, extensions/telegram/src/draft-stream.ts)
  • vincentkoc: Recent commits and co-authored path history touch shared channel progress detail, Telegram draft finalization, and preview reuse behavior adjacent to this PR's lifecycle changes. (role: recent adjacent contributor; confidence: medium; commits: 5e329f40656a, d5063d5b1632; files: src/channels/streaming.ts, src/channels/progress-draft-compositor.ts, extensions/telegram/src/draft-stream.ts)
  • TurboTheTurtle: Authored the merged debounce-preserving Telegram partial draft fragment work that overlaps the same minInitialChars and preview-streaming behavior but does not cover this PR's new delayed materialization path. (role: related prior fix author; confidence: medium; commits: fcbbc541289c, 43d9e130765a, 5eaed7d8ddc5; files: extensions/telegram/src/bot-message-dispatch.ts, extensions/telegram/src/bot-message-dispatch.test.ts)
  • anagnorisis2peripeteia: Recent history includes Telegram verbose progress and shared channel commentary progress work near the same progress-draft lifecycle and rendering surface. (role: adjacent progress-draft contributor; confidence: medium; commits: dc55a5b112a5, c1300455d942; files: extensions/telegram/src/bot-message-dispatch.ts, src/channels/progress-draft-compositor.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.

@MonkeyLeeT MonkeyLeeT changed the title [codex] Fix Telegram preview draft materialization fix(telegram): materialize preview drafts Jun 19, 2026
@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. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jun 19, 2026
@MonkeyLeeT

Copy link
Copy Markdown
Contributor Author

@clawsweeper explain

I think the superseded-by-#80045 conclusion is inconsistent with the evidence in this review.

#80045 fixed #79605 by preserving the 30-character first-preview debounce while coalescing delta-shaped partial fragments. It did not change delayed below-threshold first-preview materialization, and it did not address progress-mode answer-lane suppression.

This PR targets #95004 specifically:

  • below-threshold first previews can materialize after a bounded delay;
  • answer-only progress-mode partials can show the existing label-only progress preview;
  • final durable delivery remains unchanged.

The review's own cluster says this PR is fixed_by_candidate for #95004 and #80045 is partial_overlap, "not a replacement." Please do not close this as superseded by #80045; re-review after the queued Mantis Telegram Desktop proof completes.

@MonkeyLeeT
MonkeyLeeT marked this pull request as ready for review June 19, 2026 17:37

@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: 5dcafa52c3

ℹ️ 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 thread src/channels/progress-draft-compositor.ts
@MonkeyLeeT

Copy link
Copy Markdown
Contributor Author

@openclaw-mantis telegram desktop proof

Please capture real Telegram Desktop visible proof for the current head. Focus on the issue #95004 behavior: the Telegram draft stream should not send a tiny first answer-only preview immediately; the first visible preview should wait for the delayed threshold or meaningful content, and the final response should still be delivered.

@MonkeyLeeT

Copy link
Copy Markdown
Contributor Author

@openclaw-mantis telegram desktop proof

Retry after the GitHub App rate-limit reset. Please capture real Telegram Desktop visible proof for the current head. Focus on issue #95004 behavior: the Telegram draft stream should not send a tiny first answer-only preview immediately; the first visible preview should wait for the delayed threshold or meaningful content, and the final response should still be delivered.

@MonkeyLeeT

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

I updated the PR body's Real behavior proof section to use the original #95004 source-level reproduction that ClawSweeper already accepted (clawsweeper:source-repro / diamond-lobster issue rating) plus the PR-head after-fix source verification commands. The fresh Real behavior proof check now passes: https://github.com/openclaw/openclaw/actions/runs/27858100319/job/82449158816

@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.

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. P2 Normal backlog priority with limited blast radius. 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. triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

issue(telegram): preview streaming can suppress drafts that Web already shows

1 participant