Public Access
The phone's notification kept saying '1 shell connected' after the shell was gone, and both close routes were at fault. A shell exiting on its own raised SessionEnded from inside its run's finally block — where the run task is by definition not yet complete, so the LiveSessionCount the keep-alive reads still counted the dead shell, and nothing fired later to correct it. A tab closed by hand announced nothing at all, by a recorded decision that assumed every subscriber was the closer; the keep-alive is not, and a close it never heard about left the notification claiming a shell over nothing. The end is now announced from a continuation after the run completes, and CloseSessionAsync announces after its own drain — every subscriber was already a reconcile-to-reality handler, so the echo the old remark feared costs nothing. Shutdown stays silent: it is dismantling the subscribers along with the sessions.