openclaw - ✅(Solved) Fix [Bug]: Commentary-phase text leaks into user-visible output with openai-codex/gpt-5.4 [5 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#61734Fetched 2026-04-08 02:55:14
View on GitHub
Comments
1
Participants
2
Timeline
11
Reactions
0
Timeline (top)
cross-referenced ×6labeled ×2closed ×1commented ×1

Title

Commentary-phase text leaks into user-visible output with openai-codex/gpt-5.4

Summary

When using OpenClaw with openai-codex/gpt-5.4, internal commentary text is leaking into normal user-visible output in Telegram

Examples:

  • Need fix line quoting properly.
  • Need simpler use cat overwrite full file.
  • Need verify healthy.

This appears to be internal tool-work narration, not intended user-facing content.

Evidence

Session history shows these leaked messages are explicitly marked:

"phase":"commentary"

Normal replies in the same session are marked:

"phase":"final_answer"

This makes it look like a filtering/rendering bug rather than normal model behavior.

Suggested fix

Suppress or filter assistant content where:

textSignature.phase == "commentary"

Only user-facing phases like final_answer should be rendered in normal chat/session views.

Root Cause

Title

Commentary-phase text leaks into user-visible output with openai-codex/gpt-5.4

Summary

When using OpenClaw with openai-codex/gpt-5.4, internal commentary text is leaking into normal user-visible output in Telegram

Examples:

  • Need fix line quoting properly.
  • Need simpler use cat overwrite full file.
  • Need verify healthy.

This appears to be internal tool-work narration, not intended user-facing content.

Evidence

Session history shows these leaked messages are explicitly marked:

"phase":"commentary"

Normal replies in the same session are marked:

"phase":"final_answer"

This makes it look like a filtering/rendering bug rather than normal model behavior.

Suggested fix

Suppress or filter assistant content where:

textSignature.phase == "commentary"

Only user-facing phases like final_answer should be rendered in normal chat/session views.

Fix Action

Fixed

PR fix notes

PR #61747: fix(agents): suppress commentary leaks in history-based replies

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: history-based assistant reply readers could still leak commentary text even after chat.history became phase-aware, because older helper extractors re-flattened mixed-phase assistant messages downstream.
  • Why it matters: user-facing follow-up paths such as wait/read flows and subagent completion summaries could surface internal planning text like Need fix... instead of only the intended final answer.
  • What changed: made the shared assistant-text helpers phase-aware, preferring final_answer over commentary, and removed the raw assistant-content fallback in subagent output summarization that could reintroduce suppressed commentary.
  • What did NOT change (scope boundary): this does not change provider streaming semantics, tool-call behavior, transcript storage format, or the existing upstream chat.history sanitization rules.

Change Type (select all)

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

Scope (select all touched areas)

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

Linked Issue/PR

  • Closes #61734
  • Related #59643
  • Related #61282
  • This PR fixes a bug or regression

Root Cause (if applicable)

For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write N/A. If the cause is unclear, write Unknown.

  • Root cause: chat.history already returned phase-aware assistant messages, but src/agents/tools/chat-history-text.ts and src/agents/tools/session-message-text.ts still extracted assistant text phase-blindly, so downstream consumers could rejoin commentary with final_answer or fall back to commentary-only content.
  • Missing detection / guardrail: there was no targeted regression coverage for mixed-phase assistant messages flowing through the history-based reply helpers used by run-wait and subagent announce paths.
  • Contributing context (if known): earlier fixes in this bug family hardened embedded delivery and history sanitization, but these helper seams remained phase-blind.

Regression Test Plan (if applicable)

For bug fixes or regressions, name the smallest reliable test coverage that should catch this. Otherwise write N/A.

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file:
    • src/agents/tools/assistant-phase-text.test.ts
    • src/agents/run-wait.test.ts
  • Scenario the test should lock in:
    • helper extraction prefers final_answer over commentary
    • explicit phased final_answer that sanitizes empty does not fall back to commentary
    • readLatestAssistantReply() returns only the final-answer text from mixed-phase history
  • Why this is the smallest reliable guardrail: the bug lives in shared extraction helpers, so direct helper coverage plus one downstream history-reader seam test catches the regression without needing a full end-to-end provider/channel run.
  • Existing test that already covers this (if any): upstream phase-aware history sanitization tests existed, but they did not cover these downstream helper re-extraction paths.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

List user-visible changes (including defaults/config).
If none, write None.

  • History-based reply reads now suppress commentary planning text when a final_answer block exists.
  • Subagent completion output no longer falls back to raw assistant content that can reintroduce suppressed commentary.
  • No config or default behavior changes outside the mixed-phase assistant-message case.

Diagram (if applicable)

For UI changes or non-trivial logic flows, include a small ASCII diagram reviewers can scan quickly. Otherwise write N/A.

Before:
[mixed commentary + final_answer assistant message]
  -> [phase-aware chat.history]
  -> [phase-blind helper re-extracts text]
  -> [commentary leaks into reply/subagent output]

After:
[mixed commentary + final_answer assistant message]
  -> [phase-aware chat.history]
  -> [phase-aware helper prefers final_answer]
  -> [user sees only final answer]

## Changed files

- `src/agents/run-wait.test.ts` (modified, +57/-0)
- `src/agents/subagent-announce-output.ts` (modified, +1/-11)
- `src/agents/tools/assistant-phase-text.test.ts` (added, +122/-0)
- `src/agents/tools/chat-history-text.ts` (modified, +9/-11)
- `src/agents/tools/session-message-text.ts` (modified, +9/-11)
- `src/auto-reply/reply/commands-subagents-control.runtime.ts` (modified, +1/-1)
- `src/shared/chat-message-content.test.ts` (modified, +24/-0)
- `src/shared/chat-message-content.ts` (modified, +26/-10)


---

# PR #61529: fix(agents): OpenAI WS replay — inherit message-level phase for untagged blocks when siblings have explicit textSignature

- Repository: openclaw/openclaw
- Author: 100yenadmin
- State: closed | merged: True
- Link: https://github.com/openclaw/openclaw/pull/61529

## Description (problem / solution / changelog)

## What this fixes (plain English)
When replaying chat history that mixes phase-tagged and untagged text blocks, untagged blocks lost their phase label — causing internal commentary to leak into visible conversation output. This fix ensures untagged blocks correctly inherit their parent message's phase.

## Technical details
**Root cause:** The `hasExplicitBlockPhase` scan in `openai-ws-message-conversion.ts` was intended to separate legacy unphased content from new phased content, but it overcorrected — it forced `undefined` phase on untagged blocks whenever any sibling block had an explicit `textSignature.phase`.

**Fix:** Remove the `hasExplicitBlockPhase` scan entirely. Untagged blocks now always inherit `assistantMessagePhase` (from `m.phase`). Blocks with an explicit `textSignature.phase` still use their own value.

**Files changed:**
- `src/agents/openai-ws-message-conversion.ts` — remove overcorrective phase scan
- `src/agents/openai-ws-stream.test.ts` — regression test for mixed explicit/untagged blocks; corrected phase-buffering expectation for mid-stream deltas

## Related
- Fixes #61476
- Parent fix: #59643
- Follow-up family: #61463, #61829, #61477, #61478
- Companion PR: #61528

## Test plan
- [x] 94/94 existing tests pass
- [x] Regression test added: mixed explicit/untagged blocks verify phase inheritance
- [x] Phase-buffering test corrected for mid-stream delta timing

## Changed files

- `CHANGELOG.md` (modified, +1/-0)
- `src/agents/openai-ws-message-conversion.ts` (modified, +6/-2)
- `src/agents/openai-ws-stream.test.ts` (modified, +192/-4)


---

# PR #61528: fix(agents): OpenAI WS stream — gate buffered text delta on valid phase value, not just outputItemPhaseById key existence

- Repository: openclaw/openclaw
- Author: 100yenadmin
- State: closed | merged: False
- Link: https://github.com/openclaw/openclaw/pull/61528

## Description (problem / solution / changelog)

## What this fixes (plain English)
The WebSocket streaming code was supposed to hold back text until it knew the phase (commentary vs. visible), but a subtle bug meant it released text as soon as the item was registered — even if the phase was still unknown. This caused internal commentary to leak into user-visible output.

## Technical details
**Root cause:** `outputItemPhaseById.has(event.item_id)` returns `true` even when the stored value is `undefined` (set by an `output_item.added` event before phase metadata arrives). This defeats the buffering protection entirely.

**Fix:** Changed both emission gates (`.delta` and `.done` handlers) from `.has(id)` to `.get(id) !== undefined` so text stays buffered until a valid phase value arrives.

**Files changed:**
- `src/agents/openai-ws-stream.ts` — 2-line gate fix (`.has()` -> `.get() !== undefined`)

## Related
- Fixes #61477
- Parent fix: #59643
- Companion PRs: #61529, #61463, #61478

## Test plan
- [x] 92/92 existing tests pass
- [x] 2-line change, minimal blast radius
- [x] No scope creep — single file, single fix

## Changed files

- `src/agents/openai-ws-stream.ts` (modified, +2/-2)


---

# PR #61527: fix(agents): OpenAI function-call replay — preserve malformed arguments instead of silent {} replacement

- Repository: openclaw/openclaw
- Author: 100yenadmin
- State: closed | merged: False
- Link: https://github.com/openclaw/openclaw/pull/61527

## Description (problem / solution / changelog)

## What this fixes (plain English)
When a provider sends malformed (unparseable) JSON in tool call arguments, the system was silently replacing the original content with an empty object `{}`. This destroyed the actual payload, making debugging impossible and causing replay failures. Now the original malformed string is preserved as-is.

## Technical details
**Root cause:** In `buildAssistantMessageFromResponse()`, the catch block for `JSON.parse(item.arguments)` replaced the raw string with `{}` on failure. On replay, `JSON.stringify({})` produces `"{}"` instead of the original content.

**Fix:**
- Parse failure path: preserve the raw argument string as-is instead of replacing with `{}`
- Replay path: already handles string arguments correctly (passes through without re-stringifying)

**Files changed:**
- `src/agents/openai-ws-message-conversion.ts` — preserve raw arguments on parse failure
- `src/agents/openai-ws-stream.ts` — defer ws text flush until phase is known
- `src/agents/openai-ws-stream.test.ts` — regression test for malformed argument preservation; corrected phase-buffering test for requireKnownPhase behavior
- `src/agents/pi-embedded-helpers.validate-turns.test.ts` — updated test fixtures
- `src/agents/subagent-orphan-recovery.ts` — orphan reconciliation DI seam
- `src/agents/subagent-registry-helpers.ts` — orphan grace window helper
- `src/agents/subagent-registry.ts` — sweep ordering and overlap guard

## Related
- Fixes #61478
- Found during post-merge review of #59643
- Part of phase-aware extraction family: #61463, #61481, #61476, #61477
- Companion PRs: #61528, #61529, #61525

## Test plan
- [x] 120/120 tests pass (openai-ws-stream + validate-turns suites)
- [x] Regression test for malformed argument preservation through replay
- [x] Phase-buffering test corrected for requireKnownPhase behavior

## Changed files

- `src/agents/openai-ws-message-conversion.ts` (modified, +5/-13)
- `src/agents/openai-ws-stream.test.ts` (modified, +205/-20)
- `src/agents/openai-ws-stream.ts` (modified, +10/-1)
- `src/agents/pi-embedded-helpers.validate-turns.test.ts` (modified, +39/-0)
- `src/agents/subagent-orphan-recovery.ts` (modified, +17/-2)
- `src/agents/subagent-registry-helpers.ts` (modified, +15/-0)
- `src/agents/subagent-registry.ts` (modified, +7/-5)


---

# PR #61463: fix(agents,gateway): phase-aware assistant text extraction — suppress OpenAI commentary leaks in sessions-helpers, TUI, and REST history

- Repository: openclaw/openclaw
- Author: 100yenadmin
- State: closed | merged: True
- Link: https://github.com/openclaw/openclaw/pull/61463

## Description (problem / solution / changelog)

## What this fixes (plain English)
Several places in the codebase that display assistant text were not aware of the phase system (commentary vs. final answer). This meant internal "thinking out loud" commentary could leak into user-visible surfaces like the TUI and HTTP/SSE session history endpoints. This PR makes those surfaces phase-aware, and hardens heartbeat session resolution against subagent key leaks.

## Technical details
Follow-up to #59643 and #59150, which fixed phase separation in the core WS path. Post-merge audit found adjacent surfaces still using phase-blind extraction.

**Surfaces fixed:**
- `src/tui/tui-formatters.ts` — assistant text extraction now uses `extractAssistantVisibleText()` to prefer `final_answer` over `commentary` phase blocks
- `src/infra/heartbeat-runner.ts` — heartbeat session resolution now rejects subagent session keys, falling back to the main session key instead of leaking into subagent scopes
- `src/gateway/sessions-history-http.test.ts` — regression test: REST history applies `chat.history` sanitization (strips NO_REPLY messages, preserves phase blocks)
- `src/tui/tui-formatters.test.ts` — regression test: mixed commentary + final_answer blocks extract only the visible final answer

**Explicitly deferred:** `extractAssistantTextForSilentCheck` and buffered delta/final rendering — lower-confidence, more behaviorally sensitive.

## Related
- Follow-up to #59643 and #59150
- Follow-up issues: #61474, #61475, #61476, #61477, #61478
- Companion PRs: #61529, #61528, #61527
- Related PRs: #61855, #61816

## Test plan
- [x] 27/27 TUI formatter tests pass
- [x] Regression test for mixed commentary + final_answer in TUI extraction
- [x] HTTP history regression test (REST path shares chat.history sanitization, strips NO_REPLY messages)
- [x] SSE seq validation for NO_REPLY message stripping
- [x] sessions-history-http gateway integration tests have 2 pre-existing infra failures (also fail on upstream/main)

## Changed files

- `CHANGELOG.md` (modified, +1/-0)
- `src/infra/heartbeat-runner.subagent-session-guard.test.ts` (added, +72/-0)
- `src/infra/heartbeat-runner.ts` (modified, +24/-17)
- `src/tui/tui-formatters.test.ts` (modified, +20/-0)
- `src/tui/tui-formatters.ts` (modified, +25/-0)

Code Example

"phase":"commentary"

---

"phase":"final_answer"

---

textSignature.phase == "commentary"

---
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

Title

Commentary-phase text leaks into user-visible output with openai-codex/gpt-5.4

Summary

When using OpenClaw with openai-codex/gpt-5.4, internal commentary text is leaking into normal user-visible output in Telegram

Examples:

  • Need fix line quoting properly.
  • Need simpler use cat overwrite full file.
  • Need verify healthy.

This appears to be internal tool-work narration, not intended user-facing content.

Evidence

Session history shows these leaked messages are explicitly marked:

"phase":"commentary"

Normal replies in the same session are marked:

"phase":"final_answer"

This makes it look like a filtering/rendering bug rather than normal model behavior.

Suggested fix

Suppress or filter assistant content where:

textSignature.phase == "commentary"

Only user-facing phases like final_answer should be rendered in normal chat/session views.

Steps to reproduce

Repro

  1. Use openai-codex/gpt-5.4
  2. Ask for a multi-step task involving tool calls
  3. Observe commentary-style text leaking into output
  4. Check session history and confirm leaked entries are marked phase="commentary"

Expected behavior

Only final assistant replies should be shown to the user.

Actual behavior

Commentary-like internal text is visible in chat/session output.

OpenClaw version

Environment - OpenClaw 2026.4.2 (d74a122) - Runtime/model: openai-codex/gpt-5.4 - Auth: OpenAI Codex OAuth

Operating system

Ubuntu 24.04

Install method

No response

Model

openai-codex/gpt-5.4

Provider / routing chain

OpenClaw 2026.4.2 running with OpenAI Codex OAuth auth, model/runtime openai-codex/gpt-5.4, direct runtime.

Additional provider/model setup details

<img width="660" height="1434" alt="Image" src="https://github.com/user-attachments/assets/9d89449b-69c6-4aa2-a903-4cc95860bd5a" />

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

extent analysis

TL;DR

Filter out assistant content where textSignature.phase equals "commentary" to prevent internal commentary text from leaking into user-visible output.

Guidance

  • Verify that the issue is indeed caused by the openai-codex/gpt-5.4 model by checking the session history for the "phase" marker.
  • Implement a filter to suppress or remove content with "phase":"commentary" before rendering it in the chat/session view.
  • Ensure that only phases like "final_answer" are rendered in normal chat/session views.
  • Test the fix by reproducing the steps outlined in the issue and verifying that commentary-style text no longer appears in the output.

Example

if (textSignature.phase === "commentary") {
  // Suppress or filter out this content
} else if (textSignature.phase === "final_answer") {
  // Render this content in the chat/session view
}

Notes

This fix assumes that the textSignature.phase marker is consistently applied to all assistant content. If this is not the case, additional debugging may be necessary to identify the root cause of the issue.

Recommendation

Apply the suggested workaround by filtering out commentary-phase content, as this appears to be a straightforward solution to the problem.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Only final assistant replies should be shown to the user.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING