"Pushing yesterday's binary to eight Macs is the worst outcome this tool can produce."
Why a Copy Is Enough
The family's Macs do not each build their own apps. One Mac builds, signs and installs; the others receive copies of that signed bundle. This works because of the bundle-signing track. Every app is signed with the one self-signed identity, so its designated requirement names the certificate rather than a hash, and a grant approved on a peer keeps matching every later copy. Peers need no Swift toolchain and no keychain import: codesign --verify checks the signature against the certificate embedded in the bundle, and the private key is only needed to sign. The deploy script therefore never builds anything. If it finds source newer than the installed bundle on the building Mac, it refuses, because the only thing worse than no deploy is a confident deploy of the wrong binary everywhere.
Preflight Before the First Peer
Everything that can disqualify a deploy is checked before any peer is touched: the installed bundle is newer than its sources, its signature verifies strictly, its requirement is certificate-pinned, and the LaunchAgent plist it declares exists. A bad build must fail on the building Mac, not after it has reached Mac number one while Mac number eight is still unverified.
On Each Peer: Stage, Verify, Stop, Swap, Verify
The bundle is copied to a hidden, space-free staging name beside /Applications. The space matters: the peers' openrsync split a remote destination with a space into two arguments and died. So the fleet deploy pins Homebrew's rsync, while the TestFlight export pins Apple's, for the opposite measured reason. Leftover staging from an interrupted run is cleared with find, not a shell glob, because in the peers' zsh an unmatched glob is a fatal error for the whole command, which silently skipped the cleanup in the normal case.
On the peer the staged bundle is verified, then the running app is stopped according to its quit policy. An ambient utility can be signalled. A document app must not be: SIGTERM never reaches applicationShouldTerminate, so the prose editor's refusal to quit during Korean input composition, a peer sync or an export, and its save-or-keep-draft decision, would all be skipped. It gets a polite quit through a direct Apple Event, which works from ssh, with a deadline, and a refusal becomes a skip. The terminal app is skipped while it is open, because a quit can end running jobs. Then the old bundle is moved aside, the new one moved in, verified at its final path, and the old one restored if anything failed.
Report What Is True Per App, Per Mac
Each app on each peer ends in one line. A LaunchAgent is loaded when someone is logged in at that Mac and staged when no one is. Permission state is read per service from the database that holds it: never asked, asked and not approved (which will not prompt again), granted, or unreadable. Manual steps are listed only for apps that actually need a grant, or the report sends the owner to six Macs to approve a prompt that will never appear, and "relaunch needed" is listed only when the deploy quit a running app that nothing else will bring back.