6ed70700a0
answer() opened a fresh forward waiter but, unlike send(), never registered it in asyncTasksByWaiter. So when a worker chained a second fleet_ask inside the same resumed turn (before calling fleet_reply), markAsyncQuestion had no Task to re-associate, and answer() then completed the async ticket's future with the second QUESTION as if it were a terminal reply — fleet_poll reported FAILED while the worker was still alive and mid-conversation. Fix: register answer()'s waiter in asyncTasksByWaiter (mirroring send()) so a chained ask can re-arm the ticket under its new turnId, and guard answer()'s finishAsyncTask call the same way sendAsync's own lambda already does (skip on Outcome.QUESTION). Also drop the stale asyncTasksByTurn entry left behind when markAsyncQuestion re-arms a task under a new turnId, a leak the fix makes reachable for the first time. Reachability confirmed by driving the exact sequence through the public API (sendAsync -> ask -> answer -> ask again) in a new test; reverting the production change makes it fail with "expected: <ASKING> but was: <FAILED>", confirming it catches the regression.