The old swap renamed live aside and staging in: between the two renames /aqua/dings/ answered 404 (a
concurrent reader got FileNotFoundError), a kill there left it missing until the next run, and a killed
run leaked .stage-* dirs. Now renameat2(RENAME_EXCHANGE) swaps live and staging in one syscall, a
per-target flock serialises publishers, and the next run deletes stale staging. test_interruption.py kills
the publisher at every filesystem mutation (audit-hook counted), races readers against swaps, and fails
against the old code.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>