`adb install -r` preserves app data and phone_deploy already refuses every
path that would not, but "preserved" is a property of the happy path -- a
failed install or a later wipe leaves unpublished entries existing nowhere
else. The log is CRDT-synced precisely so a recoverable copy exists, so the
deploy now checks that one does before touching the device.
The obvious device-side signal does not work and would be a gate that can
never pass: the app records a successful tick through SyncHealth, which writes
to SharedPreferences (app-private, unreadable over ADB on a release build),
and it only writes to logcat when a sync *fails*. So the check is remote-side
-- pull the shared log and assert it holds recent entries, which answers "is
there a copy off the device" directly.
Advisory by default; SYNC_GATE_STRICT=1 makes it block (exit 38). A network
outage must not stop a fix reaching the phone.
The shell half lives in ~/.claude/scripts/lib/phone_deploy_sync.sh. Verified
against the real phone: passes when a peer is current, skips cleanly for an
unsynced or not-yet-installed app, and blocks with exit 38 in strict mode.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQpCiPaSbyRpwsLkH3dgsX