- deploy.yml sleep-30 polling loop REPLACED: registers a gitea-identity
PROCESS_EVENT wait, yields in select() on the FIFO, resumes on the
ci.yml notify-event-bridge WAKE, then re-reads the canonical Gitea
verdict (deploy_qualify.py). Event payload is never completion truth.
- ci.yml gains notify-event-bridge (always(), best-effort): a red CI
wakes the waiter as loudly as a green one; bridge unreachable ->
watchdog recovery covers the lost wake.
- event_wait.py: register_process_wait gains provider/event_type/sha
identity (16E: ONE bridge primitive; builder + gitea are adapters);
open_fifo_reader + caller-owned fifo_fd close the 16Y#10 race (event
before waiter in select()); await_resume_event returns eof instead of
busy-looping on a caller-owned fd.
- ci_event_wait.py watchdog: failure DETECTOR only — liveness-gated
re-arm, one-shot authority recovery on lost events, truthful failure
when no verdict exists; timestamps emitted for the 16D latency proof.
- tests: 8 held-outs on the REAL daemon (shared wr_daemon fixture in
conftest — no duplicated helpers). Daemon-side: /process-event passes
through provider/event_type/sha (defaults preserve T15); lease_path
sanitizes slash-bearing session ids (resume delivery was impossible
for them — found live, fixed in daemon snapshot 79434e0).
Suite 1861 green; ratchets PASS; Henxels rc=0.