Commit Graph
6 Commits
Author SHA1 Message Date
Nick 9731181a6b fix(tests): respawn the bridge daemon on mid-test death (root-caused)
deploy / deploy (push) Skipped
CI Pipeline / go-surface (push) Successful in 5s
CI Pipeline / best-practices (push) Successful in 1s
CI Pipeline / documentation (push) Successful in 2s
CI Pipeline / type-check (push) Successful in 27s
CI Pipeline / lint (push) Successful in 36s
CI Pipeline / canary (push) Successful in 42s
CI Pipeline / gitea-offline (push) Successful in 13s
CI Pipeline / go-surface (pull_request) Successful in 3s
CI Pipeline / lint (pull_request) Successful in 34s
CI Pipeline / best-practices (pull_request) Successful in 1s
CI Pipeline / documentation (pull_request) Successful in 2s
CI Pipeline / canary (pull_request) Successful in 36s
CI Pipeline / gitea-offline (pull_request) Successful in 12s
CI Pipeline / type-check (pull_request) Successful in 27s
Spec gate (headless) / spec-gate (pull_request) Successful in 4s
CI Pipeline / unit-tests (push) Failing after 4m48s
CI Pipeline / required-checks (push) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 2s
CI Pipeline / unit-tests (pull_request) Failing after 4m46s
CI Pipeline / required-checks (pull_request) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (pull_request) Successful in 2s
The hardening's own diagnostic nailed it (run 18359): the daemon answers
/health at fixture setup, then dies SILENTLY mid-test (alive=False,
out='') on the saturated runner — host shows 20GB swap in use, and a
silent kill with zero output is the memory-pressure signature, not a
race. A retry can never survive a dead process.

