forked from unom/punktfunk
design/host-actions.md P2. The host has offered sleep/restart/shutdown since the previous commit; this is where a person can reach them. Every client's host menu grows the rows right where Wake host appears when the machine is asleep — finish on the TV, sleep the host from the same menu that woke it. One shared core: pf_client_core::host_actions holds the discovery read, the id-only invoke, and a process-wide TTL cache the console, the GTK page and the Windows tile all read, so three shells cannot end up disagreeing about what a host offers. Every shell warms it on a refresh tick it already had. Discovery is PRE-fetched, never fetched when a menu opens: the console screen holds a cloned row, and rows that appear under a cursor already moving are a hazard when two of them shut a machine down. For the same reason the console's armed state became WHICH row is armed rather than a bare flag — a flag let an arming press on Forget fire Shut down host. Restart and shut down confirm; sleep is reversible from the same menu, so it goes on one press. An action the host says it cannot run right now stays listed, disabled, and says why. Surfaces: console-UI rows + ConsoleCmd::HostAction with session and Android dispatch; GTK card menu (plus a card-level Toast) with an AlertDialog confirm; Windows tile menu, its label built and matched through one function so a menu whose rows outlived their handlers cannot run a different verb; Android touch home and Skia console; Apple host card and gamepad options. Unknown ids render from the host's own title on all of them — a later host action needs no client release to appear. Typed close: the Swift hostPower case and the Kotlin host-power token. Without them, sleeping your own host from the couch reads as a crash on those two clients.