From c14a0c2dcaa23613557ba2a0e7abacd8a8492bc9 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Tue, 27 Oct 2026 09:57:56 +0600 Subject: [PATCH] [2026-10-27] eagle: work/projects/cpm-post-release-analysis-2026-10-27.md --- work/projects/cpm-post-release-analysis-2026-10-27.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/work/projects/cpm-post-release-analysis-2026-10-27.md b/work/projects/cpm-post-release-analysis-2026-10-27.md index dd090bbf..342abbd7 100644 --- a/work/projects/cpm-post-release-analysis-2026-10-27.md +++ b/work/projects/cpm-post-release-analysis-2026-10-27.md @@ -146,3 +146,14 @@ Denominators were refreshed after more 26 Oct data arrived: extension-loaded ins ### Repro statistics note 18 wake navigations cannot rule out a rare loss. At p=8% a clean run happens 22% of the time. The per-wake production rate is likely ≪1% (many wakes per install-day), which needs ~1,000 wakes for 95% power. `CPMReproIdleWakeTests` now has `CPM_REPRO_FAST_UNLOAD=1`: it calls `+[WKWebView _setApplicationBundleIdentifier:]` with `com.apple.WebKit.TestWebKitAPI`, so WebKit unloads an idle background after 3 s instead of 30 s (~5 s per cycle). It can change other test-runner-only WebKit behavior, so confirm any hit with the 30 s delay. A 1,000-cycle run (~1,500 wake navigations) was started on 27 Oct. +- **Fast idle-wake run, 27 Oct: 0 lost of 1,500 wake navigations in 1,000 cycles** (`CPM_REPRO_FAST_UNLOAD=1`, 3 tabs, single and double-tab wakes, 85 min). With zero failures the 95% upper bound on the per-wake loss rate is ≈0.2% (3/1500). A bare idle-unload → wake race on a fixture page is not the main source of the wake cohort; an extra ingredient is needed (hypotheses H1–H5 below). + +### Hypotheses for the remaining wake hangs (27 Oct) + +The embedded extension (`background-embedded.js`, 2026.10.23) registers `runtime.onMessage` synchronously (`MessageRouter`). CPM `init` = `await remoteConfigJson` → native `isAutoconsentSettingEnabled` → native `isFeatureEnabled` → `refreshDashboardState`. Every native request has a 20 s timeout, with `config_unavailable` / `setting_disabled` fallbacks that still refresh. **A 5-minute silence therefore means init never reached the worker, or the refresh was not attributed.** + +1. **H1 — worker without extension bindings after Network-process recovery (WebKit 324754).** macOS recovery is applied on 9% of installs/day. A worker without `browser.runtime` throws at top level: alive, responsive, "ready", never answers, all tabs, M4 may repeat it. Test: Network crash → recovery restart → probe `browser.runtime` in the worker → N wake cycles. Fix: verify with a ping after restart; restart again or reload if it fails. +2. **H2 — listener metadata loss.** `wakeUpBackgroundContentIfNecessaryToFireEvents` returns an empty reply without waking when the saved listener set lacks `RuntimeOnMessage`. The set is saved after every load, so one load where the worker threw before registering poisons it. Test: a prelude knob that throws or skips `onMessage` on one load only. Fix: treat an empty sendMessage reply as a failure → restart, plus re-send init. +3. **H3 — stale failed background view (iOS error 6, pattern B).** `_loadServiceWorker` failure keeps the view, so wakes only queue; activity keeps restarting the 30 s unload timer; P2 retry uses the same path. Test: fail the worker load without closing the view, with navigations every 10 s. Fix: on error 6 with a live background view, restart its WebContent process, then retry. +4. **H4 — refresh not attributed.** The monitor needs an exact scheme/host/port/path/query match with the committed URL. A cold wake answers later, giving `replaceState` / client-side redirects time to change `sender.tab.url`. `other_tab_response` is 37–53% of outcomes. Test: a fixture with `replaceState` 50–300 ms after load, cold vs warm. Fix: attribute by extension tab ID and treat same-document URL changes as the same document. +5. **H5 — slow cold-wake init.** Three native round-trips plus session storage; explains late answers (`response_after` ≥30 s in 20–35% of answered episodes), not 5-minute hangs. Test: prelude `delay` on `sendNativeMessage` 1–3 after a wake. Fix: answer init from cached config/settings first.