Skip to content

fix: avoid replaying channel restart recovery turns#74687

Closed
levineam wants to merge 1 commit into
openclaw:mainfrom
levineam:fix/channel-restart-recovery
Closed

fix: avoid replaying channel restart recovery turns#74687
levineam wants to merge 1 commit into
openclaw:mainfrom
levineam:fix/channel-restart-recovery

Conversation

@levineam

Copy link
Copy Markdown

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: restart-aborted main-session recovery can auto-replay a synthetic recovery turn into channel-backed sessions.
  • Why it matters: channel-backed sessions have external delivery state; hidden replay can re-enter delivery/recovery paths after a restart when manual recovery is safer.
  • What changed: channel-backed restart-aborted sessions are marked failed for manual recovery instead of replaying a synthetic recovery turn.
  • What did NOT change (scope boundary): restart recovery for non-channel resumable main sessions remains intact; no config, cron, memory, or QMD behavior is changed.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause (if applicable)

  • Root cause: main-session restart recovery treats channel-backed sessions like ordinary resumable local sessions and may enqueue a synthetic hidden agent turn after restart. For externally delivered sessions, that can re-enter channel/session delivery state when the safer behavior is explicit manual recovery.
  • Missing detection / guardrail: coverage did not assert that channel-backed restart-aborted sessions avoid synthetic replay.
  • Contributing context (if known): externally backed sessions carry channel metadata and delivery context that should not be implicitly retried as hidden local recovery turns.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/agents/main-session-restart-recovery.test.ts
  • Scenario the test should lock in: Discord/channel-backed restart-aborted sessions are marked failed for manual recovery and do not enqueue synthetic recovery turns; non-channel restart recovery remains resumable.
  • Why this is the smallest reliable guardrail: the behavior is decided in restart recovery before any external channel send is attempted.
  • Existing test that already covers this (if any): existing restart-recovery tests cover resumable non-channel behavior; this PR adds channel-backed coverage.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

Channel-backed sessions that were interrupted during restart recovery now require manual recovery instead of hidden automatic replay. Non-channel resumable recovery behavior is unchanged.

Diagram (if applicable)

Before:
[channel-backed interrupted session] -> [restart recovery] -> [synthetic hidden agent turn] -> [delivery/session path re-entered]

After:
[channel-backed interrupted session] -> [restart recovery] -> [failed/manual recovery marker]

Non-channel:
[local resumable interrupted session] -> [restart recovery] -> [existing synthetic recovery path]

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local gateway / Node runtime
  • Model/provider: N/A
  • Integration/channel (if any): Discord-backed channel session
  • Relevant config (redacted): channel-backed main session with delivery context

Steps

  1. Have a channel-backed main session that is restart-aborted.
  2. Restart/reopen through main-session recovery.
  3. Observe whether recovery enqueues a synthetic hidden agent turn or marks the session for manual recovery.

Expected

  • Channel-backed restart-aborted sessions should not auto-replay a synthetic recovery turn.
  • Non-channel resumable sessions should keep existing restart recovery behavior.

Actual

  • Before this PR, channel-backed sessions could follow the same synthetic recovery path as non-channel sessions.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Verification run locally:

  • node scripts/run-vitest.mjs run --config test/vitest/vitest.agents-core.config.ts src/agents/main-session-restart-recovery.test.ts --maxWorkers=1 --reporter dot — 6 passed
  • node scripts/run-vitest.mjs run --config test/vitest/vitest.agents-core.config.ts src/agents/session-write-lock.test.ts --maxWorkers=1 --reporter dot — 24 passed
  • pnpm exec oxlint src/agents/main-session-restart-recovery.ts src/agents/main-session-restart-recovery.test.ts — 0 warnings/errors

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: channel-backed restart-aborted recovery path; non-channel resumable recovery path; nearby session write-lock tests.
  • Edge cases checked: restart-aborted sessions with channel metadata; existing non-channel resumable recovery behavior.
  • What you did not verify: full live Discord end-to-end restart recovery in production.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: some channel-backed interrupted sessions that previously attempted automatic recovery will now require manual recovery.
    • Mitigation: this is intentional for externally delivered sessions; non-channel resumable sessions keep automatic recovery.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels Apr 30, 2026
@clawsweeper

clawsweeper Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as superseded: merged restart-recovery work now handles the same channel restart problem with captured delivery contexts and visible failure notices, while this branch would conflict with current main and reintroduce a broad fail-closed policy.

Canonical path: Keep the released captured-route restart recovery path from #86089, and route any remaining storage or migration cleanup through the newer restart-recovery route work instead of reviving this fail-closed branch.

So I’m closing this here and keeping the remaining discussion on #86089.

Review details

Best possible solution:

Keep the released captured-route restart recovery path from #86089, and route any remaining storage or migration cleanup through the newer restart-recovery route work instead of reviving this fail-closed branch.

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

Yes. Source inspection on current main shows the restart-recovery decision path and tests cover captured-route delivery versus historical-route non-inference; I did not run tests because this was a read-only review.

Is this the best way to solve the issue?

No. The branch's broad channel-backed failure guard is no longer the best fix because current main persists explicit recovery route context, avoids historical route inference, and sends visible notices for unresumable cases.

Security review:

Security review cleared: The diff only changes agent restart-recovery logic and a unit test; I found no concrete security or supply-chain regression.

AGENTS.md: found and applied where relevant.

What I checked:

Likely related people:

  • samzong: Authored the merged restart-recovery delivery PR that supersedes this branch and owns the current captured-route behavior. (role: feature owner; confidence: high; commits: 4decdf6245a1, eeea727e6ab4; files: src/agents/main-session-restart-recovery.ts, src/agents/main-session-restart-recovery.test.ts)
  • steipete: Co-authored the superseding restart-recovery work, contributed follow-up route-preservation commits, and opened the current SQLite route-storage follow-up. (role: recent adjacent contributor; confidence: high; commits: 4decdf6245a1, 6cb06f5fbcf5, e2b854bb18cf; files: src/agents/main-session-restart-recovery.ts, src/auto-reply/reply/agent-runner.ts, src/auto-reply/reply/effective-reply-route.ts)
  • MonkeyLeeT: Authored the merged external-route preservation work that also covers restart and pending-final recovery context handling. (role: recent adjacent contributor; confidence: medium; commits: 6cb06f5fbcf5, c7ab20b03aa5, 2cd60785966a; files: src/auto-reply/reply/effective-reply-route.ts, src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts)

Codex review notes: model internal, reasoning high; reviewed against 66880a5d736c; fix evidence: release v2026.6.6, commit 4decdf6245a1.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added stale Marked as stale due to inactivity triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 30, 2026
@clawsweeper clawsweeper Bot added the rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. label May 30, 2026
@barnacle-openclaw barnacle-openclaw Bot removed the stale Marked as stale due to inactivity label May 30, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Jun 14, 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. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 14, 2026
@clawsweeper

clawsweeper Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper applied the proposed close for this PR.

  • Action: closed this PR.
  • Close reason: duplicate or superseded.
  • Evidence: durable ClawSweeper review.
  • Coverage proof: PR B clearly supersedes PR A's useful intent with the merged and released canonical implementation for the same restart-recovery route problem. PR A's remaining differences are the rejected broad fail-closed policy, not material work that still needs separate review. Covering PR: [Fix] Deliver restart recovery replies #86089.

@clawsweeper clawsweeper Bot closed this Jun 14, 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: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: S stale Marked as stale due to inactivity status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant