cbf97c6077
Second review round. The first two are regressions from the first round. The forced exit flush added fifteen seconds to host shutdown. Node re-emits beforeExit whenever the handler schedules async work, so an unconditional flush(true) looped until the five-attempt budget was spent, and against the real 3s delivery timeout that is 15s added to the shutdown of whatever editor or CLI is hosting this. The backoff used to end that loop after one attempt; removing it for the forced path removed the only thing bounding it. Measured at 15008ms, now 6001ms with a one-shot latch, and 12ms when delivery is healthy, which is the only case most people ever see. openclaw deleted a legacy account before it had anything to replace it with. An install predating keyFingerprint has an email and no fingerprint, so the comparison failed and clearResolvedAccount() ran immediately; if the re-resolve then failed because the user was offline the email was gone from disk for good, and the per-key latch was already set so nothing retried. Now cleared only when a real fingerprint disagrees, which is the same trade the Python core makes and documents: verify, and keep what you have until the verification succeeds. The latch is released on a failed lookup so the next capture tries again. The overflow test did not exercise the path it is named for: with only two events captured the re-queue had an empty queue to merge into, so the slice on the failure path never ran, and that is the half deciding which end gets dropped. It now fills past the cap before flushing and asserts the exact surviving order. core 36, openclaw 432, opencode 35, deepseek 47. Wire e2e 9 of 9 and identity e2e 7 of 7 still pass against a real local server. Claude-Session: https://claude.ai/code/session_01C7tEmH86HAr7GoAAKCEHZb