Suppress heartbeat fallback after message-tool delivery#84273
Suppress heartbeat fallback after message-tool delivery#84273TurboTheTurtle wants to merge 4 commits into
Conversation
|
Codex review: needs real behavior proof before merge. Workflow note: Future ClawSweeper reviews update this same comment in place. How this review workflow works
Summary Reproducibility: yes. from source inspection, but not by a live run in this read-only review. Current main allows a generic message-tool send plus free text to leave heartbeatToolResponse undefined and then deliver the free-text fallback through sendDurableMessageBatch. PR rating Rank-up moves:
What the crustacean ranks mean
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. PR egg Where did the egg go?
Real behavior proof Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge Security Review findings
Review detailsBest possible solution: Keep the metadata-based suppression, but only set the delivery marker when the message-tool send matches the heartbeat/source route or target details are unavailable under the existing dedupe fallback, then prove the result with live Telegram-visible evidence or an explicit maintainer proof override. Do we have a high-confidence way to reproduce the issue? Yes from source inspection, but not by a live run in this read-only review. Current main allows a generic message-tool send plus free text to leave heartbeatToolResponse undefined and then deliver the free-text fallback through sendDurableMessageBatch. Is this the best way to solve the issue? Mostly yes, but the marker needs route scoping. The maintainable shape is to carry internal delivery evidence from runReplyAgent to runHeartbeatOnce, while preserving the existing provider/target/account/thread matching boundary already used for message-tool dedupe. Label justifications:
Full review comments:
Overall correctness: patch is incorrect Acceptance criteria:
What I checked:
Likely related people:
Codex review notes: model gpt-5.5, reasoning high; reviewed against a059309a9f9a. |
|
Pushed follow-up commit What changed:
Validation:
Author attribution verified before push: @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Pushed a follow-up fix for the failed Local validation:
@clawsweeper re-review |
|
One remaining current-head failure appears unrelated to this branch: |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Closing this out to keep the open PR queue focused. This one is still marked as needing stronger proof and carries message-delivery risk, and I cannot provide the required live/equivalent proof from the contributor side. Happy to reopen or re-spin if maintainers want this direction later. |
Summary
Fixes #84217.
Root cause
Heartbeat dispatch only understood the
heartbeat_respondtool channel data. When non-Codex providers produced a genericmessagetool call and also returned visible fallback text,runHeartbeatOncetreated the fallback text as a normal heartbeat reply and sent it to Telegram.Real behavior proof
Behavior or issue addressed:
Heartbeat message-tool-only dispatch no longer sends fallback text when a visible generic message tool send has already succeeded.
Real environment tested:
Local OpenClaw source checkout with production
runHeartbeatOnce, production reply payload metadata helpers, and a real temporary session store on macOS. The proof used an in-memory Telegram sender so the dispatch path could be observed without contacting Telegram.Exact steps or command run after this patch:
PATH=/Users/andy/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin:$PATH node --import tsx --input-type=module --eval '<script importing runHeartbeatOnce, seeding a temp session store, returning markReplyPayloadForMessageToolDelivery({ text: "fallback narration that would duplicate the message tool" }) from getReplyFromConfig, and recording Telegram send calls>'Evidence after fix:
{ "result": { "status": "ran" }, "replyCalls": [ { "sourceReplyDeliveryMode": "message_tool_only", "enableHeartbeatTool": true, "forceHeartbeatTool": true } ], "telegramSendCallCount": 0, "heartbeatEvent": { "status": "sent", "preview": "fallback narration that would duplicate the message tool", "channel": "telegram" } }Observed result after fix:
The heartbeat run still uses message-tool-only mode, records a successful heartbeat event, and does not call the Telegram fallback sender for the duplicate narration.
What was not tested:
No live Telegram API call was made; the proof observes the production heartbeat dispatch decision before network delivery.
Validation
node scripts/run-vitest.mjs src/infra/heartbeat-runner.tool-response.test.tsnode scripts/run-vitest.mjs src/auto-reply/reply/agent-runner-payloads.test.ts src/auto-reply/reply/dispatch-from-config.test.tsgit diff --checkAttribution
If maintainers squash or rework this PR, please preserve author attribution or include:
Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>