carlos / platform Public

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.
Commits 39
Discussions 0 0 open
Tasks 0/0 done

Discussions

  • No discussions on this branch yet.

Tasks

  • No tasks yet.

Activity