Skip to content

fix(agents): suppress commentary-phase output leaks#61282

Merged
mbelinky merged 4 commits into
mainfrom
fix/commentary-phase-output-leak
Apr 5, 2026
Merged

fix(agents): suppress commentary-phase output leaks#61282
mbelinky merged 4 commits into
mainfrom
fix/commentary-phase-output-leak

Conversation

@mbelinky

@mbelinky mbelinky commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: assistant messages carrying phase:"commentary" were already being preserved by the OpenAI Responses conversion path, but the embedded subscribe delivery bridge still treated them like normal user-visible assistant output.
  • Why it matters: internal planning shards like Need send... or Need update tracker... could leak into Telegram partials and final reply paths before the real answer.
  • What changed: suppress commentary-phase assistant output at the shared embedded subscribe boundary, whether the phase arrives as message.phase or only inside textSignature metadata.
  • Hardening: commentary text_* updates now bail out before mutating visible-output buffers, partial-reply state, or block-reply flush paths.

Root Cause

  • Root cause: src/agents/pi-embedded-subscribe.handlers.messages.ts ignored assistant delivery phase when deciding what to stream or flush to the user.
  • Existing evidence in code: phase metadata is already preserved upstream, including the textSignature-only shape covered by src/agents/openai-ws-stream.test.ts.
  • Failure mode: commentary text could enter onPartialReply, block-reply flush, or final assistant text emission even though it was internal-only output.

Why This Layer

  • This is the correct production boundary for OpenClaw because it controls the actual user-visible delivery paths.
  • A Pi-side render/print fix is still reasonable upstream hygiene, but it does not replace fixing the OpenClaw delivery bridge that Telegram and other embedded surfaces actually use here.
  • Fixing only Telegram lane wiring would be too narrow; the bug is broader than one preview transport.

Red-Team / Hardening Review

  • Checked whether the fix only covered message.phase: it did not originally, so this PR explicitly covers the textSignature-only commentary shape too.
  • Checked whether commentary still polluted internal visible-output state even when suppressed: it did originally, so this PR now returns early before mutating partial/block buffers on commentary text_* updates.
  • Checked whether the change accidentally suppresses legitimate final answers: suppression is limited to phase:"commentary"; final_answer and normal assistant messages still flow unchanged.
  • Checked whether this belongs in a refactor instead: no. The minimal root-cause fix is small and local; broader dedupe with other phase helpers can wait.

Change Type

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

User-visible / Behavior Changes

  • Commentary-phase planning text no longer leaks into user-visible assistant partials or final replies.
  • This applies both to direct message.phase commentary and to replay/live shapes that only carry the phase in textSignature metadata.

Tests

Targeted serial verification on mb-air:

bunx vitest run \
  src/agents/pi-embedded-subscribe.handlers.messages.test.ts \
  src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.suppresses-commentary-phase-output.test.ts \
  src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.test.ts \
  --pool forks --maxWorkers 1

Result: 3 files, 38 tests passed.

AI / Testing Notes

  • AI-assisted: yes
  • Testing: targeted local serial tests passed

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: M maintainer Maintainer-authored PR labels Apr 5, 2026
@greptile-apps

greptile-apps Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes commentary-phase assistant output leaking into user-visible delivery paths (onPartialReply, block-reply flush, Telegram partials) by adding shouldSuppressAssistantVisibleOutput at the shared embedded subscribe boundary and returning early before any visible-output buffer is mutated. Both the direct message.phase shape and the textSignature-only metadata shape are covered, buffer state is properly cleared via finalizeMessageEnd on the early path, and the new tests cover all affected paths end-to-end.

Confidence Score: 5/5

Safe to merge; the fix is minimal, well-targeted, and comprehensively tested.

The only remaining finding is a P2 observation: handleMessageStart fires the typing-indicator callback unconditionally for commentary messages, causing a spurious typing flash. Teardown is unconditional so there is no stuck-indicator risk. No P0 or P1 issues were found. The suppression logic is correct for both delivery shapes, buffer cleanup is correct, and the test suite covers all affected code paths.

No files require special attention.

Comments Outside Diff (1)

  1. src/agents/pi-embedded-subscribe.handlers.messages.ts, line 214-231 (link)

    P2 handleMessageStart fires typing signal for commentary messages

    onAssistantMessageStart is called unconditionally for all non-transcript-only assistant messages (line 230), including commentary-phase ones. In production this triggers typingSignals.signalMessageStart(), producing a brief typing-indicator flash before the run completes and the finally-block cleanup tears it down. No stuck-indicator risk exists, but a guard here would prevent the spurious flash:

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/agents/pi-embedded-subscribe.handlers.messages.ts
    Line: 214-231
    
    Comment:
    **`handleMessageStart` fires typing signal for commentary messages**
    
    `onAssistantMessageStart` is called unconditionally for all non-transcript-only assistant messages (line 230), including commentary-phase ones. In production this triggers `typingSignals.signalMessageStart()`, producing a brief typing-indicator flash before the run completes and the `finally`-block cleanup tears it down. No stuck-indicator risk exists, but a guard here would prevent the spurious flash:
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-subscribe.handlers.messages.ts
Line: 214-231

Comment:
**`handleMessageStart` fires typing signal for commentary messages**

`onAssistantMessageStart` is called unconditionally for all non-transcript-only assistant messages (line 230), including commentary-phase ones. In production this triggers `typingSignals.signalMessageStart()`, producing a brief typing-indicator flash before the run completes and the `finally`-block cleanup tears it down. No stuck-indicator risk exists, but a guard here would prevent the spurious flash:

```suggestion
  if (msg?.role !== "assistant" || isTranscriptOnlyOpenClawAssistantMessage(msg)) {
    return;
  }
  if (shouldSuppressAssistantVisibleOutput(msg)) {
    // Reset state for accurate baseline tracking, but skip the typing signal —
    // commentary-phase messages produce no visible output.
    ctx.resetAssistantMessageState(ctx.state.assistantTexts.length);
    return;
  }

  // KNOWN: Resetting at `text_end` is unsafe (late/duplicate end events).
  // ASSUME: `message_start` is the only reliable boundary for "new assistant message begins".
  // Start-of-message is a safer reset point than message_end: some providers
  // may deliver late text_end updates after message_end, which would otherwise
  // re-trigger block replies.
  ctx.resetAssistantMessageState(ctx.state.assistantTexts.length);
  // Use assistant message_start as the earliest "writing" signal for typing.
  void ctx.params.onAssistantMessageStart?.();
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(agents): suppress commentary-phase o..." | Re-trigger Greptile

@mbelinky mbelinky force-pushed the fix/commentary-phase-output-leak branch from 5f72beb to b3f1093 Compare April 5, 2026 11:00
@mbelinky mbelinky force-pushed the fix/commentary-phase-output-leak branch from b3f1093 to e392904 Compare April 5, 2026 11:03
@mbelinky mbelinky merged commit 4175cae into main Apr 5, 2026
9 checks passed
@mbelinky mbelinky deleted the fix/commentary-phase-output-leak branch April 5, 2026 11:04
@mbelinky

mbelinky commented Apr 5, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

Thanks @mbelinky!

lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
Merged via squash.

Prepared head SHA: e392904
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
Merged via squash.

Prepared head SHA: e392904
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Merged via squash.

Prepared head SHA: e392904
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
Merged via squash.

Prepared head SHA: e392904
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling maintainer Maintainer-authored PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant