mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-26 06:15:13 +00:00
Regression: the drain IIFE finally (`drain.ts:263-271`) performed an unconditional `FOLLOWUP_QUEUES.delete(key)` + `clearFollowupDrainCallback(key)` using only the key, without checking whether the captured `queue` still matched the map entry. Under the `/stop` + immediate followup sequence, a late-returning D1 finally could delete the map entry for a fresh Q2 and orphan it until the next enqueue. Fix: only remove the map entry and drain callback when `FOLLOWUP_QUEUES.get(key) === queue`. Mirrors the identity pattern noted in `subagent-announce-queue.ts:62-64`. Adds `src/auto-reply/reply/queue/drain.identity-guard.test.ts` which uses real `enqueueFollowupRun` / `scheduleFollowupDrain` / `clearSessionQueues` (no module mocks) and a Deferred gate to park D1 inside `runFollowup`. The test uses `restartIfIdle=false` on the Q2 enqueue so D1's finally is the only mutator that can touch the map entry, producing deterministic pre/post-fix differentiation: pre-fix : get(key) === undefined (Q2 orphaned), depth === 0 post-fix : get(key) === Q2, depth === 1 AI-assisted (fully tested). 1082 auto-reply/reply tests pass, pnpm check + pnpm build clean.