The Owner Needed a Verb
An owner that keeps sessions alive across app quits also has to be replaced sometimes: a new build changes its protocol, a new input contract has to reach it. Until 2026-09-17 that replacement was a hand sequence — quit the app, ask launchd to restart the agent, check that a new owner answered, reopen the app. Dad asked the obvious question: why is this not in the app? Nothing forbade it any more. The previous lesson had just made every pane reconnect and reopen as a shell by itself. The one remaining fact was that a restart ends every job the owner holds. So it became a verb, and the verb asks first.
Consent Is a List
Shell → Restart Session Service… first asks the running owner for its sessions, every page of them, and shows what will end — workflow seats called out by name — before anything happens:
The wording is the product. Every job in these sessions ends, including running CLIs. Ordinary panes restore their saved launches as new processes in their folders, which may restart commands. Mobile devices reconnect to the new service. The button says the count it will end: Restart and End 3 Sessions. If the owner cannot be asked, the inventory is treated as unknown, never as empty, and the confirmation warns that live jobs may end. Only one restart can be in flight, including its question and its confirmation. It is not reachable from a sibling request, from a phone, or from an isolated test run. It is the operator's verb and nobody else's.
Re-register, Never Kickstart
The first build of the verb restarted the agent the way the hand sequence had: by asking launchd to kill and restart the loaded job. Dad's first press froze every pane and every new tab. Two causes were measured. launchd refused to run the new owner binary at all — "Launch Constraint Violation", then "Unable to get updated LWCR" every ten seconds — because the loaded job was still bound to the launch constraint recorded when it was first registered, and an install had replaced the signed binary underneath it. And the fallback shells opened while the owner was missing kept their keyboard pointed at the attachment they had just released, so they could not type either.
The repair, the same afternoon: the restart now unregisters the job, waits, registers it again from the installed property list (one retry), and waits up to thirty seconds for an owner with a new incarnation to answer. Panes show one reconnecting line, retry every second, and reopen in place. A pane that cannot reach the owner for three seconds asks launchd whether the job is running and re-registers it if not, at most once a minute — a job that is not running owns no PTYs, so that ends nothing. A pane still without an owner after about twenty seconds (five for a brand-new pane) runs a working app-owned shell, labeled. The fallback shells got their own keyboard back, and a test now types into them.
Who Is Allowed to Restart It
Only the operator. Installing a new app build never restarts a compatible owner; a deploy to other Macs never restarts one either. The installer re-registers an owner that is loaded but not running, and when a running owner is older than the bundle it compares build identities and prints a stale marker instead of acting. The family deploy reports that marker as a fact. The decision to end live jobs stays with the person who owns them.