Skip to content

Reasoning summary events can contain and render literal <!-- --> placeholders #31664

Description

@Eridanus117

What happened?

Reasoning summaries can contain a literal empty HTML comment placeholder, <!-- -->. This placeholder then shows up in user-facing surfaces such as the TUI progress/history view and codex exec --json output.

Example observed in the TUI:

• <!-- -->

  Clarifying Codex comment leaks and prevention
  <!-- -->

  Proposing global instruction update
  <!-- -->

A later clean-isolation run reproduced the same issue in exec --json and persisted session JSONL, so this is broader than a TUI-only rendering issue.

Environment

codex-cli: 0.143.0
release tag checked: rust-v0.143.0
model: gpt-5.5
model_reasoning_effort: xhigh
model_reasoning_summary: auto / concise / detailed / none tested
OS: macOS 26.5.1, arm64
terminal: Ghostty 1.3.2-HEAD-+05c3e29
install: Homebrew cask
subscription/auth: ChatGPT Pro auth

The regular user config originally had:

model_reasoning_summary = "auto"
model_reasoning_effort = "xhigh"

codex doctor --json reported overallStatus = warning, but the warning was about rollout/session inventory mismatch with an empty historical session file; it appears unrelated. Config parsing and auth were OK, and the responses websocket handshake succeeded.

Clean-isolation reproduction

I reproduced with a fresh temporary HOME and CODEX_HOME, copying only auth.json so the CLI could authenticate. The invocation used --ignore-user-config --ignore-rules, a temp working directory, and no user hooks, personal skills, AGENTS.md, project instructions, or user config.

Command shape:

ISO_ROOT=$(mktemp -d /tmp/codex-clean-iso2.XXXXXX)
ISO_HOME="$ISO_ROOT/home"
ISO_CODEX="$ISO_ROOT/codex"
mkdir -p "$ISO_HOME" "$ISO_CODEX"
cp "$HOME/.codex/auth.json" "$ISO_CODEX/auth.json"

HOME="$ISO_HOME" CODEX_HOME="$ISO_CODEX" \
  codex --ask-for-approval never --sandbox workspace-write \
  exec --json --ignore-user-config --ignore-rules --skip-git-repo-check \
  -C "$ISO_ROOT" -m gpt-5.5 \
  -c 'model_reasoning_effort="xhigh"' \
  -c 'model_reasoning_summary="auto"' \
  < "$ISO_ROOT/prompt.txt" > "$ISO_ROOT/out.jsonl"

Prompt:

Without using the network, inspect this empty temp workspace. Run `pwd` and `ls -la`, then answer with two concise bullet points: what files are present and the current working directory basename.

Result: reproduced in exec --json:

{"type":"item.completed","item":{"id":"item_0","type":"reasoning","text":"**Planning parallel command execution**\n\n<!-- -->"}}

The persisted isolated session JSONL also contained the placeholder in both agent_reasoning and completed reasoning.summary_text:

{"type":"event_msg","payload":{"type":"agent_reasoning","text":"**Planning parallel command execution**\n\n<!-- -->"}}
{"type":"response_item","payload":{"type":"reasoning","summary":[{"type":"summary_text","text":"**Planning parallel command execution**\n\n<!-- -->"}]}}

A minimal no-tool prompt in the same isolation style did not reproduce; its session had "summary": []. So the issue appears task-shape dependent and intermittent, but it reproduces without my local config/hooks/skills/project instructions.

Matrix

I then ran a small clean-isolation matrix: model_reasoning_summary x task shape.

summary_mode  task_shape  stdout <!-- -->  session <!-- -->  agent_reasoning events  reasoning summary items
auto          no_tool     0               0                 0                       0
auto          tool        0               0                 0                       0
concise       no_tool     0               0                 1                       1
concise       tool        0               0                 1                       1
detailed      no_tool     0               0                 0                       0
detailed      tool        1               2                 1                       1
none          no_tool     0               0                 0                       0
none          tool        0               0                 0                       0

The detailed + tool run produced:

