Raised by Codex on #91 (round 4, P1) and capped there by the owner (2026-09-09): plan 2 ships the phase-boundary renewals and the in-phase heartbeat on the upgrader's filters (SA#80), and this issue records what those cannot cover.
The gap. Aura_Worker_Magic_Link::take_claim() stores fence|timestamp, and a seizer treats a claim older than ITS window (ten minutes, passed by every caller) as dead. The holder can move the timestamp — refresh_claim() between phases, and from heartbeat_during()'s upgrader filter callbacks inside a phase — but PHP is single-threaded: nothing runs while one blocking call (download_url(), unzip_file(), copy_dir(), ZipArchive::extractTo()) is in progress. A single such call that lasts longer than the window leaves the lease seizable, and a successor can start replacing the same directory while the first request is still inside its call.
Why it is a residual, not a defect being shipped. The window exists precisely to reclaim dead holders, and max_execution_time bounds a request well under ten minutes on every host in the fleet; SiteAgent's own zip is ~1 MB. #78 round 25 (SA#80's origin) accepted the same residual for the self-update's install(). After plan 2 the outlived request also STOPS on the first check that fails (no restore, no verdict, no rollback over the successor's files — #91 round 3), so the cost of the race is bounded to two installs of the same build, never a rollback over a newer one.
The fix, when it is worth it. A lease with a holder-set expiry: the value becomes fence|expires_at, the holder sets expires_at = now + min( max_execution_time, HARD_CAP ) before each blocking phase, and a seizer takes over only past expires_at — the claim cannot expire during an operation the holder has declared. This changes the claim primitive that the connect (#434) and the site claim share (take_claim / refresh_claim / release_claim / the regex-matched $wpdb stubs), so it is its own change with its own review, not a task in plan 2.
Refs: #80, #91 discussion r3971802169, plan docs/superpowers/plans/2026-09-09-siteagent-2.17-agent-code.md Task 4.
Raised by Codex on #91 (round 4, P1) and capped there by the owner (2026-09-09): plan 2 ships the phase-boundary renewals and the in-phase heartbeat on the upgrader's filters (SA#80), and this issue records what those cannot cover.
The gap.
Aura_Worker_Magic_Link::take_claim()storesfence|timestamp, and a seizer treats a claim older than ITS window (ten minutes, passed by every caller) as dead. The holder can move the timestamp —refresh_claim()between phases, and fromheartbeat_during()'s upgrader filter callbacks inside a phase — but PHP is single-threaded: nothing runs while one blocking call (download_url(),unzip_file(),copy_dir(),ZipArchive::extractTo()) is in progress. A single such call that lasts longer than the window leaves the lease seizable, and a successor can start replacing the same directory while the first request is still inside its call.Why it is a residual, not a defect being shipped. The window exists precisely to reclaim dead holders, and
max_execution_timebounds a request well under ten minutes on every host in the fleet; SiteAgent's own zip is ~1 MB. #78 round 25 (SA#80's origin) accepted the same residual for the self-update'sinstall(). After plan 2 the outlived request also STOPS on the first check that fails (no restore, no verdict, no rollback over the successor's files — #91 round 3), so the cost of the race is bounded to two installs of the same build, never a rollback over a newer one.The fix, when it is worth it. A lease with a holder-set expiry: the value becomes
fence|expires_at, the holder setsexpires_at = now + min( max_execution_time, HARD_CAP )before each blocking phase, and a seizer takes over only pastexpires_at— the claim cannot expire during an operation the holder has declared. This changes the claim primitive that the connect (#434) and the site claim share (take_claim/refresh_claim/release_claim/ the regex-matched$wpdbstubs), so it is its own change with its own review, not a task in plan 2.Refs: #80, #91 discussion
r3971802169, plandocs/superpowers/plans/2026-09-09-siteagent-2.17-agent-code.mdTask 4.