zdd-3-swap
Zero-downtime deploys, plan 3 of 6: the swap (spec rev 17: §6.4, §7.1 canonical link, §7.4, §7.5 steps 1-8, §7.8, §7.10, §12).
Dormant. Plan 1's generations switch stays off until plan 5 wires CARLOS_SWAP. Nothing calls Service.Swap yet. Rebased onto main 412ca787, which has plans 1, 2 and 4.
What lands:
- Each activator entry gets an operation set (spawning, successor, retiring). stop() joins it before any terminal stop gives up the lease. A stop releases the lease only through releasable: no member, no stray sidecar, and the current generation proven terminated.
- Shutdown covers waking and swapping entries. It also covers failed wakes that are still retained.
- Admission goes through hostwrite. The ownership check (ownedLocked) runs at every exec, and one classifier (classifyStep/verdictOf) makes every refusal an abandonment, never a failure.
- The overlap swap: verified staged path, health on the generation's own socket, a 10 s canary settle, then the switch under the entry lock (AppSocket, canonical symlink, cache generation). The retiring generation then gets SIGTERM and actStopTimeout, and the parent limit is restored only after the child is proven empty.
- The hold swap: finishStop installs a waking entry pinned to the staged build. A refusal before the build executes counts as an abandonment.
- Legacy sidecars run the serving generation's staged build, and nothing forgets a sidecar until termination is proven.
- A retiring generation's schedule writes get 409, through a write fence that the switch takes.
- Nested generations mount the staged build. Root first validates it: the registry row's app, no symlinks, the digest, a regular file.
- Workers get numbered generations and are proven through their host cgroup.
- P2-13 (plan 2's parked High finding) is closed: a failed generation start whose kill can't be proven keeps its lease.
Reduced scope (ruling P2-9). Every claims-on launch on this base is closed (main a4cd3003), so claims-on swaps are refused before any raise or stop. The launch-independent fields that plan 5 uses are built. The claimed successor spawn, the entry's strict-parent lifecycle and the fallback re-Prepare are owed to whichever plan opens the isolated launch.
Flag-off changes, all ruled and all fail-closed:
- startSidecar and worker respawns check ownership at exec.
- Lease release uses a detached, bounded context.
- A failed or fenced wake whose process still runs keeps its lease, and Shutdown waits for it, within its budget. This fixes a bug that is also on main.
- A refused respawn child is kept until its exit is proven.
Simulation gate (final revision 4a134a2b): 3000 seeds at GOMAXPROCS=2, nice 19. The sweep passed. mutate.sh 300 gave 9 CAUGHT, 0 MISSED, 0 ERROR. In an earlier run of the same gate, M5's sweep panicked under the mutation; that was ruled a kill and Astra agreed. The strengthened sweep found two real production bugs, and both are fixed.
Review: per-task spec and quality reviews. Astra's final review went r1 ACCEPT WITH FIXES, r2 ACCEPT WITH FIXES, r3 ACCEPT. The findings are in docs/superpowers/plans/CODEX-FINDINGS-ZDD-IMPL-3*.md.
Owed before merge or before the flag goes on:
- Copy review of schedule.RetiredWriteMessage.
- Dev-box checks: the registry read under the real control unit, and StopGen(kill) of a never-loaded unit.
- Plan 5 must refuse to arm the flag on a box without cgroup delegation, and must capture staged identity for cold wakes and sidecars.
- F6 (deferred, pre-existing): flag-off, a retained wake is proven by its leader's exit only.
Discussions
- No discussions on this branch yet.
Tasks
- No tasks yet.
Activity
- claude agent, operated by paul@keymail.dev pushed 9737fd125 zdd plan 3: Astra scoped re-review r3 (ACCEPT)
- claude agent, operated by paul@keymail.dev pushed 4a134a2b2 zdd plan 3 final fix 2: a parent restore retry is joined by its entry's stop (R2-2)
- claude agent, operated by paul@keymail.dev pushed 895fc8602 zdd plan 3 final fix 2: a shed respawn child is kept until its exit is proven (R2-1)
- claude agent, operated by paul@keymail.dev pushed 37ffe34b5 zdd plan 3: Astra scoped re-review r2 (ACCEPT WITH FIXES; R2-1, R2-2)
- claude agent, operated by paul@keymail.dev pushed ef71d55de zdd plan 3 final fix: Lease keeps its own doc comment (comment-only)
- claude agent, operated by paul@keymail.dev pushed 89319f5d4 zdd plan 3 final fix: hold, sidecar-join and worker-proof tests use controlled ordering (T6, T7, T11)
- claude agent, operated by paul@keymail.dev pushed 25a338d51 zdd plan 3 final fix: barrier and settle tests wait on positive signals, not sleeps (T2, T5)
- claude agent, operated by paul@keymail.dev pushed 65375b092 zdd plan 3 final fix: root's staged-exe refusal removes the generation's launch file (T9)
- claude agent, operated by paul@keymail.dev pushed 2a4a29d92 zdd plan 3 final fix: retiring schedule writes go through a write fence the switch takes (F8, T8 nested gate)
- claude agent, operated by paul@keymail.dev pushed 2255d11a1 zdd plan 3 final fix: retained worker processes keep their build pinned until proven gone (F12, T11 shed-path test)
- claude agent, operated by paul@keymail.dev pushed 1f5de209b zdd plan 3 final fix: parent-limit repair obligations survive a partial raise and a failed restore (F11)
- claude agent, operated by paul@keymail.dev pushed fc14e7fd3 zdd plan 3 final fix: a worker respawn asks ownership at its exec and before its install (F1, F5/T11 log lines)
- claude agent, operated by paul@keymail.dev pushed 967812fc4 zdd plan 3 final fix: a hold checks its own lease and attempt at the exec; exec evidence is the spawn result (F7, F10)
- claude agent, operated by paul@keymail.dev pushed b19a0f016 zdd plan 3 final fix: every claims-backed swap is refused before its raise or stop (F9)
- claude agent, operated by paul@keymail.dev pushed 6fcc08ef3 zdd plan 3 final fix: unproven-start sentinels read as the fence to members; Shutdown's flag-off wait recorded (F5, T13)
- claude agent, operated by paul@keymail.dev pushed 29119d3d8 zdd plan 3 final fix: the sim's process death is one transition (F2)
- claude agent, operated by paul@keymail.dev pushed 31bf28b35 zdd plan 3 final fix: WIP mutate.sh integrity and scratch isolation (F3/F4, partial, untested; fixer cut off by a usage limit)
- claude agent, operated by paul@keymail.dev pushed a6ba2a095 zdd plan 3: Astra final review r1 (ACCEPT WITH FIXES)
- claude agent, operated by paul@keymail.dev pushed 5b9055bc0 zdd plan 3 task 13: fix round 2: keep the M6 marker text off the sim's comment
- claude agent, operated by paul@keymail.dev pushed 5cf536b13 zdd plan 3 task 2 fix: a failed wake never releases its lease while its process runs
- claude agent, operated by paul@keymail.dev pushed c25878d98 zdd plan 3 task 13: fix round 1: the sweep models unproven terminations; mutate.sh verdicts per run
- claude agent, operated by paul@keymail.dev pushed 502eb1190 zdd plan 3 task 2 fix: Shutdown waits for retained unproven wakes
- claude agent, operated by paul@keymail.dev pushed 5e8db7328 zdd plan 3 task 13: invariant simulation (I1-I3) and its mutation checks
- claude agent, operated by paul@keymail.dev pushed ecef92996 zdd plan 3 task 12: fix round 1: the spawning subtest uses a spawn that outlives cancellation
- claude agent, operated by paul@keymail.dev pushed 520d267b5 zdd plan 3 task 12: agent restart mid-swap and the never-healthy app, end to end
- claude agent, operated by paul@keymail.dev pushed e757c0853 zdd plan 3 task 11: worker children are numbered generations; a respawn joins the operation set
- claude agent, operated by paul@keymail.dev pushed f089cff93 zdd plan 3 task 10: fix round 1: a member's wake event reads as the claims refusal's cause, not its admission wrapper
- claude agent, operated by paul@keymail.dev pushed 86e307018 zdd plan 3 task 10: claims-on generation types and refusals; a retiring claimed generation drains first
- claude agent, operated by paul@keymail.dev pushed b7bd32027 zdd plan 3 task 9: nested generations mount the staged build; root validates it first
- claude agent, operated by paul@keymail.dev pushed 3ff569b88 zdd plan 3 task 8: a retiring generation's schedule writes get 409 after the switch