Skip to content

fix(agents): preserve streamed assistant text when Claude CLI result event is empty#90450

Open
totobusnello wants to merge 7 commits into
openclaw:mainfrom
totobusnello:fix/claude-cli-empty-result-preserve-streamed-text
Open

fix(agents): preserve streamed assistant text when Claude CLI result event is empty#90450
totobusnello wants to merge 7 commits into
openclaw:mainfrom
totobusnello:fix/claude-cli-empty-result-preserve-streamed-text

Conversation

@totobusnello

@totobusnello totobusnello commented Jun 4, 2026

Copy link
Copy Markdown

Summary

  • The claude stream-json dialect can emit a final result event with empty text even though assistant text deltas were already streamed (or the turn was tool-only). Both JSONL parsers trust the final event and discard everything accumulated, so the CLI runner throws CLI backend returned an empty response. (reason=empty_response) and the gateway falls back to the next model — losing a reply that had already fully arrived.
  • Fix: when the result event has no text, fall back to the accumulated streamed deltas instead of dropping them, in both createCliJsonlStreamingParser and parseCliJsonl; add a structured CliOutput.hadToolCalls flag (via the existing isClaudeToolUseBlockType) so tool-only turns stop triggering the empty-response failover.
  • The parser already half-acknowledges this case — parseClaudeCliJsonlResult deliberately keeps session metadata when the result text is empty ("Keep the resolved session handle and usage instead of dropping them"). This PR extends the same reasoning to the streamed assistant text itself.
  • Safety: if the model genuinely returned nothing, the accumulated text is also empty, so the FailoverError fires exactly as before. Non-Claude dialects are untouched (hadToolCalls stays undefined).
  • Reviewers should focus on: the fallback expression in both parsers, the structured tool_use detection helper, and the extra output.hadToolCalls !== true guard in cli-runner.ts.
  • The vulnerable path (if (result) { output = result; return; }) is present in the published 2026.6.1 and 2026.6.2-beta.1 npm tarballs (dist/claude-live-session-*.js).

Tests

  • cli-output.test.ts: 4 new cases — streamed text preserved on empty result (both parsers), tool-only flag set (both parsers); updated the existing "preserves Claude session metadata even when the final result text is empty" expectation (hadToolCalls: false).
  • cli-runner.reliability.test.ts: existing empty-response throw/silent tests pass unchanged.
  • pnpm build && pnpm check && pnpm test run locally (macOS): the only failures are environment-specific (host locale leaking into Intl formatting asserts and /tmp/private/tmp symlink canonicalization), none in the touched files.

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: Claude CLI turns streamed a full reply, but the final result event arrived with empty text; the gateway threw CLI backend returned an empty response. (reason=empty_response) and fell back to openai/gpt-5.5, discarding the streamed reply. Tool-only turns hit the same false failover.

  • Real environment tested: production OpenClaw 2026.6.1 gateway on an Ubuntu VPS (systemd service), anthropic/claude-sonnet-4-6 and claude-haiku-4-5 via the claude-cli backend, fallback chain to openai/gpt-5.5, live Discord/WhatsApp channels and cron agents.

  • Exact steps or command run after this patch: applied the equivalent fix as a dist-bundle patch (same logic as this PR's source change) to dist/claude-live-session-*.js and dist/cli-runner-*.js, validated with node --check, then systemctl restart openclaw-gateway (2026-06-04 13:56 BRT) and watched journalctl -u openclaw-gateway -f under normal production traffic; later verified with ssh to the host and journalctl -u openclaw-gateway --since "14:26" | grep -c empty_response.

  • Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output): redacted runtime logs / copied live output below. After the restart: journalctl -u openclaw-gateway --since "14:26" | grep -c empty_response0 (vs 3 occurrences earlier that same day), and the gateway boot shows claude sessions healthy:

    Jun 04 14:26:26 [gateway] http server listening (11 plugins: anthropic, codex, discord, ...)
    Jun 04 14:26:27 [gateway] ready
    Jun 04 14:26:27 [heartbeat] started
    Jun 04 14:26:29 [whatsapp] Listening for WhatsApp inbound messages (DM + 2 configured groups).
    
  • Observed result after fix: zero empty_response fallbacks across several hours of live traffic since the restart; claude turns that previously produced outBytes=0 now deliver the streamed text and stay on the requested model. The tool-only half of this fix has been running in the same production gateway since 2026-05-31 with no false empty_response fallbacks.

  • What was not tested: non-Claude CLI backends (gemini/codex dialects — code paths untouched, hadToolCalls stays undefined for them); allowEmptyAssistantReplyAsSilent=true beyond existing unit coverage.

  • Proof limitations or environment constraints: the empty-result event is intermittent (3 occurrences on 2026-06-04 before the patch, none reproducible on demand); an instrumented hook in the production gateway dumps the raw JSONL stream on the next occurrence, and we will attach a sanitized capture as a follow-up comment.

  • Before evidence (optional but encouraged): three occurrences on 2026-06-04 before the patch. Note outHash=e3b0c44298fc — the SHA-256 of the empty string — after 40/66/86 streamed JSONL lines: a full stream arrived, exactly zero bytes were delivered, and the turn was answered by the fallback model:

    Jun 04 09:56:23 [agent/cli-backend] claude live session turn: provider=claude-cli model=claude-sonnet-4-6 durationMs=12765 rawLines=40 outBytes=0 outHash=e3b0c44298fc
    Jun 04 09:56:23 [model-fallback/decision] decision=candidate_failed requested=anthropic/claude-sonnet-4-6 candidate=anthropic/claude-sonnet-4-6 reason=empty_response next=openai/gpt-5.5 detail=CLI backend returned an empty response.
    Jun 04 13:42:52 [agent/cli-backend] claude live session turn: provider=claude-cli model=claude-sonnet-4-6 durationMs=30337 rawLines=66 outBytes=0 outHash=e3b0c44298fc
    Jun 04 13:42:52 [model-fallback/decision] decision=candidate_failed requested=anthropic/claude-sonnet-4-6 candidate=anthropic/claude-sonnet-4-6 reason=empty_response next=openai/gpt-5.5 detail=CLI backend returned an empty response.
    Jun 04 13:45:51 [agent/cli-backend] claude live session turn: provider=claude-cli model=claude-sonnet-4-6 durationMs=36624 rawLines=86 outBytes=0 outHash=e3b0c44298fc
    Jun 04 13:45:51 [model-fallback/decision] decision=candidate_failed requested=anthropic/claude-sonnet-4-6 candidate=anthropic/claude-sonnet-4-6 reason=empty_response next=openai/gpt-5.5 detail=CLI backend returned an empty response.
    

