From 89fa7bad79e67ac0411fb364b0c3d64e01694062 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Tue, 27 Oct 2026 14:06:53 +0600 Subject: [PATCH] [2026-10-27] eagle: work/projects/cpm-post-release-analysis-2026-10-27.md --- .../cpm-post-release-analysis-2026-10-27.md | 18 ++++++++++++++++++ 1 file changed, 18 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 342abbd7..b9548883 100644 --- a/work/projects/cpm-post-release-analysis-2026-10-27.md +++ b/work/projects/cpm-post-release-analysis-2026-10-27.md @@ -157,3 +157,21 @@ The embedded extension (`background-embedded.js`, 2026.10.23) registers `runtime 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. + +### H1/H2 tests — results (27 Oct) + +New `CPMReproBrokenWorkerTests` and harness changes (uncommitted): +- `Options.isNetworkRecoveryEnabled`, on by default as in the app; off in `CPMReproWebKitTests.unprotected`. +- Prelude `startFaults` breaks one worker start inside a wall-clock window: `.skipOnMessage` (script runs, no `runtime.onMessage` listener) or `.throw` (top-level throw before the extension script). +- `CPM_REPRO_FAST_UNLOAD` moved to `CPMReproTestCase.enableFastUnloadIfRequested()`. + +| Scenario | Fast unload (3 s) | Production unload (30 s) | +|---|---|---| +| H2 skipOnMessage: one woken worker without `onMessage` | only the broken navigation lost; all later ones answered | not re-run | +| H2 throw: one woken worker throws at top level | broken navigation + 5 busy + 3 idle-wake losses, **tabs 1–2 broken for the rest of the test** | broken navigation + **1** busy loss, then everything answered | +| H1 Network crash, recovery on, 20 / 10 wakes | 2 lost after crash, then **tabs 1–2 never got `initResp`**, tab-3 always fine; all restarted workers ran | 2 lost after crash, then all 10 wakes answered; all restarted workers ran | + +- **H1 not confirmed:** every worker restarted after Network recovery ran its script (bindings present). With the real delay, recovery restores messaging after 2 lost navigations. +- **H2 (listener metadata loss) not confirmed:** one start without a listener only loses that navigation; P1's wake plus re-registration heals it. +- **The fast-mode per-tab breakage is an artifact:** after a confirmed hang and recovery, tabs with an unanswered init kept receiving the dashboard refresh but never `initResp`. That is WebKit's silent `tabs.sendMessage` path (`processes.isEmpty()` → `{}`), and the monitor sent one `was_stuck=true / reload_state=loaded / other_tab_response` episode and nothing more. It **did not reproduce with the 30 s delay**. The TestWebKitAPI identity or the 3 s unload changes WebKit behavior; fast-mode hits must always be confirmed with the production delay. The blind spot it exposed is still real in principle: the monitor cannot see a tab that gets the dashboard refresh but no `initResp`. +- **H3 (stale failed background) reproduced with production timing:** after the throwing start, error 6 is recorded and the failed background view **stays present**. The next navigation 9 s later got nothing, and only the M4 reload (new context) restored messaging. No `background_load_retry` pixel fired, so the P2 retry never completed, as predicted by WebKit's `loadBackgroundWebViewIfNeeded` early return. Cost: at least one extra lost navigation per error 6, plus a full M4 reload. On iOS, error 6 is 7.5% of episodes and 25% of stuck.