[2026-10-30] eagle: work/projects/cpm-ios-idle-wake-investigation-2026-10-30.md work/projects/cpm-ios-uncovered-groups-2026-10-30.md
This commit is contained in:
1 parent
d32498646c
commit
9f3e3c5001
2 files changed
+222
No files matched your search
@@ -0,0 +1,220 @@
|
||||
---
|
||||
tags:
|
||||
- cpm
|
||||
- ios
|
||||
- webkit
|
||||
- investigation
|
||||
updated: '2026-10-30'
|
||||
status: investigation-and-proposal
|
||||
---
|
||||
# CPM iOS idle wake: действия, возможные механизмы и диагностический план
|
||||
Дата: 30 октября 2026. Продолжение [[cpm-ios-uncovered-groups-2026-10-30]].
|
||||
|
||||
**Основной вывод:** idle wake остаётся приоритетным сценарием, но текущий пиксель объединяет разные механизмы. Нужно разделить выполнение content script, доставку init в worker, ожидания внутри worker, dashboard → native → monitor и реальное получение initResp страницей. Проверка shipped bundle выявила две неограниченные storage-зависимости; контролируемые проверки показали, что общая очередь cpmState может остановить dashboard-ответы нескольких вкладок при продолжении отправок initResp. Естественный production-trigger такого storage stall пока не найден.
|
||||
|
||||
## Что проверено и чего эти результаты не доказывают
|
||||
|
||||
Проверены исходники **реально измеряемого iOS 7.243.0**, tag `7.243.0+ios`, commit `9b67ed7c720d274a554a86052881d2d690cccb3e`; ZIP extension извлечён из этого tag. Его manifest version — **2026.10.14**. Это важнее версии локального extension checkout: там уже есть ещё не выпущенные init progress marks, в shipped ZIP их нет.
|
||||
|
||||
Дополнительно: текущий main `3934949758`; WebKit source snapshot `99051d5d08cd9f19ec76ce599f7539d070b1ae09` от 29 сентября; проверены upstream patches четырёх связанных WebKit bugs. **Наличие исправления в upstream main не устанавливает, в какой iOS версии оно включено.** Этот проход не создавал production PR и не менял приложение/флаги.
|
||||
|
||||
Перечитаны записи 27–30 октября. В частности, гипотеза неограниченного `storage.session.get("config")` уже была записана 27 октября; это не впервые обнаруженная идея. Новое здесь — разбор общей state queue и контролируемое разделение dashboard и initResp на shipped методах.
|
||||
|
||||
В этом проходе выполнены три изолированные проверки JS-логики с подменёнными browser/native I/O. **Новый естественный iOS/WebKit outage не воспроизведён**, физический iPhone в этом проходе не использовался. Предыдущие H1/H2, idle и real-page результаты учитываются со своими ограничениями, а не переобъявляются новыми.
|
||||
|
||||
## 1. Какие действия пользователя дают эту картину
|
||||
|
||||
### A. Достаточно читать страницу в открытом браузере, затем перейти по ссылке
|
||||
|
||||
1. Открыть обычную HTTPS-страницу, получить работающий CPM.
|
||||
2. Читать/прокручивать её, не создавая новых extension-событий. Примерно через 30 секунд последней активности WebKit может выгрузить непостоянный background. Это нормальный lifecycle, не crash.
|
||||
3. Нажать ссылку, обновить страницу или открыть новую вкладку с URL.
|
||||
4. На main-frame HTTP(S) navigation app запрашивает готовность extension **на policy stage**, до загрузки документа. WebKit создаёт новый background view, recorder устанавливает proxy.
|
||||
5. Получаем `dealloc → view → proxy_on`; фон может успешно загрузиться за <1 секунды.
|
||||
6. Документ выполняет CPM content script, отправляет init. Если требуемый dashboard-сигнал не дошёл до monitor за 4 секунды после finish, появляется episode и первый snapshot.
|
||||
|
||||
Поэтому `view_age=4s_to_8s` естественен: время на загрузку страницы плюс четырёхсекундное ожидание. Он не доказывает, что view появился в момент сбоя. Несколько `dealloc>view>proxy_on` подряд могут быть обычными переходами с интервалами >30 секунд.
|
||||
|
||||
Если страница регулярно шлёт extension-сообщения или открыт активный port, выгрузка может откладываться; ровно 30 секунд от открытия вкладки не является гарантией.
|
||||
|
||||
### B. Home / блокировка телефона / возвращение в браузер
|
||||
|
||||
1. Открыть 2–3 здоровые вкладки, перейти в другое приложение или заблокировать экран.
|
||||
2. Во время простоя background может выгрузиться; native callbacks/timers могут отработать после resume.
|
||||
3. Вернуться, затем **сделать новую navigation**: ссылка, reload, новый URL в другой вкладке. Получается та же wake-история, иногда с `interruption`.
|
||||
4. Для подтверждённого cross-tab случая после первого timeout сделать свежую обычную navigation во второй вкладке; один только возврат к старому документу этого не доказывает.
|
||||
|
||||
В shipped monitor resume **перезапускает уже ожидающие замеры**, обычно с 8-секундным grace; он не создаёт новый init/замер на любой показ старой страницы. Чистый back/forward restore исключён из health measurement. Поэтому «разблокировать и посмотреть старую страницу» и «разблокировать и перейти на новую страницу» — разные опыты.
|
||||
|
||||
`interruption` в bg_events говорит о событии в доступной истории; `interrupted=true` означает, что именно первый измеряемый запрос пересёк suspension. Их нельзя смешивать.
|
||||
|
||||
### C. Граница unload/wake и две почти одновременные navigation
|
||||
|
||||
После 25–35 секунд idle начать переход в A и сразу в B; отдельно — заблокировать телефон во время перехода и завершить после resume. Навигации разделяют startup gate, но документы и сообщения имеют разные поколения. Это сильный сценарий для routing/registration и attribution races.
|
||||
|
||||
Чтобы доказать browser-wide failure, после первоначального сбоя нужна ещё одна navigation, начатая уже после него; один пакет одновременно восстановленных вкладок для этого недостаточен.
|
||||
|
||||
### D. M4 после второго timeout, затем тишина
|
||||
|
||||
Второй квалифицирующий timeout запускает context reload. Пользователь может после этого просто остаться на странице и перестать навигировать. В конце активного окна получается no-response, хотя **проверки нового контекста свежим документом могло не быть**.
|
||||
|
||||
Это существенная граница интерпретации прежних чисел. У wake cross-tab no-response 29 октября:
|
||||
- `reload_state=loaded`: **2 140 из 2 920** count-эпизодов.
|
||||
- `response_timed_out`: **776**.
|
||||
- failed/pending: 4.
|
||||
|
||||
`loaded` доказывает успешный context reload, но не проведённый и проваленный post-reload messaging test. `response_timed_out` сильнее: monitor зарезервировал post-reload regular measurement, и он истёк. Даже он не доказывает вечную поломку.
|
||||
|
||||
Следовательно, фразу «все 2 920 пережили M4 без восстановления» применять нельзя. Для опытов после M4 обязательно отдельно открыть новый документ и проверить actual initResp.
|
||||
|
||||
### E. Похожий footprint может создать не поломка worker
|
||||
|
||||
Валидная страница после idle может:
|
||||
- не выполнить ожидаемый content script;
|
||||
- выполнить init, но застрять на config/storage;
|
||||
- получить initResp, пока dashboard ждёт сохранения state;
|
||||
- прислать dashboard, который не прошёл parsing/маршрутизацию/атрибуцию.
|
||||
|
||||
Все эти пути способны дать готовый background и одинаковые native flags. Эти флаги проверяют конфигурацию и WebKit verdict, а не прохождение конкретного JS-запроса.
|
||||
|
||||
## 2. Реальная цепочка в shipped коде
|
||||
|
||||
`navigation policy → native background gate → WebKit background load → content script → runtime.sendMessage(init) → MessageRouter → handleAutoConsentMessage → config/settings/site checks → [dashboard branch || initResp branch]`.
|
||||
|
||||
**Ветки после init различаются:**
|
||||
- Dashboard: `updateCpmDashboardState → modifyCpmState → storage.session → refreshCpmDashboardState native message → validation → health monitor correlation`.
|
||||
- Ответ странице: `tabs.sendMessage(initResp) → content-script listener → AutoConsent.initialize`.
|
||||
|
||||
Dashboard запускается через promise chain и **не является ACK доставки initResp**. Возможны оба расхождения: dashboard есть, actual initResp потерян; actual initResp отправляется/доставляется, dashboard отсутствует.
|
||||
|
||||
В 7.243 MessageRouter завершает autoconsent-handler через `.then(() => {})`: успешный `runtime.sendMessage(init)` сам по себе может вернуть **undefined**. У нас undefined нельзя считать признаком потерянного worker, даже если в чужом ping/pong reproduction это аномалия. Нужны явные stages/ACK.
|
||||
|
||||
Полезные source anchors:
|
||||
- [App navigation gate](/Users/admin/DuckDuckGo/apple-browsers.git/cpm-ios-idle-wake-investigation-2026-10-30/shipped-app/TabViewController.swift:3662).
|
||||
- [Shipped config/state/init](/Users/admin/DuckDuckGo/apple-browsers.git/cpm-ios-idle-wake-investigation-2026-10-30/shipped-extension/public/js/background-embedded.js:2570).
|
||||
- [Независимая ветка dashboard](/Users/admin/DuckDuckGo/apple-browsers.git/cpm-ios-idle-wake-investigation-2026-10-30/shipped-extension/public/js/background-embedded.js:2678).
|
||||
- [Content script ждёт отдельный initResp](/Users/admin/DuckDuckGo/apple-browsers.git/cpm-ios-idle-wake-investigation-2026-10-30/shipped-extension/public/js/content-scripts/cpm.js:2846).
|
||||
|
||||
## 3. Конкретные механизмы и места поиска
|
||||
|
||||
### H1. Unbounded config/storage и общий state queue — проверяемая app/extension-гипотеза
|
||||
|
||||
В `refreshRemoteConfig` первый `getFromSessionStorage("config")` выполняется **перед** native request и его timeout. После успешного обновления config запись `storage.session.set` также ожидается без своего timeout. Все init ждут общий `remoteConfigJson`.
|
||||
|
||||
Отдельно `modifyCpmState` сериализует обновления разных вкладок через `_stateQueue`. Операция ожидает `getCpmState`, затем `updateCpmState`, включая storage write. Rejection ловится и позволяет очереди продолжить; never-settled promise удерживает всё последующее. Dashboard каждого init зависит от этой очереди. Это глобальная точка блокировки, даже если JS event loop и browser.runtime работают.
|
||||
|
||||
Проверки на извлечённых shipped классах:
|
||||
1. При удерживаемом config read native request вообще не начался; его 20-секундный timeout ещё не мог помочь. После отпускания storage handler завершился.
|
||||
2. Healthy control: два init дали две попытки initResp и два dashboard-вызова.
|
||||
3. Pending cpmState write: два init дали **две попытки initResp**, **ноль dashboard-вызовов**, выполнена только первая заблокированная запись. После отпускания записи дошли оба dashboard-вызова.
|
||||
|
||||
Это **логическая демонстрация механизма**, не доказательство естественного зависания browser.storage, доставки initResp в настоящий документ или доли production false positives. Browser/native I/O подменены управляемыми promises.
|
||||
|
||||
Свежий JS realm после M4 должен очистить чисто in-memory очередь. Поэтому для повторения после M4 нужны повторный storage stall/общая нижележащая проблема либо другой механизм. Не всякий пяти минутный episode доказывает, что очередь оставалась зависшей после reload.
|
||||
|
||||
Куда смотреть: config storage get/set; cpmState get/set; возраст головы очереди; глубина очереди; отдельный health/ACK путь. При будущем исправлении persistence не должна безгранично удерживать ответ/наблюдение. Одного `Promise.race(timeout)` недостаточно для безопасных записей: старая незавершённая запись может позднее завершиться и затереть более новую; нужны revision/order/coalescing semantics.
|
||||
|
||||
### H2. Worker готов по load callback, но init не маршрутизируется в listener
|
||||
|
||||
WebKit `runtimeSendMessage` после wake получает набор процессов для `RuntimeOnMessage`; если он пуст, завершает вызов пустым результатом. Выборка идёт по listener frames/content world, а не просто по живому PID background view.
|
||||
|
||||
`bg_process_responsive` проверяет WebKit verdict о процессе WKWebView. Он не проверяет, что нужный SW listener зарегистрирован и выполняется. Carrier page, SW thread, API bindings и listener routing — разные уровни.
|
||||
|
||||
Нужно поймать: content script точно начал init; worker ingress отсутствует при известной диагностической поддержке; альтернативный worker/native путь проверен. Одно отсутствие native progress mark недостаточно — сам мост может не работать.
|
||||
|
||||
Предыдущие проверки H1 Network crash и H2 skip-listener из заметок **не подтвердили естественный persistent trigger** на production 30-секундном unload. Быстрый TestWebKitAPI режим давал артефакты; его красный результат не переносится на production без повторения.
|
||||
|
||||
### H3. Init дошёл, но native bridge / handler / dashboard correlation потеряли результат
|
||||
|
||||
Handler registered проверяет наличие native handler в словаре. Это не факт получения текущего сообщения. После message delivery есть отдельные parsing, URL/consentStatus validation и correlation по tab, document URL и extension generation.
|
||||
|
||||
Monitor сравнивает scheme/host/port/path/query, игнорируя fragment. Bundle берёт tab URL из `sender.tab.url/pendingUrl`; при redirects, URL rewrite и пересечении context reload возможны несовпадения. При известных mismatch до failure monitor часто отменяет недоказуемый замер, поэтому нельзя любой mismatch объявить false-positive. Но после первого failure отсутствие подходящего current-generation response может оставить episode открытым.
|
||||
|
||||
Нужны отдельные счётчики handler-entry, parse rejection, stale context, URL mismatch, zero candidates, ambiguous candidates и accepted attribution. Без них полученный, но отвергнутый ответ внешне равен отсутствующему.
|
||||
|
||||
### H4. Script не выполнялся / ранний JS exception / неправильный sender
|
||||
|
||||
`tab_has_ext_scripts=true` означает зарегистрированный user script нужного content world, а не исполнение в конкретном документе. Перед обработкой init bundle проверяет sender.tab, frameId и tabId; часть неверных метаданных ведёт к раннему return.
|
||||
|
||||
Искать после independent cs-start evidence. Исследовать обычную navigation, восстановление/переиспользование web view, process swap и previews отдельно. Большая часть P6/controller mismatch к iOS wake-группе не относится.
|
||||
|
||||
### H5. Idle wake может быть обычным состоянием большинства navigation
|
||||
|
||||
Большая доля wake среди failures не определяет риск wake. После 30-секундной выгрузки многие здоровые navigation тоже создают новый background.
|
||||
|
||||
Нужен знаменатель: `failed wake / все eligible wake navigation` против `failed warm / все eligible warm navigation`, одинаковая выборка и правила. Без него keep-warm может лечить действительно важный lifecycle race или просто сдвигать классификацию. До такого сравнения blanket keep-warm не является первым выбором.
|
||||
|
||||
## 4. Что найдено в WebKit и публичных обсуждениях
|
||||
|
||||
- [317981](https://bugs.webkit.org/show_bug.cgi?id=317981): потеря sendMessage на первоначальном старте при ещё неизвестном listener set; исправление добавляет очередь для initial load. **Первый load после очистки listener state — его scope**, обычный повторный wake он полностью не объясняет.
|
||||
- [324743](https://bugs.webkit.org/show_bug.cgi?id=324743): readiness объявлялась до завершения registration; исправлено ожидание нужного состояния. Это показывает ограниченность прежнего loader-ready как messaging-ready, но не устанавливает наличие бага на нашей OS.
|
||||
- [324754](https://bugs.webkit.org/show_bug.cgi?id=324754), [patch](https://github.com/WebKit/WebKit/commit/001f7dbb8bbf): после unload/reload worker мог оказаться в процессе, где отсутствует carrier page и не инжектируются extension bindings. Хорошее структурное сходство, однако требуется совпадение trigger/OS; прежняя наша Network-проверка это не подтвердила.
|
||||
- [322881 / patch](https://github.com/WebKit/WebKit/commit/4ce58a7ff78ce27cf6646691c6ddfb966b22b51c): восстановление SW clients при повторном background load. Upstream regression проверяет offscreen client; обычные HTTPS-вкладки с content scripts не следует автоматически считать теми же SW clients.
|
||||
- [Публичный iPhone reproduction](https://github.com/Happygallo/SafariExtensionBackgroundUndefinedBug): автор сообщает о сбое после lock/inactivity на iOS 18/26 и отсутствии проявления в Simulator/с Web Inspector. Исходники проверены: worker возвращает явный pong; manifest использует module worker, content script document_end и ping раз в секунду. У нас classic worker/document_start, явный native pre-wake и отдельный initResp. Это мотивирует device/без-inspector опыт, а не доказывает одинаковую причину.
|
||||
- [Apple Forums 758346](https://developer.apple.com/forums/thread/758346): исторические device-only wake failures; автор описывает улучшение при непостоянной background page вместо service worker. Apple сообщала о фиксе в 17.6.1, позже есть сообщения пользователей о сохранении проблемы. Это не единый доказанный баг всех новых OS.
|
||||
- [WWDC26](https://developer.apple.com/videos/play/wwdc2026/216/) описывает поддержку background page и service worker. Локальный WebKit manifest parser тоже поддерживает непостоянный document background при MV3. Поэтому **SW ↔ nonpersistent background page — допустимый диагностический A/B-кандидат**, а не keep-alive workaround.
|
||||
|
||||
Наличие этих upstream fixes не означает, что надо ждать очередного Safari release. Сначала нужны наши stages и совпадающее воспроизведение. Safari-hosted extension и WKWebExtension внутри DDG отличаются управлением и lifecycle.
|
||||
|
||||
## 5. Телеметрия, которая действительно различит эти ветки
|
||||
|
||||
Это предложение контракта, не добавленные пиксели. Значения — ограниченные enum/bool/buckets; URL, tab IDs, document IDs, worker IDs и nonce в аналитику не отправляются.
|
||||
|
||||
### Минимальный приоритетный набор
|
||||
|
||||
**A. Per-document trace с локальной корреляцией.** Временный navigation/document token + extension generation только в памяти app/JS. Token проходит вместе с init/ответом, не сохраняется между сессиями и не уходит в ClickHouse. Он должен различать повторную загрузку того же URL и поколения после M4. Capability handshake: `unsupported/unknown/supported`; отсутствие marks у старого bundle/старого документа нельзя писать как `init_not_received`.
|
||||
|
||||
**B. Раздельные положительные свидетельства на границах:**
|
||||
- content script started;
|
||||
- init send attempted / rejected / settled;
|
||||
- worker init ingress;
|
||||
- dashboard handler entry / validation / attribution;
|
||||
- initResp send attempt / transport completion;
|
||||
- content script actually received initResp и завершил предусмотренную initialize-стадию.
|
||||
|
||||
Нельзя заменить последнюю точку успешным `tabs.sendMessage`: это транспортный результат, не прикладной ACK. И нельзя считать успешный runtime promise с undefined ACK принятия init.
|
||||
|
||||
**C. Где ждёт worker.** Отдельные bounded markers:
|
||||
`config_session_get`, `native_config_request`, `config_session_set`, `user_settings`, `site_policy`, `state_queue_wait`, `state_session_get`, `state_session_set`, `dashboard_notify`; возраст текущего ожидания и глубина очереди в buckets. Маркеры пишутся **до await**, collector не зависит от той же state queue/storage. Для параллельных dashboard/initResp нужны отдельные bits/statuses, а не один максимальный stage, который теряет информацию о второй ветке.
|
||||
|
||||
**D. Native rejection reason.** `no_handler / malformed / stale_context / url_mismatch / no_candidate / ambiguous / attributed`, с отдельным `unknown` если входящий вызов не наблюдался. В аналитику идёт классификация расхождения, не адрес страницы.
|
||||
|
||||
**E. First и end evidence + recovery opportunity.** Сохранить первый snapshot; дополнить bounded end-state и событиями, произошедшими после него:
|
||||
- view/context replaced, background ready/failure;
|
||||
- retry/M4 attempted либо suppression reason;
|
||||
- количество eligible regular measurements после recovery: 0 / 1 / 2+;
|
||||
- post-recovery timed out / dashboard attributed / page ACK / no opportunity;
|
||||
- initial-document recovery и ответ другой вкладки отдельно.
|
||||
|
||||
Пятиминутное отсутствие ответа при нуле post-reload opportunities не должно означать доказанный провал recovery.
|
||||
|
||||
### Два обязательных условия дизайна
|
||||
|
||||
**Независимость диагностического канала.** Если все worker marks идут только через потенциально сломанный native messaging, отсутствие marks не различает «init не пришёл» и «worker не может отчитаться». Нужен дополнительный app↔content-script diagnostic bridge с проверенной привязкой content world и/или post-failure диагностический runtime reply, который content script передаст native независимо. App-owned probe в другом world доказывает работу того probe, а не исполнение CPM script; эти результаты нельзя объединять.
|
||||
|
||||
Positive marker надёжно показывает пройденную границу. Negative marker требует поддержки контракта и проверки канала; иначе результат остаётся unknown. Стопроцентно назвать внутренний баг WebKit только этими полями нельзя, но можно выбрать узкий участок для engine trace.
|
||||
|
||||
**Healthy baseline и отсутствие изменения поведения до failure.** Те же bounded признаки для небольшой случайной выборки здоровых eligible navigation: wake/warm, gate outcome, time since resume, readiness, page ACK. Измерение выбирается до результата, с известным sampling. Readiness-пробы не должны специально будить фон до контрольного snapshot; ping после обнаруженного failure отмечается как вмешательство. Никаких постоянных heartbeat/ports в основном диагностическом варианте.
|
||||
|
||||
Вспомогательные native поля: wake trigger `navigation / retry / network recovery / context reload / WebKit-or-unknown`, resume-age bucket, current measured navigation kind, diagnostic schema support; пересечения вызовов помечать как multiple/unknown, а не выдумывать один trigger.
|
||||
|
||||
## 6. Как превратить расследование в решение
|
||||
|
||||
1. **Первый небольшой диагностический change:** per-document correlation, worker ingress, bounded pending-await/state queue, native attribution reason и настоящий page ACK. Добавить end-of-episode recovery opportunity. Адаптировать идею #7385 к нынешнему episode contract, а не публиковать старый stacked PR без переноса.
|
||||
2. **Контролируемые fault cases:** dropped init; config get never settles; state set never settles; native dashboard rejected; response URL/generation mismatch; initResp lost. Для каждого диагностический результат должен различаться. Уже выполненный storage control покрывает первые две storage-развилки на уровне JS.
|
||||
3. **Физический iPhone, штатные 30 секунд, без debugger/Web Inspector:** foreground idle control; lock/resume 1–5–30 минут; lock during startup; fresh navigation в A и B. Протокол требует и dashboard, и page ACK; после M4 нужна новая regular navigation. Нельзя ограничиваться старой страницей или одним успешным callback.
|
||||
4. **Сильный причинный A/B:** тот же CPM JS и непостоянный background, но service worker против document background. Сохранить idle unload, одинаковые профили/флаги и реально проверить unload/reload в обеих ветках. Если сбой воспроизводится в SW и исчезает в document при равной нагрузке, это сужает поиск до SW-specific registration/routing/bindings. Изменение сохраняет различия окружения и само по себе не идентифицирует одну строку WebKit.
|
||||
5. **Второй A/B по нашему коду:** убрать блокировку delivery/health-evidence на сохранении CPM state, сохранив корректность serial writes и настройки consent. Если page ACK здоровый, а старая dashboard-ветка висит, это отдельное исправление наблюдения/state pipeline; оно не должно маскировать реальные потери initResp.
|
||||
6. Только после совпадающего естественного fault решать о re-init, bounded restart или изменении background environment. Keep-warm оставлять отдельным causal experiment с расходом ресурсов и знаменателем wake, не первым безусловным лечением.
|
||||
|
||||
**Практический следующий шаг:** двигаться с двумя узкими гипотезами — init не дошёл до реально работающего worker; init дошёл, но общий config/state/native/attribution путь удержал наблюдаемый ответ. Новая телеметрия должна первым делом развести их и отдельно показать page ACK. Увеличение одного bg_events хвоста этого не сделает.
|
||||
|
||||
## Артефакты
|
||||
|
||||
`/Users/admin/DuckDuckGo/apple-browsers.git/cpm-ios-idle-wake-investigation-2026-10-30/`:
|
||||
- `shipped-app/`, `shipped-extension/`, `revisions.json` — проверенные версии и извлечённый исходник.
|
||||
- `webkit-commit-*.json` — реальные upstream patches; source snapshot отдельно в `/Users/admin/Downloads/WebKit_sparse`.
|
||||
- `storage-probes.cjs`, `storage-probe-results.json` — три проверки shipped методов, включая healthy control и освобождение заблокированной операции.
|
||||
- `public-repro/` — прочитанный публичный минимальный пример для сравнения scope.
|
||||
|
||||
Основание количественных выводов и SQL: [[cpm-ios-uncovered-groups-2026-10-30]]. История прошлых воспроизведений: [[cpm-post-release-analysis-2026-10-27]].
|
||||
@@ -8,6 +8,8 @@ status: analysis
|
||||
---
|
||||
# CPM iOS: оставшиеся группы и следующий фокус — 30 октября 2026
|
||||
|
||||
Продолжение: [[cpm-ios-idle-wake-investigation-2026-10-30]] — browser actions, shipped app/extension/WebKit paths, проверка storage/state queue, публичные аналоги и конкретный telemetry proposal. Уточнение интерпретации M4: `reload_state=loaded` без квалифицирующего нового замера не доказывает провал messaging recovery; отдельно выделены `response_timed_out` и предложен post-recovery opportunity counter.
|
||||
|
||||
Обновлён ClickHouse-срез и проверены актуальные PR. **Следующий основной фокус — потеря ответа после idle wake при уже готовом фоне; второй — старт с `pending` без текущей error 6. Отдельно остаётся непроверенный хвост error-6 history → replacement view → pending: его нельзя объявлять закрытым #7730.** Это выбор следующего расследования и исправления по наблюдаемым симптомам, а не доказанная причинная классификация.
|
||||
|
||||
macOS в этом пересчёте не анализировалась.
|
||||
|
||||
Reference in new issue
Block a user