src/window-tracking/AxObserverHealthSpecs.md
AxObserverHealth is a pure registry and reducer. It models one observer entry for each live PID generation,
classifies subscription outcomes, and emits lifecycle decisions. It neither imports Accessibility APIs nor
infers window focus. The impure registry is responsible for creating one observer/runloop source, applying
decisions, and cancelling the generation synchronously on teardown.
AXObserverCreate failure is retried with bounded exponential delay; success resets the consecutive
creation-failure tier without erasing lifetime diagnostics.AXUIElementDestroyed ends one app-side element generation; it does not by itself end the user-facing
window. The reducer moves the window through axElementEnded and joins two separately issued reads:
replacementPending because the AX query did not cover them.The join has a timeout. A found replacement or physical absence can still decide from partial evidence; every other partial result stays inconclusive rather than turning silence into closure.
ProcessGeneration synchronously replaces the old entry and reports its cancelled observer
generation.Tests pin every result classification, independent capability refusal budgets, exponential and sparse retry boundaries, cooldown/recovery triggers, callback diagnostics, global permission gating including processes started or replaced during failure, rebuild generation rejection, teardown/PID reuse, and the one-entry-per-PID invariant. They also pin recoverable observer creation, reset of consecutive creation backoff, per-wid single-use destroy correlation, and AX-node-end reconciliation against WindowServer scope.