Fix: registrations are file-backed under WR_ROOT, so a respawned daemon
resumes the same state — post_event now ensures liveness before each
attempt (respawn on death) and _spawn is the single spawn path (init's
T21.5 fresh-port retry preserved). Bridge suites 19/19, ruff clean.
2026-10-04 12:30:37 +01:00
Nick 544c19719e fix(tests): harden the bridge daemon post_event against load-dependent refusal
deploy / deploy (push) Skipped
CI Pipeline / lint (push) Successful in 34s
CI Pipeline / go-surface (push) Successful in 2s
CI Pipeline / canary (push) Successful in 38s
CI Pipeline / best-practices (push) Successful in 2s
CI Pipeline / documentation (push) Successful in 1s
CI Pipeline / type-check (push) Successful in 26s
CI Pipeline / gitea-offline (push) Successful in 12s
CI Pipeline / lint (pull_request) Successful in 33s
CI Pipeline / go-surface (pull_request) Successful in 3s
CI Pipeline / canary (pull_request) Successful in 38s
CI Pipeline / best-practices (pull_request) Successful in 2s
CI Pipeline / documentation (pull_request) Successful in 2s
CI Pipeline / gitea-offline (pull_request) Successful in 13s
Spec gate (headless) / spec-gate (pull_request) Successful in 4s
CI Pipeline / type-check (pull_request) Successful in 27s
CI Pipeline / unit-tests (push) Failing after 4m47s
CI Pipeline / required-checks (push) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 2s
CI Pipeline / unit-tests (pull_request) Failing after 4m45s
CI Pipeline / required-checks (pull_request) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (pull_request) Successful in 2s
Observed 2026-10-04 (runs 18340/18342/18346/18347): the fixture's daemon
answers /health at setup, then a POST lands ECONNREFUSED under runner
load — the twin-failure pattern across two commits while sibling runs
passed. Harness-side hardening per the intermittent-defect law:
post_event retries twice with a beat, and on final failure dumps the
daemon's captured output (alive state + log tail) so the next diagnosis
starts from evidence. Bridge suite 11/11 locally, ruff clean.
2026-10-04 12:18:28 +01:00
Nick 756ebe6201 fix(t21.5): pyright-clean provider loader; harden test Daemon fixture against bind races (retry on fresh ephemeral port)
CI Pipeline / best-practices (push) Successful in 19s
CI Pipeline / documentation (push) Successful in 6s
CI Pipeline / canary (push) Successful in 45s
CI Pipeline / lint (push) Successful in 1m1s
CI Pipeline / gitea-offline (push) Successful in 15s
CI Pipeline / type-check (push) Failing after 34s
CI Pipeline / lint (pull_request) Successful in 45s
CI Pipeline / canary (pull_request) Successful in 41s
CI Pipeline / best-practices (pull_request) Successful in 6s
CI Pipeline / documentation (pull_request) Successful in 8s
CI Pipeline / gitea-offline (pull_request) Successful in 24s
CI Pipeline / type-check (pull_request) Failing after 33s
deploy / deploy (push) Skipped
Spec gate (headless) / spec-gate (pull_request) Successful in 17s
CI Pipeline / unit-tests (push) Failing after 3m23s
CI Pipeline / required-checks (push) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 6s
CI Pipeline / unit-tests (pull_request) Failing after 3m18s
CI Pipeline / required-checks (pull_request) Failing after 1s
CI Pipeline / CI Pipeline / notify-event-bridge (pull_request) Successful in 7s
2026-09-17 13:06:17 +01:00
Nick e1a71efeb9 feat(ci): event-driven CI qualification wait over the existing W/R bridge (T16 16C/16D/16E)
CI Pipeline / best-practices (push) Successful in 9s
CI Pipeline / documentation (push) Successful in 6s
CI Pipeline / canary (push) Successful in 37s
CI Pipeline / lint (push) Successful in 46s
Auto-version and Release / release (push) Successful in 53s
deploy / deploy (push) Failing after 16s
CI Pipeline / unit-tests (push) Successful in 2m50s
CI Pipeline / gitea-offline (push) Successful in 15s
CI Pipeline / type-check (push) Successful in 26s
CI Pipeline / required-checks (push) Successful in 1s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Successful in 4s
- 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.
2026-09-15 16:26:54 +01:00
Nick fd5f31bba2 fix(scaffolding): §15D tests use ephemeral ports, not fixed 8793
CI Pipeline / best-practices (push) Successful in 10s
CI Pipeline / documentation (push) Successful in 4s
CI Pipeline / lint (push) Successful in 46s
Auto-version and Release / release (push) Successful in 55s
CI Pipeline / canary (push) Successful in 36s
CI Pipeline / type-check (push) Successful in 30s
CI Pipeline / gitea-offline (push) Successful in 16s
CI Pipeline / unit-tests (push) Successful in 2m33s
CI Pipeline / required-checks (push) Successful in 1s
deploy / deploy (push) Successful in 4m10s
CI failure on the 0.66.61 bump run (job 18584): the latency test got
watchdog/alive:False because its daemon could not bind the FIXED port
8793 — a stale TIME_WAIT socket from an earlier test in the same file
held it (verified locally: 8793 bindable only with SO_REUSEADDR while
no listener exists). The notifier's event POSTs went nowhere, so the
watchdog correctly reported PROCESS_LOST: the harness was at fault,
not the bridge. Daemon fixture now binds port 0 (ephemeral) and reads
back the assigned port. 3x consecutive green locally.
2026-09-15 14:14:44 +01:00
Nick eccb446a3c feat(scaffolding): §15C/§15D/§15E — event-driven wait becomes the canonical default
- 15C audit: the W/R bridge (daemon :8791) was complete but its resume
  target was mimo-session-shaped only — every Python controller had to
  sleep/poll. Root cause recorded, not excused.
- src/rune/event_wait.py: register_process_wait (durable PROCESS_EVENT
  wait + per-wait FIFO resume cmd), run_builder_under_events (real
  builder under a notifier that observes actual exit and POSTs the
  event), await_resume_event (select-block, NO sleep floor, watchdog
  deadline = failure detector), resume_or_recover (restart: durable
  waitstore wins over transient token).
- 15E adversarials: duplicate/stale/wrong-correlation/malformed events,
  controller restart, lost-event watchdog (zombie-aware liveness).
- Latency proof: builder exits at T, controller resumes at T+~0.1s —
  no arbitrary floor. Failures carry truth (exit_code verdict).
- tests/test_event_wait.py: 8 proofs, real daemon subprocess,
  disposable WR_ROOT. Daemon invariant suites 45/45 + 36/36 unchanged.
2026-09-15 02:12:54 +01:00