Skip to content

fix(buzz): keep implicit replies at thread root - #138879

Merged
steipete merged 2 commits into
openclaw:mainfrom
sunlit-deng:sunlit/fix/issue-138812
Sep 5, 2026
Merged

steipete merged 2 commits into
openclaw:mainfrom
sunlit-deng:sunlit/fix/issue-138812

Conversation

@sunlit-deng

@sunlit-deng sunlit-deng commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes Buzz implicit replies that nest under the triggering child message instead of staying at the thread root. Fixes #138812.

Why This Change Was Made

The shared message-action path already supplies the thread root and whether the reply target was explicit. The Buzz plugin now uses that existing threading hook to normalize implicit replies to the root. Explicit child replies keep their nesting, and automatic off-mode replies retain their top-level behavior. The encoder and generic routing policy are unchanged.

The maintainer refinement removes a redundant unequal-ID check, replaces a stale comment, and makes the regression table explicitly cover message-tool calls without replyDelivery metadata. The original contributor commits remain in the ancestry.

User Impact

Implicit Buzz replies remain in the active thread. Explicit child replies and top-level sends continue to work.

Evidence

The independent hosted proof exercised production runMessageAction, the Buzz adapter, and an authenticated signed local WebSocket relay. The baseline emitted both root and child-reply tags for an implicit reply; the candidate emitted only the root reply tag. Explicit-child, explicit-root, off-mode, and top-level controls passed. All 51 focused channel, inbound, and bus tests passed. The executed production file matches the published candidate byte-for-byte. The parent proof run is red because the separate Feishu lane referenced a stale test filename; the Buzz job passed.

This is synthetic relay transport proof, not a hosted Buzz service or native-client recording. The existing reporter reproduction supplies the client symptom. Direct inspection of Buzz's threading implementation confirms its root/child tag contract.

Fresh independent Codex review through P2 found no actionable defects. Production +9/-3 (net +6), tests +34/-16 (net +18). The small production addition is the missing plugin-owned default-routing decision; putting it in the encoder would flatten explicit child replies, and putting it in core would impose Buzz policy on other channels. Exact published-head CI passed.

Thanks @sunlit-deng for the original fix and reproduction.

@clawsweeper

clawsweeper Bot commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P1 High-priority user-facing bug, regression, or broken workflow. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 5, 2026
@clawsweeper

clawsweeper Bot commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed September 5, 2026, 1:45 PM ET / 17:45 UTC.

ClawSweeper review

What this changes

The Buzz plugin anchors implicit replies to the thread root, preserves explicitly requested child replies, and expands routing regression coverage.

Merge readiness

✅ Ready for maintainer review

This remains necessary: current main and v2026.9.1 still have the message-tool routing gap. The earlier merged fix covers automatic delivery; no blocking defects were found in this patch.

Priority: P1
Reviewed head: c8980753f41f4059a0cfd45dd9a5066af3ce1f68

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) A focused owner-boundary repair with useful regression coverage and reported authenticated transport proof.
Proof confidence 🐚 platinum hermit (4/6) ✨ media proof bonus Sufficient (linked_artifact): The captured report describes production message-action and Buzz transport execution over an authenticated local relay, with corrected implicit-parent tags and passing explicit/off/top-level controls. This satisfies the changed transport behavior; linked logs were inaccessible to this worker, and no native-client recording is claimed.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (linked_artifact): The captured report describes production message-action and Buzz transport execution over an authenticated local relay, with corrected implicit-parent tags and passing explicit/off/top-level controls. This satisfies the changed transport behavior; linked logs were inaccessible to this worker, and no native-client recording is claimed.
Evidence reviewed 11 items Verified introduced change: The pinned merge-base-to-head diff contains only the Buzz routing hook and its regression table. It preserves off-mode clearing and explicit reply targets; unrelated endpoint drift is not attributed to this PR.
Current main still needs the repair: Current main’s Buzz hook only handles replyToMode off; it does not canonicalize implicit child replies.
Latest release has the same gap: The v2026.9.1 source contains the same off-only hook. The release tag resolves to ad6fe23.
Findings None None.
Security None None.

How this fits together

OpenClaw’s message tool supplies the conversation thread and reply intent to the Buzz plugin. The plugin selects the reply parent before its transport encodes and publishes the message.

flowchart TD
  A[Message tool send] --> B[Shared reply inheritance]
  B --> C[Buzz reply policy]
  C --> D{Reply intent}
  D -->|Implicit| E[Thread root]
  D -->|Explicit| F[Requested parent]
  E --> G[Encode tags and publish]
  F --> G
Loading

Before merge

None.

Agent review details

Security

None.

PR surface

Source +6, Tests +18. Total +24 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 9 3 +6
Tests 1 34 16 +18
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 43 19 +24

Review metrics

Metric Value Why it matters
Production versus test growth Production net +6; tests net +18 The production growth adds the missing plugin-owned intent decision without a new helper, API, or configuration surface.

Root-cause cluster

Relationship: fixed_by_candidate
Canonical: #138812
Summary: This PR addresses the canonical message-tool report; the merged automatic-delivery repair overlaps but does not supersede it.

Members:

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

Technical review

Best possible solution:

Keep root selection in Buzz’s existing hook, preserving explicit nesting and off mode; the encoder cannot absorb this decision because it lacks explicit-reply intent.

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

