STATUS: RULE RATIFIED by David (2026-09-13) — implementation unblocked; see the decision comment below.
Why
pad-run.sh (#53) prevents collisions but cannot prevent a stranded lock: a SIGKILLed run leaves the lock on the device (confirmed by doing it in #53's smoke). "Never clear another handle's lock" then has no recovery path. Today's lesson (2026-09-12) is that age alone is never sufficient: a 3.5-hour-old lock that three sessions judged dead was live, on a different device that had been swapped onto the cable.
Proposed rule (recommended, awaiting decision)
A foreign lock may be cleared only when all hold, in this order:
- Device identity verified by serial (
PAD_SERIAL / adb devices -l), so the lock and the evidence below come from the same unit. Already mechanical: pad-run.sh refuses an unattached PAD_SERIAL and an ambiguous multi-device attach.
- No session answers to the handle:
ListAgents on the attached box shows no owner, and a message to any plausible owner goes unanswered for 10 minutes. Liveness of the holder session is the signal — never liveness of a process on the device. On the phone the runtime freezes within a minute of idle and stays frozen: alive, with a ServiceRecord, doing nothing.
- No device activity:
dumpsys usagestats shows no ACTIVITY_RESUMED row and the lock file's mtime is unchanged for 30 minutes past the lock's own stated duration. Already mechanical: pad-run.sh takes that snapshot; it survives logcat rolling. Normalise clocks before comparing: usagestats rows are device-local time, lock timestamps are UTC, this box is UTC-7 — compare epoch seconds (stat -c %Y, date +%s), never the printed strings.
- The clearer posts the old line verbatim (bus / issue) and takes the lock in the same command, purpose
cleared stale <handle> <ts>.
What would be built, once ratified
pad-lock.sh stale-check [<handle>] prints CLEARABLE / NOT CLEARABLE: <which step failed> (exit 0/1), implementing steps 1 and 3 mechanically (durations in the lock line should be written in a parseable form, e.g. ~15min, treated as 30 min when absent) and spelling out steps 2 and 4 for the human/agent. pad-lock.sh clear-stale <handle> performs step 4 only when stale-check said CLEARABLE, refusing otherwise.
Not in scope
Any automatic clearing. The point is a decision procedure with evidence, not a timer.
Refs: #52, #53, runtime#1454 (the measurement withdrawn after the 2026-09-12 collision).
Why
pad-run.sh(#53) prevents collisions but cannot prevent a stranded lock: a SIGKILLed run leaves the lock on the device (confirmed by doing it in #53's smoke). "Never clear another handle's lock" then has no recovery path. Today's lesson (2026-09-12) is that age alone is never sufficient: a 3.5-hour-old lock that three sessions judged dead was live, on a different device that had been swapped onto the cable.Proposed rule (recommended, awaiting decision)
A foreign lock may be cleared only when all hold, in this order:
PAD_SERIAL/adb devices -l), so the lock and the evidence below come from the same unit. Already mechanical:pad-run.shrefuses an unattachedPAD_SERIALand an ambiguous multi-device attach.ListAgentson the attached box shows no owner, and a message to any plausible owner goes unanswered for 10 minutes. Liveness of the holder session is the signal — never liveness of a process on the device. On the phone the runtime freezes within a minute of idle and stays frozen: alive, with a ServiceRecord, doing nothing.dumpsys usagestatsshows noACTIVITY_RESUMEDrow and the lock file's mtime is unchanged for 30 minutes past the lock's own stated duration. Already mechanical:pad-run.shtakes that snapshot; it surviveslogcatrolling. Normalise clocks before comparing:usagestatsrows are device-local time, lock timestamps are UTC, this box is UTC-7 — compare epoch seconds (stat -c %Y,date +%s), never the printed strings.cleared stale <handle> <ts>.What would be built, once ratified
pad-lock.sh stale-check [<handle>]printsCLEARABLE/NOT CLEARABLE: <which step failed>(exit 0/1), implementing steps 1 and 3 mechanically (durations in the lock line should be written in a parseable form, e.g.~15min, treated as 30 min when absent) and spelling out steps 2 and 4 for the human/agent.pad-lock.sh clear-stale <handle>performs step 4 only whenstale-checksaid CLEARABLE, refusing otherwise.Not in scope
Any automatic clearing. The point is a decision procedure with evidence, not a timer.
Refs: #52, #53, runtime#1454 (the measurement withdrawn after the 2026-09-12 collision).