Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
In Discord streaming.mode: "progress" with commentary enabled, some assistant commentary lines in the live progress draft render with a literal leading _ instead of italics, because commentary is underscore-wrapped (_line_) before the shared progress-line truncation runs and that truncation can drop the closing _.
Steps to reproduce
- Run OpenClaw
2026.5.31-beta.3 with a Discord guild text channel using streaming.mode: "progress" and progress.commentary: true (full config shape under "Additional provider/model setup details").
- Start a turn that emits visible assistant commentary/progress text long enough to exceed the progress-draft line limit (
maxLineChars).
- Watch the temporary Discord progress draft while it is being edited.
Intermittent: it does not reproduce on every commentary line. It often appears on an early commentary block but, per the screenshots, also affects later commentary blocks.
Expected behavior
A commentary line intended to be italic should render as italic text, or fall back to plain text if truncation would otherwise produce invalid Markdown. It should never display a literal leading _.
Actual behavior
Some commentary lines render with a literal leading underscore and no closing underscore, e.g.:
_I'll turn this into a skill update proposal rather than patching the skill files directly, since reusable skill...
Other commentary blocks in the same progress draft render correctly as italics, so this does not affect all commentary rendering — only lines that hit the truncation path.
OpenClaw version
2026.5.31-beta.3
Operating system
Ubuntu 24.04.4 LTS (kernel 6.17.0-29-generic)
Install method
npm global (openclaw installed under the global node_modules)
Model
openai/gpt-5.5 (effective agents.defaults.model.primary)
Provider / routing chain
Discord guild text channel -> OpenClaw Discord gateway -> OpenAI (Codex/OpenAI OAuth profile) -> openai/gpt-5.5
Additional provider/model setup details
Effective Discord streaming config (observed in the gateway openclaw.json):
{
"streaming": {
"mode": "progress",
"preview": {
"toolProgress": true,
"commandText": "raw"
},
"progress": {
"toolProgress": true,
"commandText": "raw",
"commentary": true
}
}
}
Auth is an OpenAI OAuth profile (Codex/ChatGPT sign-in). No per-channel model override is set for Discord, so the channel uses the default model above.
Logs, screenshots, and evidence
Screenshots showing a literal leading _ in the live Discord progress draft (bot username/app-id redacted) are being added to this issue momentarily:
- IMG_2461-redacted — first commentary line starts with
_I'll look...
- IMG_2462-redacted — one commentary line starts with
_I'll turn..., while the following commentary line renders italicized correctly
- IMG_2464-redacted — a later (non-first) commentary line starts with
_The proposal applied...
Captured literal text from the draft:
_I'll turn this into a skill update proposal rather than patching the skill
files directly, since reusable skill...
Impact and severity
- Affected: Discord users on
streaming.mode: "progress" with progress.commentary: true.
- Severity: Low. Cosmetic only — it affects the temporary progress draft; final answers are unaffected.
- Frequency: Intermittent — only commentary lines long enough to be truncated; often an early block but also later blocks.
- Consequence: The live progress draft shows malformed Markdown (a stray leading
_), making in-progress status harder to read.
Additional information
Duplicate search
No existing issue covers this literal-underscore-on-truncation symptom. Closest related, all distinct:
Root cause (source on main @ a46d331, version 2026.5.31-beta.3; verified by source inspection)
Commentary is wrapped in italic underscores before the shared progress-line truncation, and that truncation only rebalances backticks — never the italic _ — so a truncated commentary line keeps an unmatched leading _.
-
extensions/discord/src/monitor/message-handler.process.ts:1016-1018 routes payload.kind === "preamble" to draftPreview.pushCommentaryProgress(...).
-
extensions/discord/src/monitor/message-handler.draft-preview.ts, normalizeCommentaryProgressText (lines 473-484) wraps each non-empty line in underscores — balanced at this point:
return cleaned
.split(/\r?\n/u)
.map((line) => line.replace(/\s+/g, " ").trim())
.filter(Boolean)
.map((line) => `_${line}_`) // line 482
.join("\n");
-
The draft is rendered via formatChannelProgressDraftText, and core src/channels/streaming.ts:1016 applies compactChannelProgressDraftLine(rawText, maxLineChars).
-
compactChannelProgressDraftLine (src/channels/streaming.ts:872) truncates the line and finishes every return path through removeUnbalancedInlineBackticks(...) (lines 891 and 914). That helper (lines 855-861) only repairs backticks:
function removeUnbalancedInlineBackticks(value: string): string {
const backtickCount = Array.from(value).filter((char) => char === "`").length;
if (backtickCount % 2 === 0) {
return value;
}
return value.trimStart().startsWith("`") ? value.replaceAll("`", "'") : value.replaceAll("`", "");
}
So the truncation already knows it must keep inline Markdown balanced — it does exactly that for code spans — but the italic _ (and * bold) wrapper has no equivalent guard. When a commentary line exceeds maxLineChars, truncation drops the trailing _ and leaves the leading one; Discord renders it literally. This matches the observed pattern: only commentary lines long enough to be truncated are affected, which is why it is intermittent and not tied to the first block. Presented as the most likely path given the source, not asserted as the only one.
Suggested fix (mirroring the existing backtick repair; final approach left to maintainers)
Primary — make the compaction boundary underscore-aware, the same way it is already backtick-aware:
- Add an underscore counterpart to
removeUnbalancedInlineBackticks (or generalize it to a delimiter-aware removeUnbalancedInlineMarker covering `, _, and *) and call it at the same two return sites in compactChannelProgressDraftLine (streaming.ts:891, streaming.ts:914).
- To avoid mangling legitimate underscores in arbitrary text (e.g.
snake_case, paths), scope the underscore repair to the unmatched leading wrapper only — when the compacted line starts with _ and has an odd _ count, drop just the dangling marker (or fall back to plain text) rather than stripping every _. This is the one place the backtick helper's blunt replaceAll is riskier for _, so the underscore variant should be narrower.
Alternative (more robust, larger change): have the Discord side apply the italic wrap after compaction instead of in normalizeCommentaryProgressText, so the delimiters are added to already-truncated text and can never be split. This keeps core compaction Markdown-agnostic but requires threading "this line is italic commentary" through to post-compaction.
Either way: render commentary as plain text rather than emitting a half-open _ when balancing is not possible.
Tests: there is currently no co-located unit test for these helpers (both are module-private in src/channels/streaming.ts, and there is no message-handler.draft-preview.test.ts under extensions/discord/src/monitor/). Suggest adding a focused case — commentary longer than maxLineChars must not yield a line starting with a lone _ — at whichever seam the fix lands (a new draft-preview test on the Discord side, or a unit test if the repair helper is exported).
Happy to open a PR with the fix plus that test if the approach looks right.
Filed with AI assistance (Claude Code). Bug behavior is from the reporter's live OpenClaw + Discord install (screenshots attached); the root-cause and fix were verified against openclaw/openclaw main @ a46d331.
Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
In Discord
streaming.mode: "progress"with commentary enabled, some assistant commentary lines in the live progress draft render with a literal leading_instead of italics, because commentary is underscore-wrapped (_line_) before the shared progress-line truncation runs and that truncation can drop the closing_.Steps to reproduce
2026.5.31-beta.3with a Discord guild text channel usingstreaming.mode: "progress"andprogress.commentary: true(full config shape under "Additional provider/model setup details").maxLineChars).Intermittent: it does not reproduce on every commentary line. It often appears on an early commentary block but, per the screenshots, also affects later commentary blocks.
Expected behavior
A commentary line intended to be italic should render as italic text, or fall back to plain text if truncation would otherwise produce invalid Markdown. It should never display a literal leading
_.Actual behavior
Some commentary lines render with a literal leading underscore and no closing underscore, e.g.:
Other commentary blocks in the same progress draft render correctly as italics, so this does not affect all commentary rendering — only lines that hit the truncation path.
OpenClaw version
2026.5.31-beta.3Operating system
Ubuntu 24.04.4 LTS (kernel
6.17.0-29-generic)Install method
npm global (
openclawinstalled under the globalnode_modules)Model
openai/gpt-5.5(effectiveagents.defaults.model.primary)Provider / routing chain
Discord guild text channel -> OpenClaw Discord gateway -> OpenAI (Codex/OpenAI OAuth profile) ->
openai/gpt-5.5Additional provider/model setup details
Effective Discord streaming config (observed in the gateway
openclaw.json):{ "streaming": { "mode": "progress", "preview": { "toolProgress": true, "commandText": "raw" }, "progress": { "toolProgress": true, "commandText": "raw", "commentary": true } } }Auth is an OpenAI OAuth profile (Codex/ChatGPT sign-in). No per-channel model override is set for Discord, so the channel uses the default model above.
Logs, screenshots, and evidence
Screenshots showing a literal leading
_in the live Discord progress draft (bot username/app-id redacted) are being added to this issue momentarily:_I'll look..._I'll turn..., while the following commentary line renders italicized correctly_The proposal applied...Captured literal text from the draft:
Impact and severity
streaming.mode: "progress"withprogress.commentary: true._), making in-progress status harder to read.Additional information
Duplicate search
No existing issue covers this literal-underscore-on-truncation symptom. Closest related, all distinct:
Root cause (source on
main@a46d331, version 2026.5.31-beta.3; verified by source inspection)Commentary is wrapped in italic underscores before the shared progress-line truncation, and that truncation only rebalances backticks — never the italic
_— so a truncated commentary line keeps an unmatched leading_.extensions/discord/src/monitor/message-handler.process.ts:1016-1018routespayload.kind === "preamble"todraftPreview.pushCommentaryProgress(...).extensions/discord/src/monitor/message-handler.draft-preview.ts,normalizeCommentaryProgressText(lines 473-484) wraps each non-empty line in underscores — balanced at this point:The draft is rendered via
formatChannelProgressDraftText, and coresrc/channels/streaming.ts:1016appliescompactChannelProgressDraftLine(rawText, maxLineChars).compactChannelProgressDraftLine(src/channels/streaming.ts:872) truncates the line and finishes every return path throughremoveUnbalancedInlineBackticks(...)(lines 891 and 914). That helper (lines 855-861) only repairs backticks:So the truncation already knows it must keep inline Markdown balanced — it does exactly that for code spans — but the italic
_(and*bold) wrapper has no equivalent guard. When a commentary line exceedsmaxLineChars, truncation drops the trailing_and leaves the leading one; Discord renders it literally. This matches the observed pattern: only commentary lines long enough to be truncated are affected, which is why it is intermittent and not tied to the first block. Presented as the most likely path given the source, not asserted as the only one.Suggested fix (mirroring the existing backtick repair; final approach left to maintainers)
Primary — make the compaction boundary underscore-aware, the same way it is already backtick-aware:
removeUnbalancedInlineBackticks(or generalize it to a delimiter-awareremoveUnbalancedInlineMarkercovering`,_, and*) and call it at the same two return sites incompactChannelProgressDraftLine(streaming.ts:891,streaming.ts:914).snake_case, paths), scope the underscore repair to the unmatched leading wrapper only — when the compacted line starts with_and has an odd_count, drop just the dangling marker (or fall back to plain text) rather than stripping every_. This is the one place the backtick helper's bluntreplaceAllis riskier for_, so the underscore variant should be narrower.Alternative (more robust, larger change): have the Discord side apply the italic wrap after compaction instead of in
normalizeCommentaryProgressText, so the delimiters are added to already-truncated text and can never be split. This keeps core compaction Markdown-agnostic but requires threading "this line is italic commentary" through to post-compaction.Either way: render commentary as plain text rather than emitting a half-open
_when balancing is not possible.Tests: there is currently no co-located unit test for these helpers (both are module-private in
src/channels/streaming.ts, and there is nomessage-handler.draft-preview.test.tsunderextensions/discord/src/monitor/). Suggest adding a focused case — commentary longer thanmaxLineCharsmust not yield a line starting with a lone_— at whichever seam the fix lands (a new draft-preview test on the Discord side, or a unit test if the repair helper is exported).Happy to open a PR with the fix plus that test if the approach looks right.
Filed with AI assistance (Claude Code). Bug behavior is from the reporter's live OpenClaw + Discord install (screenshots attached); the root-cause and fix were verified against
openclaw/openclawmain@a46d331.