fix #91420: [Bug]: Delivery retry loop corrupts active sessions (R-004) β retry selector bypasses delivery.mode=none#91453
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 11, 2026, 5:56 AM ET / 09:56 UTC. Summary PR surface: Source +31, Tests +185. Total +216 across 2 files. Reproducibility: no. live current-main reproduction was run in this read-only review. The issue is source-reproducible from current main's broad fallback path plus the reporter attachment, and the PR adds focused before/after-style regression coverage for the routing boundary. Review metrics: none identified. 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 detailsBest possible solution: Land the narrow sessions_send routing fix after maintainers accept the compatibility tradeoff and CI is acceptable, then close the linked issue after merge. Do we have a high-confidence way to reproduce the issue? No live current-main reproduction was run in this read-only review. The issue is source-reproducible from current main's broad fallback path plus the reporter attachment, and the PR adds focused before/after-style regression coverage for the routing boundary. Is this the best way to solve the issue? Yes, this appears to be the best fix shape: it stays inside sessions_send, replaces broad suffix stripping with existing session-key helpers, preserves the shipped cron fallback, and avoids adding config or removing documented A2A behavior. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 1e878dde7c3c. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +31, Tests +185. Total +216 across 2 files. View PR surface stats
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
|
|
@clawsweeper re-review |
|
π¦π§Ή I asked ClawSweeper to review this item again. Re-review progress:
|
78d6af5 to
cefa507
Compare
vincentkoc
left a comment
There was a problem hiding this comment.
No blocking findings.
This is the right owner-boundary fix: sessions_send now uses the active-run queue only for run-scoped targets, keeps the existing stranded cron-run fallback for structurally valid cron run keys, and reports unsafe queue rejections instead of rerouting them through durable sessions. Ordinary active sessions stay gateway-routed.
Best-fix verdict: best. I checked the sessions_send owner path, the run-scoped key helpers, active-run delivery fallback behavior, and adjacent session-tool regression coverage. Removing all fallback would break the shipped cron pingback recovery path; moving this into the endpoint/session store would leave the retry selector bug in the tool path.
Verification:
git diff --check origin/main...HEADnode_modules/.bin/oxfmt --check src/agents/openclaw-tools.sessions.test.ts src/agents/tools/sessions-send-tool.tsnode scripts/run-oxlint.mjs src/agents/openclaw-tools.sessions.test.ts src/agents/tools/sessions-send-tool.ts- autoreview: clean after rebase
- Crabbox Azure
cbx_737f52db0db0/ runrun_ddbe1aea4671:node scripts/run-vitest.mjs src/agents/openclaw-tools.sessions.test.tsβ 34 passed - GitHub CI on exact head
cefa507ed4ee4d69b8be8d43ae7292f30b1cc7e9: green; transient Labeler 504 was rerun and passed
Summary
sessions_sendretry behavior instead of removing every durable retry path.runtime_rejected, source reply delivery mode mismatch, compacting runs, and non-cron run-looking keys now surface the queue error on the original target.agentpath.Linked context
Closes #91420
Related: #86638 shipped the stranded cron pingback fallback that this patch keeps, but now under a narrower session-key and queue-reason gate.
Was this requested by a maintainer or owner? No direct maintainer request; this follows the open bug report plus bot/review feedback asking for issue-specific proof and a safer retry design if #86638 remains part of the runtime contract.
Maintainer review notes
sessions_sendactive-run retry routing plus focused regression coverage, and the runtime proof exercises the blocked unsafe path, the preserved safe cron fallback, and the ordinary active-session gateway path.agentrun, so a failed run-scoped delivery could silently cross from active runtime state into a durable session.agentpath, and only the Fix run-scoped sessions_send pingback fallbackΒ #86638 stranded cron case has a durable parent contract, so fallback is now gated by structural cron key parsing and safe queue reasons.sessions_send, ordinary active-session gatewayagentrouting, successful run-scoped active-run queue delivery, transcript-commit best-effort retry, documented A2A reply-back behavior, channel delivery policy, session visibility, provider routing, schema, config, defaults, and migrations.sessions_send; it reusesparseAgentSessionKey()/isCronRunSessionKey()instead of restoring broad:run:<id>suffix stripping.src/agents/openclaw-tools.sessions.test.ts; adjacent guardrails also runsrc/agents/embedded-agent-runner/runs.test.tsandsrc/agents/tools/sessions-send-tool.a2a.test.ts.agentcall; safe stranded cron delivery falls back only toagent:leasing-ops:cron:monthly-utility; ordinary active session targets still use the gatewayagentpath and do not fail on source reply mode mismatch.not_streamingorno_active_runqueue outcomes.:run:keys instead of silently starting a new durable-session agent run.Real behavior proof (required for external PRs)
Behavior or issue addressed: unsafe rejected run-scoped active-run
sessions_senddelivery no longer falls back through a durable session key, the Fix run-scoped sessions_send pingback fallbackΒ #86638 stranded cron run case still falls back to the durable cron parent, and ordinary active session targets remain gateway-routed instead of being steered through the active queue.Real environment tested: local patched OpenClaw runtime with isolated
OPENCLAW_HOME; the issue-specific proof invokes the productionsessions_sendtool against the active embedded-run queue registry.Exact steps or command run after this patch:
sessions_sendwithtimeoutSeconds: 0for all three routing boundaries.Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output):
Copied console output from the isolated issue-path proof harness:
{ "proof": "issue-91420-safe-sessions-send-run-scoped-delivery", "invocation": "production sessions_send tool with active embedded-run queue registry", "scenarios": { "unsafeRuntimeRejected": { "status": "error", "sessionKey": "agent:leasing-ops:cron:monthly-utility:run:run-fast", "error": "queue_message_failed reason=runtime_rejected sessionId=caller-active-session gatewayHealth=live error=active session ended before queued steering message was committed", "queueMessageCalls": 1, "gatewayAgentFallbackCalls": 0, "assertions": { "explicitRuntimeRejectedError": true, "originalRunScopedSessionPreserved": true, "noDurableAgentFallback": true } }, "safeStrandedCronFallback": { "status": "accepted", "runId": "durable-cron-parent-run", "reportedSessionKey": "agent:leasing-ops:cron:monthly-utility:run:run-fast", "durableCronParentKey": "agent:leasing-ops:cron:monthly-utility", "queueMessageCalls": 0, "gatewayAgentFallbackCalls": 1, "gatewayAgentSessionKeys": [ "agent:leasing-ops:cron:monthly-utility" ], "assertions": { "acceptedThroughDurableCronParent": true, "originalRunScopedSessionReported": true, "onlyDurableCronParentUsed": true, "activeQueueNotInvokedAfterNotStreaming": true } }, "ordinaryActiveGatewayPath": { "status": "accepted", "runId": "ordinary-agent-run", "reportedSessionKey": "agent:main:main", "queueMessageCalls": 0, "gatewayAgentCalls": 1, "gatewayAgentSessionKeys": [ "agent:main:main" ], "assertions": { "acceptedThroughGatewayAgent": true, "ordinarySessionPreserved": true, "noActiveQueueDelivery": true, "onlyOrdinaryGatewayAgentUsed": true, "noSourceReplyModeMismatch": true } } }, "assertions": { "unsafeRuntimeRejectedDoesNotFallback": true, "safeStrandedCronFallbackPreserved": true, "ordinaryActiveSessionsStayGatewayRouted": true } }Observed result after fix: the unsafe runtime-rejected scenario returns
status="error"withqueue_message_failed reason=runtime_rejectedand recordsgatewayAgentFallbackCalls=0; the safe stranded cron scenario returnsstatus="accepted"and records exactly one gatewayagentcall toagent:leasing-ops:cron:monthly-utility; the ordinary active-session scenario returnsstatus="accepted", recordsqueueMessageCalls=0, and sends exactly one gatewayagentcall toagent:main:main.What was not tested: the reporter's full macOS 16-agent fleet, external channel accounts, and the intermittent production corruption loop.
Proof limitations or environment constraints: the deterministic proof uses an in-process local runtime harness because the public gateway HTTP/RPC API does not expose a stable way to force active queue
runtime_rejectedornot_streamingon demand; it exercises the productionsessions_sendtool and active-run queue registry, but it is not a live reproduction of the reporter's full external fleet.Before evidence (optional but encouraged): before the production change in this iteration, the new focused stranded-cron regression failed with
AssertionError: expected 'error' to be 'accepted', proving the safe Fix run-scoped sessions_send pingback fallbackΒ #86638 fallback had not yet been restored.Tests and validation
Commands run:
Regression coverage added or updated:
runtime_rejectedactive delivery test requiring an explicit error and no durableagentcall.agentrouting and no source reply mode mismatch failure.What failed before this fix:
Risk checklist
Did user-visible behavior change? (
Yes/No) Yes β unsafe rejected run-scoped active delivery now reports an error instead of silently retrying through a durable session; ordinary active session targets keep the existing gatewayagentpath; safe stranded cron pingback fallback remains accepted.Did config, environment, or migration behavior change? (
Yes/No) No.Did security, auth, secrets, network, or tool execution behavior change? (
Yes/No) Yes β tool execution routing is narrowed so failed active-run queue delivery cannot use a persistent session as an implicit relay except for the explicitly preserved durable cron parent path.What is the highest-risk area? Existing workflows that depended on broad durable-session fallback for non-cron or runtime-rejected active-run sends will now see explicit send errors.
How is that risk mitigated? The change only affects rejected run-scoped active queue delivery; normal direct
sessions_send, ordinary active-session gateway routing, successful run-scoped active-run queue delivery, transcript-commit best-effort delivery, documented A2A reply-back behavior, and the #86638 stranded cron fallback are covered by focused tests and runtime proof.Current review state
What is the next action? Ready for CI and bot re-review after the update-branch refresh and round-two author fix.
What is still waiting on author, maintainer, CI, or external proof? CI and ClawSweeper need to consume this updated commit and PR body. External reporter-environment proof is not available from this local setup; the maintainer decision is whether this narrower retry contract correctly balances #91420's session boundary against #86638's stranded cron pingback fallback while preserving ordinary active-session gateway routing.
Which bot or reviewer comments were addressed?
status: β³ waiting on authorlabel was caused by the ordinary active-session compatibility finding, not by missing proof.agentpath without source reply delivery mode mismatch.src/agents/openclaw-tools.sessions.test.tson the updated PR head; result: 34 passed.src/agents/embedded-agent-runner/runs.test.tsandsrc/agents/tools/sessions-send-tool.a2a.test.tson the updated PR head; result: 44 passed.