# CPM Web Extension Breakage — статус и PR-план > Актуально на 2026-09-23. Полная трассировка: [[cpm-web-extension-breakage-findings]]. > Experiment Definition: [[cpm-background-graveyard-experiment-definition]]. ## Решение Есть два независимых класса проблем: - **Per-tab lifecycle** исправлен в M1 и уже merged. - **All-tabs CPM outage** идёт stack: M3 telemetry → M4 hung recovery → M5 bounded graveyard → M6 A/B. M4 перезагружает Web Extensions при первом сигнале `hung`, который подтверждает global CPM outage после предшествующего `messaging init failure`. Сам `messaging init failure` остаётся диагностическим: он не меняет состояние расширений. ## Статус проблем | Проблема | Статус | Что делаем | |---|---|---| | Forced background-process death → persistent all-tabs CPM outage | **Подтверждено** | M3 измеряет production incidence; M5 лечит; M6 сравнивает control/treatment. | | Natural crash/memory/CPU termination → production outage | **Не проверено в production** | Один production release M3 до включения M5/M6. | | Close Other Tabs, popup duplicate, pin/unpin/reorder/move/merge/window close | **Исправлено, merged** | M1 PR #6827. | | Нестабильный Web Extension base URL | **Исправлено локально** | M2 задаёт deterministic base URL до load/reload и отвергает malformed identifier без crash. | | Startup/session-restore content-script miss | **Подтверждено как transient** | Не объясняет persistent all-tabs outage. | | Failed background load навсегда блокирует WebKit | **Отвергнуто** | WebKit повторяет load; нужна повторяемая причина/traffic. | | Critical memory pressure как root cause | **Не воспроизведено** | Остаётся diagnostic correlation M3. | | Event starvation / JSC hang / native messaging stall | **Не проверено** | Остаётся в M3 diagnostic buckets. | | Network process restart | **Отвергнуто** | На проверенной сборке CPM восстановился. | | removeAllUserScripts / flag transition / scriptlet reload / page JS как all-tabs cause | **Отвергнуто** | Это не persistent global failure mode. | ## Milestones | Milestone | Branch / worktree | Готовность | |---|---|---| | M1 tab lifecycle | `codex/cpm-tab-lifecycle-fixes` | **Merged:** [PR #6827](https://github.com/duckduckgo/apple-browsers/pull/6827), CI green. | | M2 stable base URL | `alex/cpm-stable-base-url` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-stable-base-url` | **Production-ready:** 2 files; 11/11 targeted tests. Добавлена safe URL construction и negative validation вместо force-unwrap. | | M3 attribution telemetry | `alex/cpm-failure-telemetry` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-failure-telemetry` | **Merged 2026-09-23:** [PR #6844](https://github.com/duckduckgo/apple-browsers/pull/6844), CI green. Bucketed diagnostics, app launch/version attribution, `extension_updated`, `base_url_changed`, `recovery_from`, reload-error pixel; recorder и proxy имеют отдельные flags. [[cpm-m3-telemetry-privacy-triage]]. | | M4 hung recovery | `codex/cpm-hung-recovery` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-hung-recovery` | **In progress:** первый `messaging init failure` открывает diagnostic episode; первый последующий `hung` перезагружает Web Extensions. | | M5 graveyard mitigation | `alex/cpm-graveyard-mitigation` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-graveyard-mitigation` | **Production-ready, default off:** one retained view maximum, 3-second bounded hold, stale release cancellation, unload/reload/runtime kill-switch cleanup. 24/24 targeted tests; earlier real forced-kill iOS E2E recovered with release at ≈3.15 s. | | M6 graveyard A/B | `alex/cpm-graveyard-ab` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-graveyard-ab` | **Production-ready code:** lazy exposure enrollment, stable cohorts, control/treatment isolation, bounded pending queue, operational pixels and standard `experiment_metrics` outcome. 421/421 WebExtensions tests; iOS/macOS app builds; iOS/macOS pixel validators. | All milestone diffs pass `git diff --check`; changed Swift lines are within 150 columns. ## Stack and Git state M3 merged: [PR #6844](https://github.com/duckduckgo/apple-browsers/pull/6844), merge commit `2d58ad8cf4fae728a92e2aae0d3ec6073ddf49f2`. M2 — independent stable-base-URL fix. Вошедший в M3 `base_url_changed` только сообщает о смене URL между загрузками контекста с одинаковым identifier; URL и identifier не отправляются. Это не фикс M2. Stacked PRs: ``` M3 telemetry └── M4 hung recovery └── M5 graveyard mitigation └── M6 A/B experiment ``` Следующий Git-шаг: обновить `origin/main`, сверить diff M2/M4/M5/M6 и перенести оставшиеся изменения на merged M3 в порядке выше. Старые локальные refs не подтверждают актуальный stack; готовность M2/M5/M6 в таблице относится к предыдущей локальной валидации, не к повторной проверке после merge M3. Rebase/commit этих веток ещё не выполнялись в рамках этого обновления. Не включать generated `Package.resolved` churn. ## Experiment contract - Experiment: `cpmBackgroundGraveyardExperiment`. - Cohorts: `control`, `treatment`. - Enrollment: only on an actual eligible CPM background-process termination. - Primary framework metric: `cpmBackgroundGraveyardOutcome`, window `0...1`, values `healthy`, `initialization_failed`, `not_measured`. - Rollback: disable both `cpmBackgroundGraveyardExperiment` and `cpmBackgroundGraveyard`. Full definition and config draft: [[cpm-background-graveyard-experiment-definition]]. ## Remaining gates 1. Обновить оставшиеся ветки поверх merged M3; build/validate M4 и повторно проверить зависимые M5/M6. Открыть M2/M4/M5/M6 PRs в topology выше. 2. Create separate iOS and macOS experiment-log tasks. 3. Create Privacy Configuration + privacy/schema review tasks. 4. Create Data Science sample-size/design and Native Apps Experiment Analysis task. 5. Ship M3 first; enable M5/M6 only if production telemetry confirms the process-death hypothesis. M3 merged, но ещё не подтверждён как shipped production release. Feature flag registry tasks созданы отдельно для iOS/macOS; ссылки — в [[cpm-m3-telemetry-privacy-triage]]. Это обновление затрагивает только Obsidian.