fix: surface stalled-session interruptions#103990
Conversation
|
Codex review: needs changes before merge. Reviewed July 18, 2026, 5:46 AM ET / 09:46 UTC. Summary PR surface: Source +67, Tests +151. Total +218 across 8 files. Reproducibility: yes. at source level: the linked report and the PR’s negative-control output identify the stale-expiry and non-cooperative-tool paths, but this review did not execute the current-main reproduction. Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Rebase onto current main, apply the same abort race to the active Do we have a high-confidence way to reproduce the issue? Yes at source level: the linked report and the PR’s negative-control output identify the stale-expiry and non-cooperative-tool paths, but this review did not execute the current-main reproduction. Is this the best way to solve the issue? No; the terminal-outcome design is narrow and appropriate, but the abort race must be applied to the active Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against a941d3ab727e. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +67, Tests +151. Total +218 across 8 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
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
Review history (10 earlier review cycles; latest 8 shown)
|
b984de4 to
31a8d1b
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
8eff5ce to
3525e7a
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
4aea3e6 to
cd1bdd2
Compare
f2ad2fc to
95e8af1
Compare
55e24bc to
3198858
Compare
- wrapToolWithAbortSignal: race tool execution against run abort signal so non-cooperative tools no longer block an aborted turn - Stale reply-operation recovery now preserves run_stalled as a user-visible interruption instead of silently dropping the draft - Both the error handler and fallback-cycle settlement check for stalled operations before the broad user-abort predicate - isReplyOperationStalled and buildStalledRunReplyPayload helpers keep stalled handling explicit and separate from abort paths Closes openclaw#103905
6a15996 to
200dea1
Compare
Closes #103905
What Problem This Solves
Fixes an issue where a stuck-session recovery could remove a channel's streamed draft without sending a terminal notice. A non-cooperative tool could also keep running after the owning turn was aborted, leaving the caller blocked until it eventually settled.
Why This Change Was Made
The reply-operation terminal state now preserves
run_stalledas a user-visible interruption while explicit user and restart cancellations keep their existing behavior. Tool execution races the existing cooperativeAbortSignal, so an aborted run stops waiting while late tool settlement remains observed. Risk note: external side effects cannot be undone; the tool still receives the abort signal and its late promise is deliberately drained rather than delivered into the terminated run.User Impact
Users whose stalled turn is recovered now receive a clear interruption message instead of losing all visible trace of the turn. Plugin tools that honor cancellation can stop promptly, and tools that do not no longer hold the aborted turn open.
Evidence
Focused regression proof drives the real reply-run registry expiry path into the production runner:
expireStaleReplyOperation()recordsrun_stalledand aborts the same operation before both terminal projections run. The tool abort proof exerciseswrapToolWithAbortSignalwith a non-cooperative handler. Negative control used the real pre-fix sources viagit show HEAD^ -- <files>.Before (pre-fix abort wrapper): caller stays blocked after run abort while the non-cooperative tool keeps running.
Before (pre-fix reply runner): stalled recovery leaves an empty success outcome, so the channel-facing draft can disappear with no interruption notice.
After (fixed branch): abort returns in ~21ms, and stalled recovery surfaces the interruption payload.
Focused local verification:
What was not tested: no live Slack Socket Mode round-trip of a 15-minute blocked tool. The proven boundary is the channel-facing reply projection and tool-wrapper abort race before outbound send, which is where the silent draft deletion and blocked caller originate.
AI-assisted: Codex/Cursor; focused proof run manually.