…event is empty

The claude stream-json dialect can emit a final result event with empty
text even though assistant text deltas were streamed (or the turn was
tool-only). Both JSONL parsers trusted the final event and discarded the
accumulated text, which made the CLI runner throw
"CLI backend returned an empty response." and triggered model fallback,
losing a reply that had already fully arrived.

- createCliJsonlStreamingParser: fall back to the accumulated streamed
  text (or collected message texts) when the result event has no text,
  mirroring how session metadata is already preserved.
- parseCliJsonl: accumulate streamed deltas and apply the same fallback.
- CliOutput.hadToolCalls: structured flag set when tool_use /
  server_tool_use / mcp_tool_use blocks are seen, so tool-only turns are
  not treated as empty replies.
- cli-runner: skip the empty-response FailoverError when the turn had
  tool calls.

Genuinely empty turns keep the previous behavior: with no deltas the
accumulated text is also empty, so the FailoverError still fires.
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: M triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 4, 2026
@clawsweeper

clawsweeper Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 9, 2026, 12:10 AM ET / 04:10 UTC.

Summary
The PR changes Claude CLI JSONL parsing to preserve accumulated streamed text when a final result event is empty, adds empty-turn tool-use metadata, and extends parser plus runner reliability coverage.

PR surface: Source +76, Tests +243. Total +319 across 4 files.

Reproducibility: yes. by source inspection and production logs: current main returns the empty Claude result before using accumulated stream deltas, and the PR body shows live empty_response fallbacks after streamed raw lines. The exact Claude edge is intermittent, so I did not establish an on-demand live reproduction.

Review metrics: none identified.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Update the PR body to remove the stale claim that tool-only turns stop triggering empty-response failover by default.

Risk before merge

  • [P2] This is fallback-sensitive provider routing: preserving streamed Claude text intentionally prevents an empty_response failover where current main would switch to the next model.
  • [P1] The PR body still describes the removed default tool-only failover bypass, so the public summary should be corrected before merge to match the current head.

Maintainer options:

  1. Update the description, then review for merge (recommended)
    Have the author correct the PR body so it matches the current head, then let maintainers accept the parser-level fallback behavior with focused CI/proof in view.
  2. Accept the routing behavior as intentional
    Maintainers can choose to merge without further code changes if they agree that an empty Claude result after streamed deltas should stay on Claude rather than fall back.

Next step before merge

  • [P2] No automated code repair is needed; maintainer review should focus on fallback-sensitive Claude CLI behavior and PR-body cleanup before merge.

