[2026-10-15] eagle: work/projects/cpm-status-2026-10-15.md

This commit is contained in:
Alexey Martemyanov committed 2026-10-15 23:26:30 +06:00
1 parent 7d13bdaaaa
commit f53943f88f
1 file changed
+33 -4
+33 -4
View File
@@ -81,8 +81,8 @@ tags:
| **P2. «Пробуждение → error 6»**, циклы | `proxy_on>dealloc>view>proxy_on>error_E:6` (23.6k), `error>dealloc>view>proxy_on>error` (5.7k), после `died_crash` (1.5k) | iOS; macOS 118 | macOS: заморозка нового процесса на ≥30 с даёт error 6, корзина 25–35 с. iPhone: 4 сценария безуспешно. Главный iOS-хвост **без** `unresponsive` (в воспроизведении он есть) | корень в WebKit (`wakeUpBackgroundContentIfNecessary` взводит 30-секундный таймер до загрузки worker'а). Гипотеза: перезагрузка расширения при возврате на передний план |
| **P3. Контекст загружен, view нет** | `load` / `load>base_url_changed` | 17.1k + 0.9k / 162 + 81 | задержка очистки при смене `baseURL` воспроизведена на macOS при большом кэше (около 10 минут заполнения); iOS-гонка запуска (`bg_view_creations=0`, восстановление сессии, первые 30 с) не воспроизведена: холодный старт в harness'е отвечает за миллисекунды | кандидат: стабильный `baseURL` (ветка `cpm-stable-base-url`: не доведён, меняет URL всем расширениям, не прогнан через harness, старая база). Фикс WebKit 318756@main, номер сборки ОС не проверен |
| **P4. Первая загрузка** | `load>view>proxy_on` | 6.8k + 2.3k / 570 | да (фикс A) | фикс A |
| **P5. Фон выгружен в момент сбоя** | `proxy_on>dealloc>view>proxy_on>dealloc` | 1.9k / 494 | да: test-only потеря регистрации живой вкладки и пустые runtime listener metadata с первого старта; долгий документ и пауза main actor P5 не дали (§10) | кандидаты: корректный tab lifecycle; при пустых metadata explicit loadBackgroundContent после восстановления listener. Естественный вход не найден |
| **P6. macOS: вкладка без расширения** | `load>view>proxy_on>dealloc` / `load>view>proxy_on`; варианты с `extension_updated` отдельно | iOS ≈0 / 627 + 235 | да: test-only отсутствие controller до/после idle и сохранение controller прежнего менеджера (§10) | корректно подключать current controller при создании view; reload контекста неверно подключённую view не чинит. Естественный вход не найден |
| **P5. Фон выгружен в момент сбоя** | `proxy_on>dealloc>view>proxy_on>dealloc` | 1.9k / 494 | да: закрытие окна с shared pinned tab через production listener → WebKit сам удаляет сохранённый tab; точная сигнатура с tab=false (§11). Пустые listener metadata пока только test-only (§10) | найден browser→WebKit путь для Mac/tab=false; фильтрации явных didCloseTab недостаточно — didCloseWindow закрывает tabs повторно. Для tab=true и iOS естественный вход не найден |
| **P6. macOS: вкладка без расширения** | `load>view>proxy_on>dealloc` / `load>view>proxy_on`; варианты с `extension_updated` отдельно | iOS ≈0 / 627 + 235 | да: цикл главного webExtensions flag через production handler создаёт replacement manager, прежний WKWebView сохраняет старый controller и даёт точную сигнатуру (§11); nil controller до/после idle — test-only (§10) | условный production-путь найден; фактическое переключение главного flag в выборке не подтверждено. Embedded-only cycle сохраняет controller; reload контекста старую привязку не чинит |
| **Network заменён** | | см. раздел 4 | да (краш, worker мёртв при том же view) | фикс B |
| **«Здоровый» остаток, other** | | iOS 12.5%, macOS 22% | нет | нет гипотезы |
@@ -143,7 +143,7 @@ tags:
4. **Судьба фикса A:** слабое основание в данных, не совпадает с названием задачи; решить, сливать ли без зелёного измерения эффекта через `first_load_wait`.
5. **P3:** довести стабильный `baseURL` (ограничить встроенными расширениями без `web_accessible_resources`, прогнать harness, перенести на свежий `main`), проверить номер сборки ОС с фиксом 318756@main.
6. **Локальные repro для P1–P3** отдельным PR без фиксов (по образцу harness'а, `requireLocalRun`), чтобы гонять после релизов WebKit.
7. **iOS:** воспроизведение error 6 на реальном устройстве. P5/P6 на macOS воспроизведены контролируемыми условиями (§10); остаётся найти естественные входы в потерю регистрации/listener metadata и отсутствующий/прежний controller.
7. **iOS:** воспроизведение error 6 на реальном устройстве. Для Mac P5/tab=false найден и проверен путь shared pinned window → didCloseWindow → внутренний didCloseTab WebKit; для P6 проверен условный путь цикла главного flag (§11). Не установлены P5/tab=true, iOS lifecycle и реальность flag-transition в P6-сессиях.
8. Блокеры по ревью: #7376 и #7378 ждут ревью; #7384/#7385 стоят на #7376.
## 9. Методика и инструменты
@@ -166,6 +166,8 @@ multiIf(
## 10. Журнал воспроизведения P5/P6 — 15 октября 2026
Хронологический журнал первоначальных controlled экспериментов; дополнительные результаты с привязкой к production-путям и текущие ограничения — в §11.
Работа начата по запросу: добавить тесты новых гипотез и попытаться воспроизвести наблюдаемые цепочки. Продакшен-фиксы и публичные PR этим запросом не меняются.
**Выбор worktree:** `/Users/admin/DuckDuckGo/apple-browsers.git/alex/cpm-web-extension-remaining-failures`, ветка `alex/cpm-web-extension-remaining-failures`, HEAD `a0717cf098cd1cbd32d5bc9d19aa7db0fab2399f`. Здесь общий harness, production recorder, локальные эксперименты пробуждения, error 6 и очистки baseURL (P1–P3), без watchdog/фиксов A/B. Полного единого набора всех сценариев сейчас нет: базовые A/B находятся в `cpm-repro-harness`/фикс-ветках, init-progress E2E — в `cpm-e2e-init`. Существующие dirty-изменения сохранены; добавления этой работы ограничиваются тестовым harness.
@@ -340,7 +342,7 @@ CPM_REPRO=1 CPM_REPRO_P5_P6=1 swift test --disable-automatic-resolution --filter
- Две последующие навигации дали actual initialization failures и stuck: `load>view>proxy_on>dealloc>view>proxy_on>dealloc`, creations=2, view=false, context=true, tab=false, controller/scripts=true, errors=none, network_restarted=false. Content script получает init-error. Новая вкладка работает; `didOpenTab` восстанавливает исходную.
- `testClosingUnrelatedWindowPreservesRegisteredTab` — **1.205 с**: закрытие окна, не возвращающего эту вкладку, сохраняет tab_in_context=true, initResp и 0 failures.
Лог: `/private/tmp/cpm-p5-p6-20261015/production-window-close.log`. Это **source-linked воспроизведение на системном WebKit 26.7.1** через production listener и неизменённую логику CPM, а не произвольное закрытие живого tab. Harness использует window/tab delegates, повторяющие контракт macOS; сам MainWindowController/AppKit целиком в SPM-тест не загружен. Следовательно, browser call chain подтверждён чтением исходников, внутренний эффект WebKit и P5 — исполнением теста.
Лог: `/private/tmp/cpm-p5-p6-20261015/production-window-close.log`. Это **source-linked воспроизведение на системном WebKit под macOS 26.7.1** через production listener и неизменённую логику CPM, а не произвольное закрытие живого tab. Harness использует window/tab delegates, повторяющие контракт macOS; сам MainWindowController/AppKit целиком в SPM-тест не загружен. Следовательно, browser call chain подтверждён чтением исходников, внутренний эффект WebKit и P5 — исполнением теста.
Область объяснения: **P5/tab_in_context=false** (в выбранном Mac-срезе 68 событий). Это не доказательство, что все эти события были caused by shared pinned windows, и не объяснение P5/tab_in_context=true либо iOS.
@@ -364,3 +366,30 @@ CPM_REPRO=1 CPM_REPRO_P5_P6=1 swift test --disable-automatic-resolution --filter
Embedded-контроль **красный, 6.119 с, 3 assertions**: controller/scripts/tab=true, но первая навигация в 0.704 с ушла до sw activate в 0.747 с и потеряла init. Таким образом, «embedded cycle всегда здоровый сразу после sync» — неверное ожидание: здесь воспроизводится уже известный механизм **A / P4**, а не P6. Не считаю красный результат ошибкой постановки.
Для изоляции именно controller-binding уточняю контроль: после sync явно дождаться `loadEmbeddedExtensionBackgroundContent`, затем требовать initResp без failures при прежнем controller. Этот readiness wait — контрольное условие теста; production fix A данной работой не добавляется.
### P6: уточнённый прогон завершён
`production-flag-cycle-final.log`: **2 tests, 0 failures, 10.237 с**:
- `testMainFeatureFlagCycleRecreatesManagerAndMatchesP6` — **9.252 с**; повторное подтверждение P6 через true → false → true главного flag.
- `testEmbeddedFeatureFlagCycleKeepsControllerAfterBackgroundBecomesReady` — **0.985 с**; прежний controller и scripts=true, после explicit readiness wait initResp и 0 failures. Первоначальный красный контроль с потерей первой навигации сохранён в предыдущем логе и описан выше как известный A.
Таким образом, добавлены **четыре новых source-linked проверки**: две window-close и две flag-cycle; все четыре текущих метода зелёные в двух запусках. Они выполняют production listener/flag handler/manager/CPM и системный WebKit; app-side host callbacks и window delegates реализованы harness по исходникам macOS, приложение целиком не запущено.
Оставшиеся неизвестные: происхождение P5 с tab_in_context=true; реальные iOS lifecycle-условия; было ли переключение главного flag в P6-сессиях. Главный flag default enabled, поэтому config fetch с неизвестной задержкой не считается доказанным триггером.
### Проверка после source-linked дополнений
- Обычный пакет: `swift test --disable-automatic-resolution --skip-build` — **478 XCTest, 28 opt-in skipped, 0 failures, 10.469 с**. Лог `package-tests-production-paths.log`.
- Strict SwiftLint всех восьми файлов этой работы — **0 violations** (`--no-cache`).
- `summarize.py` и `results.json` обновлены: 14 текущих методов (10 первоначальных + 4 source-linked) имеют pass по последним соответствующим логам. Это несколько групп запусков, не единый прогон всех 14.
- Изменения этой работы остались в `SharedPackages/WebExtensions/Tests/WebExtensionsTests/CPMRepro/`: дополнен harness windows/initial-tabs, два P5 window tests в `CPMReproLifecycleHypothesisTests.swift`, новый `CPMReproProductionFlagTests.swift`. Новых production-правок нет; первоначальный tracked dirty diff — те же 10 файлов / 164 additions / 8 deletions. SHA-1 Package.resolved прежний `7ccce20acd452656c9bf2d2fa186d044e4a8185f`.
Точки для проверки call chain:
- browser: `macOS/DuckDuckGo/MainWindow/MainWindowController.swift:611–640`, `macOS/DuckDuckGo/WebExtensions/MainWindowController+WKWebExtensionWindow.swift:31`, `macOS/DuckDuckGo/Windows/View/WindowControllersManager.swift:178`;
- WebKit: `Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionContextCocoa.mm:1351–1367` (window closes tabs), `:1419` (forgetTab), `Cocoa/API/WebExtensionContextAPIRuntimeCocoa.mm:129–141` (tab check before wake);
- P6 browser: `macOS/DuckDuckGo/Application/AppDelegate.swift:2153–2166,2209–2221`; shared production handler: `Sources/WebExtensions/FeatureFlag/WebExtensionFeatureFlagHandler.swift`; WebKit validates controller in `WebExtensionTabCocoa.mm:339–360`.
Повторить именно четыре новых source-linked теста из `alex/cpm-web-extension-remaining-failures/SharedPackages/WebExtensions`:
```sh
CPM_REPRO=1 CPM_REPRO_P5_P6=1 swift test --disable-automatic-resolution --filter 'CPMReproProductionFlagTests|CPMReproLifecycleHypothesisTests/testClosing'
```