{"kind":"agent_reasoning","text":"**Running parallel directory commands**\n\n<!-- -->"}
{"kind":"reasoning","summary":["**Running parallel directory commands**\n\n<!-- -->"]}

I also repeated the auto + tool case five times with the same isolated prompt. Runs 1-4 did not emit summaries; run 5 emitted two reasoning summary items, both with the placeholder:

run  stdout <!-- -->  session <!-- -->  agent_reasoning events  reasoning summary items
1    0               0                 0                       0
2    0               0                 0                       0
3    0               0                 0                       0
4    0               0                 0                       0
5    2               4                 2                       2

Run 5 summary texts:

**Planning parallel execution of pwd and ls**\n\n<!-- -->
**Preparing to execute pwd and ls commands**\n\n<!-- -->

Local session frequency

In my normal ~/.codex/sessions/2026/07/08 data, before the clean-isolation checks, I found:

files with agent_reasoning containing <!-- -->: 9
agent_reasoning entries containing <!-- -->: 1680

Representative normal-session lines:

{"type":"event_msg","payload":{"type":"agent_reasoning","text":"**Clarifying Codex comment leaks and prevention**\n\n<!-- -->"}}
{"type":"event_msg","payload":{"type":"agent_reasoning","text":"**Proposing global instruction update**\n\n<!-- -->"}}
{"type":"response_item","payload":{"type":"reasoning","summary":[{"type":"summary_text","text":"**Clarifying Codex comment leaks and prevention**\n\n<!-- -->"},{"type":"summary_text","text":"**Proposing global instruction update**\n\n<!-- -->"}]}}

Those entries predated the user later copying the visible leak back into the conversation, so they were not merely echoes of user-provided text.

Source-path notes from rust-v0.143.0

I checked the release tag corresponding to the installed version. The user-facing path appears to pass summary text through without filtering:

  • codex-rs/codex-api/src/sse/responses.rs:354-369 maps response.reasoning_summary_text.delta/done into ResponseEvent::ReasoningSummaryDelta/Done using the server-provided delta/text as-is.
  • codex-rs/core/src/session/turn.rs:2337-2368 turns ReasoningSummaryDone.text into ReasoningContentDeltaEvent.delta as-is for streaming to the client.
  • codex-rs/core/src/event_mapping.rs:177-195 maps completed ResponseItem::Reasoning.summary[].text into ReasoningItem.summary_text with text.clone().
  • codex-rs/protocol/src/legacy_events.rs:104-110 turns every ReasoningItem.summary_text into AgentReasoningEvent { text: summary.clone() }.
  • codex-rs/exec/src/event_processor_with_jsonl_output.rs:150-158 joins ThreadItem::Reasoning.summary and emits it as an exec --json reasoning item if text.trim() is non-empty.
  • codex-rs/exec/src/event_processor_with_human_output.rs:468-482 similarly joins summary entries for human output.
  • codex-rs/tui/src/chatwidget/streaming.rs:200-235 appends reasoning deltas directly into reasoning_buffer and later calls new_reasoning_summary_block.
  • codex-rs/tui/src/history_cell/messages.rs:486-499 splits **header** from the remaining content. For **Header**\n\n<!-- -->, the remaining content is non-empty, so the final reasoning cell displays the literal placeholder.

Expected behavior

User-facing reasoning summaries should not expose literal empty HTML comment placeholders.

Either:

  1. Do not generate <!-- --> in reasoning summary text, or
  2. Normalize/filter placeholder-only HTML comment lines before emitting user-facing reasoning summary events and rendering them.

If raw ResponseItem persistence should remain untouched for debugging, the filter could live in the user-facing conversion/rendering layers, such as the AgentReasoningEvent / ThreadItem::Reasoning / exec --json / TUI history conversion path.

Workaround

model_reasoning_summary = "none" parses successfully and avoided the issue in the matrix, but it disables reasoning summaries entirely.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLITUIIssues related to the terminal user interface: text input, menus and dialogs, and terminal displaybugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions