# CPM Web Extension Breakage — статус и PR-план > Актуально на 2026-09-15. Полная трассировка: [[cpm-web-extension-breakage-findings]]. ## Итог Есть два независимых класса проблем: - **All-tabs:** после смерти background WebContent process CPM может перестать работать во всех вкладках. Нужна последовательность telemetry → production validation → bounded graveyard → A/B. - **Per-tab:** ошибки lifecycle заставляют WebKit забыть ещё живую вкладку. Исправляются независимо от graveyard. ## Статус гипотез | Проблема | Статус | Результат | |---|---|---| | Forced death background process → persistent all-tabs CPM outage | **Подтверждено воспроизведением** | Kill background PID ломает CPM; reload и новая вкладка не помогают, Fire восстанавливает. | | Natural crash / memory / CPU termination в production | **Не проверено** | Механизм доказан, реальная частота и связь с outage требуют M3/M4. | | Close Other Tabs forget-ит retained tab | **Подтверждено и исправлено в M1** | Сохраняется тот же экземпляр Tab без ложного didCloseTab. | | Duplicate Tab из popup переносит original | **Подтверждено и исправлено в M1** | В main window уходит копия, source остаётся отдельным объектом. | | Закрытие окна forget-ит shared pinned/other-owned tabs | **Подтверждено и исправлено в M1** | Закрываются только tabs, реально принадлежащие закрываемому окну. | | Нестабильный WebExtension base URL | **Исправлено и локально проверено в M2** | URL детерминирован по identifier и сохраняется между load/reload; production migration/storage validation остаётся rollout-задачей. | | Startup/session-restore content-script miss | **Подтверждено как transient** | Не объясняет устойчивый all-tabs outage. | | Failed background load навсегда застревает в m_backgroundWebView | **Исходный вывод отвергнут** | WebKit способен повторно загрузить background; устойчивый outage требует повторяемой причины/traffic. | | Event starvation / JSC hang / native messaging stall | **Не проверено** | Оставлено в diagnostic buckets M3. | | Critical memory pressure как конкретный trigger | **Не воспроизведено** | Не считать root cause без production correlation. | | Network process restart как trigger | **Отвергнуто** | На проверенной сборке CPM восстановился. | | removeAllUserScripts удаляет WebExtension scripts | **Отвергнуто** | WebKit использует RemoveWebExtensions::No. | | Feature-flag transition / scriptlet reload / обычный page JS как all-tabs cause | **Отвергнуто** | Это другой context или tab-local execution. | ## Worktrees Все созданы от локального `origin/main` `570c2f8ef4`. Коммитов нет. Исходный `cpm-breakage-pixel` не изменялся. | Milestone | Branch / worktree | Статус | |---|---|---| | M0 debug/repro | `codex/cpm-debug-tooling` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-debug-tooling` | **Готово:** local-only HTTP iframe churn fixture; localhost HTTP 200. | | M1 tab lifecycle | `codex/cpm-tab-lifecycle-fixes` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-tab-lifecycle-fixes` | **Готово:** три lifecycle fix; 4 targeted tests и macOS build проходят. | | M2 stable base URL | `codex/cpm-stable-base-url` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-stable-base-url` | **Готово:** 11/11 tests; iOS/macOS builds проходят. | | M3 attribution telemetry | `codex/cpm-failure-telemetry` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-failure-telemetry` | **Готово к PR:** passive PII-free facts, forwarding proxy, runtime kill switch; 23/23 tests; schemas iOS/macOS валидны. | | M4 production validation | `codex/cpm-production-validation` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-production-validation` | **Ожидает production data:** runbook готов; начинать после одного telemetry release. | | M5 graveyard mitigation | `codex/cpm-graveyard-mitigation` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-graveyard-mitigation` | **Готово к PR, выключено по умолчанию:** максимум один WKWebView, bounded 3 s hold, unload/reload cleanup, runtime disable; 18/18 tests; iOS/macOS builds проходят. | | M6 graveyard A/B | `codex/cpm-graveyard-ab` — `/Users/admin/DuckDuckGo/apple-browsers.git/cpm-graveyard-ab` | **Готово к PR:** control/treatment, stable cohort, denominator/outcome pixels, bounded pending queue; 30/30 tests; iOS/macOS builds и pixel validators проходят. | Во всех семи worktree проходит `git diff --check`; случайный `Package.resolved` churn удалён. ## PR topology Независимые PR от `origin/main`: 1. M0 — optional/local tooling. 2. M1 — tab lifecycle fixes. 3. M2 — stable base URL. 4. M3 — production telemetry. Последовательный feature stack: ``` M3 telemetry ├── M4 production validation gate └── M5 graveyard mitigation └── M6 A/B experiment ``` Поскольку коммитов пока нет, refs зависимых branches указывают на тот же base SHA, а зависимость представлена накопленным dirty diff. При оформлении: commit M3 → перенести/перебазировать M5 на M3 → M6 на M5. M4 фиксирует Go/No-Go после production данных. ## Rollout gates - M3: privacy review, schema review, затем один production release. - M4: отдельно по iOS/macOS проверить termination reason → initialization failure/stuck и долю per-tab failures. - M5: включать только если M4 подтверждает process-death hypothesis; kill switch и graveyard по умолчанию выключены. - M6: internal/review → небольшой 50/50 sample → проверить cohort balance, denominator/outcome coverage и crash/retention guardrails.