Yes: current source shows a threaded message-tool send without explicit replyTo inheriting the triggering child ID, which the existing encoder preserves as its parent. This review did not execute the reproduction.

Is this the best way to solve the issue?

Yes: the existing channel hook receives both root identity and explicit intent, making it the appropriate repair boundary without imposing Buzz policy on other channels.

AGENTS.md: found and applied where relevant.

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

Labels

Label justifications:

  • P1: The linked current-release report shows routine Buzz mobile replies becoming hidden in nested subthreads.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (linked_artifact): The captured report describes production message-action and Buzz transport execution over an authenticated local relay, with corrected implicit-parent tags and passing explicit/off/top-level controls. This satisfies the changed transport behavior; linked logs were inaccessible to this worker, and no native-client recording is claimed.
  • proof: sufficient: Contributor real behavior proof is sufficient. The captured report describes production message-action and Buzz transport execution over an authenticated local relay, with corrected implicit-parent tags and passing explicit/off/top-level controls. This satisfies the changed transport behavior; linked logs were inaccessible to this worker, and no native-client recording is claimed.

Evidence

What I checked:

  • Verified introduced change: The pinned merge-base-to-head diff contains only the Buzz routing hook and its regression table. It preserves off-mode clearing and explicit reply targets; unrelated endpoint drift is not attributed to this PR. (extensions/buzz/src/channel.ts:74, c8980753f41f)
  • Current main still needs the repair: Current main’s Buzz hook only handles replyToMode off; it does not canonicalize implicit child replies. (extensions/buzz/src/channel.ts:75, 3e4becea5e2c)
  • Latest release has the same gap: The v2026.9.1 source contains the same off-only hook. The release tag resolves to ad6fe23. (extensions/buzz/src/channel.ts:75, ad6fe23aecb9)
  • Existing shared normalization boundary: Current main inherits the triggering message for same-conversation implicit replies and invokes the selected channel’s existing hook when both reply and thread IDs exist. Top-level opt-outs bypass inheritance. (src/infra/outbound/message-action-threading.ts:58, 3e4becea5e2c)
  • Caller preserves explicit intent: The send owner passes initialReply.source into replyToIsExplicit and carries the canonicalized reply ID into delivery. This uses an existing API and adds no parallel routing path. (src/infra/outbound/message-action-send.ts:423, c8980753f41f)
  • Encoder and dependency boundary: buildBuzzMessageTags emits separate root and parent tags only when those IDs differ. BuzzBus publishes those tags through both connected and one-shot sends. These Buzz tag semantics establish the relevant dependency signal; no Codex runtime or protocol contract is involved. (extensions/buzz/src/message-event.ts:260, c8980753f41f)

Likely related people:

  • steipete: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • LeahArmstrong: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
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.

Workflow

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

History

Review history (3 earlier review cycles)
  • reviewed 2026-09-05T05:38:07.328Z sha c9915c1 :: needs real behavior proof before merge. :: none
  • reviewed 2026-09-05T06:45:58.318Z sha c9915c1 :: needs real behavior proof before merge. :: none
  • reviewed 2026-09-05T13:06:32.166Z sha c9915c1 :: needs maintainer review before merge. :: none

@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: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 5, 2026
Simplify the shared channel hook and cover implicit message-tool routing without replyDelivery metadata. Preserve explicit child replies and top-level controls.

Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com>
@steipete
steipete merged commit e4b42c7 into openclaw:main Sep 5, 2026
108 checks passed
@steipete

steipete commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

vincentkoc added a commit that referenced this pull request Sep 5, 2026
* commit '911d7d5b0c107f7274f2415ca9655dcc6105f0e8': (867 commits)
  fix(skills): deliver pending Workshop approval controls (#139248)
  fix(gateway): deliver loopback ask_user prompts to the originating channel (#138831)
  docs: keep root agent instructions focused on repository policy (#139258)
  fix(matrix): exclude archived state roots from scans and selection (#112329)
  perf(agents): prepare exact tool names once per catalog batch (#139267)
  fix: preserve Swarm progress and simplify owner plumbing (#139269)
  fix(tailscale): release claims after gateway process-group exit (#139261)
  refactor(cli): simplify lazy command registration (#139108)
  test(ui): retain synthetic widget failure evidence (#139229)
  fix(buzz): keep implicit replies at thread root (#138879)
  test(diagnostics): await graceful Gateway shutdown before cleanup (#139247)
  fix(ci): unblock releases with different tooling package managers (#139259)
  feat(ui): add social preview links for private sessions (#139250)
  fix(codex): retain failed conversations for guarded continuation (#139246)
  chore(ui): refresh control ui locales (#139200)
  fix(ci): run browser checks for real-gateway inputs (#139256)
  fix(llama-cpp): reconcile managed router state before requests (#136363)
  chore(i18n): refresh native locales (#139237)
  refactor(worker): unify inference payload handling (#139245)
  refactor(terminal): replay wrapped prefixes in one pass (#139240)
  ...
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Sep 6, 2026
* fix(buzz): keep implicit replies at thread root

* fix(buzz): keep implicit replies at their thread root

Simplify the shared channel hook and cover implicit message-tool routing without replyDelivery metadata. Preserve explicit child replies and top-level controls.

Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: buzz 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: S 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.

buzz: message-tool replies inside a thread are parented to the triggering message, so Buzz mobile renders every bot reply as a nested sub-thread

2 participants