Security
Cleared: Cleared: the diff is limited to agent parser/runner code and tests, with no dependency, workflow, package, secret, or downloaded-code execution surface changed.

Review details

Best possible solution:

Land the parser-level preservation after maintainer acceptance of the Claude fallback semantics, with the PR body updated to say truly empty/tool-only turns still follow the existing silent-empty policy.

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

Yes, by source inspection and production logs: current main returns the empty Claude result before using accumulated stream deltas, and the PR body shows live empty_response fallbacks after streamed raw lines. The exact Claude edge is intermittent, so I did not establish an on-demand live reproduction.

Is this the best way to solve the issue?

Yes: preserving deltas inside the CLI JSONL parser is the narrowest owner-boundary fix because both normal and live Claude CLI paths consume that parser output. The runner now keeps the existing default failover contract for truly empty output.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 9fdd56da2106.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR supplies redacted production gateway logs and copied live output showing the central empty-result fallback symptom before an equivalent patch and zero empty_response matches after restart.

Label justifications:

  • P1: The bug can drop already-streamed Claude CLI replies and answer via a fallback model in live agent/channel workflows.
  • merge-risk: 🚨 message-delivery: The patch changes the path that decides whether streamed assistant text is delivered or discarded after an empty final result.
  • merge-risk: 🚨 auth-provider: The patch changes when Claude CLI is treated as the winning provider/model instead of triggering model fallback.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR supplies redacted production gateway logs and copied live output showing the central empty-result fallback symptom before an equivalent patch and zero empty_response matches after restart.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR supplies redacted production gateway logs and copied live output showing the central empty-result fallback symptom before an equivalent patch and zero empty_response matches after restart.
Evidence reviewed

PR surface:

Source +76, Tests +243. Total +319 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 78 2 +76
Tests 2 246 3 +243
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 324 5 +319

What I checked:

  • Current main still trusts an empty Claude result: On current main, the streaming parser stores output = result as soon as a Claude result record is parsed, and the complete parser returns claudeResult before any accumulated stream deltas can be used, so an empty final result can still erase streamed text. (src/agents/cli-output.ts:702, 9fdd56da2106)
  • PR preserves accumulated text for empty final results: At the PR head, both JSONL parser paths keep non-empty assistantText or message text when the Claude result text is empty, while retaining session and usage metadata. (src/agents/cli-output.ts:743, 9d0223f67f30)
  • Default empty-response fallback is preserved: The current PR head keeps the existing runner behavior: empty CLI output still throws empty_response unless allowEmptyAssistantReplyAsSilent is explicitly true, so the earlier unconditional tool-only silence risk is addressed. (src/agents/cli-runner.ts:552, 9d0223f67f30)
  • Focused tests cover parser and fallback policy: The PR adds complete-parser and streaming-parser cases for empty final results after streamed text, plus runner coverage that tool-only empty turns fail over by default and become silent only under the existing opt-in policy. (src/agents/cli-output.test.ts:405, 9d0223f67f30)
  • Claude CLI stream-json is the shipped backend surface: The bundled Anthropic CLI backend uses claude -p --output-format stream-json --include-partial-messages --verbose with output: "jsonl" and liveSession: "claude-stdio", so the parser behavior is on the production Claude CLI path. (extensions/anthropic/cli-backend.ts:38, 9fdd56da2106)
  • Related narrower PR is not a superseding landing path: The referenced silent-empty policy PR is closed unmerged and only passed allowEmptyAssistantReplyAsSilent through the reply fallback boundary; it did not implement the parser-level streamed-text preservation this PR adds. (src/auto-reply/reply/agent-runner-execution.ts, 14ef91a86909)

Likely related people:

  • @steipete: History shows Peter Steinberger split the CLI runner pipeline and introduced Claude CLI JSONL streaming support, which are the central parser and runner surfaces touched here. (role: introduced behavior and likely feature owner; confidence: high; commits: 48ae97633303, 4e099689c075; files: src/agents/cli-output.ts, src/agents/cli-runner.ts)
  • @vincentkoc: Recent current-main history and blame touch the same CLI output and runner files, and recent Claude parsing/cache work appears in the file history. (role: recent area contributor; confidence: medium; commits: ff5fac143973, bcd0a492a4, 2e08f0f4221f; files: src/agents/cli-output.ts, src/agents/cli-runner.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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.

How this review workflow works
  • 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.

@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 4, 2026
@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. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. labels Jun 4, 2026
@totobusnello

Copy link
Copy Markdown
Author

Addressing the two P2 risk notes from the review, since they're the design trade-offs maintainers need to accept:

1. Malformed empty result with a tool_use block → silent turn instead of fallback

This is a real trade-off, but silence is the safer side of it. By the time the empty result arrives, the turn's tool calls have already executed (side effects included). Falling back re-answers the turn on a model that never saw those tool calls or their results, so the fallback reply is generated without the context of actions that already happened — arguably worse than a silent turn. Also note the window is narrow: the guard only suppresses the failover when the turn verifiably emitted tool_use blocks (structured detection, not heuristics) and both the final result text and every streamed text delta were empty.

2. Requested-provider/no-fallback contract for tool-only turns

2026.6.1 already introduced allowEmptyAssistantReplyAsSilent, so the codebase already treats "empty reply = intentional silence" as a legitimate, opt-in outcome. This PR applies the same semantics automatically to the one case where the parser has structural evidence the emptiness is intentional (tool-only work), instead of requiring the operator to opt in globally. Turns with no tool calls and no streamed text keep the exact previous behavior: FailoverError → fallback chain.

If maintainers prefer a more conservative rollout, gating the hadToolCalls bypass behind the existing allowEmptyAssistantReplyAsSilent flag (or a dedicated config) would be a small change — happy to adjust.

Separately: we left an instrumented hook in our production gateway that dumps the raw JSONL stream the next time Claude emits an empty final result after streaming deltas; we'll attach a sanitized capture here when it fires.

@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 9, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. and removed 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. labels Jun 9, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 9, 2026
@totobusnello

Copy link
Copy Markdown
Author

The malformed-import blocker from the last review was a casualty of syncing this branch with main earlier today — the conflict resolution dropped the opening brace on the normalizeLowercaseStringOrEmpty import. Fixed at head 97c3825d:

import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";

The prior verdict was computed against 90a79d74 (the broken intermediate), so the P1 "would break the parser module" no longer applies to the current head. CI on 97c3825d is green: 130 checks passing, 0 failing (the build/check/test/lint matrix, CodeQL, and Opengrep). The only non-green item is the bot's own auto-response, pending this re-review. The parser/runner logic is the originally-submitted, proven version — only the import line and a post-merge if-block closure were touched.

On the two P2 notes (tool-only → silent vs. fallback): covered in my earlier comment — silence is the safer side, since by the time the empty result arrives the tool calls have already executed, so a fallback re-answers without that context. Still happy to gate the hadToolCalls bypass behind the existing allowEmptyAssistantReplyAsSilent flag if maintainers prefer a more conservative default.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. and removed merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jun 9, 2026
…antReplyAsSilent

The empty-response guard skipped failover whenever a Claude tool_use block was seen, even when allowEmptyAssistantReplyAsSilent was false — turning an existing fallback answer into no visible reply. Gate tool-only empty output on the existing silent-empty policy: empty turns (tool-only or not) fail over by default and stay silent only when the caller opted in. Parser-level streamed-text preservation is unchanged.

Add cli-runner.reliability coverage for both policy states on tool-only empty output (default -> FailoverError, explicit silent -> SILENT_REPLY_TOKEN).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 9, 2026
@totobusnello

Copy link
Copy Markdown
Author

Pushed ac2f807c implementing Option 1 (gate tool-only silence behind the existing policy) from the last review.

Change (src/agents/cli-runner.ts): removed the unconditional output.hadToolCalls empty-response bypass. An empty CLI turn — tool-only or not — now fails over by default and stays silent only when the caller set allowEmptyAssistantReplyAsSilent. This restores the prior fallback contract: existing fallback chains are no longer silently swallowed on a tool-only empty turn. The parser-level streamed-text preservation is unchanged, so genuinely-streamed replies still never reach this branch empty.

Tests (src/agents/cli-runner.reliability.test.ts): added focused coverage for both policy states on a verifiably tool-only empty turn (tool_use block + empty result):

  • allowEmptyAssistantReplyAsSilent unset → FailoverError (empty_response).
  • allowEmptyAssistantReplyAsSilent: trueSILENT_REPLY_TOKEN, no fallback.

Local verification on ac2f807c: tsc --noEmit clean, oxlint clean, and the focused suites green — cli-output.test.ts (36) and cli-runner.reliability.test.ts (39, incl. the 2 new cases). git diff --check clean.

This directly addresses the P1 at src/agents/cli-runner.ts:548 and should clear the merge-risk: message-delivery / auth-provider / availability concerns, since the default fallback behavior is preserved.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@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: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 9, 2026
The jsonl/text ternary widened to string without a const assertion (tsc TS2322), but a full type assertion tripped oxlint no-unnecessary-type-assertion. Use per-branch `as const` to satisfy both lint and typecheck.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 9, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M 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.

1 participant