Files
obsidian-vault/work/projects/cpm-readiness-telemetry-tech-design-2026-10-15.md

144 KiB
Executable File
Raw Permalink Blame History

updated
updated
2026-10-20

TD: Pixel Definition: CPM Readiness Telemetry (macOS/iOS)

#7379 — независимый P2 flag, 20 октября 2026: production 55a42802a6, harness a6e6835a5f; новый webExtensions.cpmBackgroundLoadRecovery default ON на iOS/macOS отделяет same-context error-6 retry от cpmMessagingHangRecovery (full-context restart). 271 selected unit PASS, 47 новых shared regression methods; четыре новых independence regressions дают 4 FAIL с прежними связанными проверками и PASS с новым flag. Signed macOS harness и полный iOS app build PASS. CI нового head: 39 SUCCESS / 13 SKIPPED / 4 IN_PROGRESS, без failures (20 октября, 14:16 UTC). Late GET reload по-прежнему default OFF; P4 detection независим. Подробности — в последнем разделе про independent P2 flag.

Current implementation — verified 20 October 2026

The earlier proposal to add parameters to separate failure/recovery pixels has been superseded. The current published #7376 branch (5d1cb4abd2) sends one terminal web_extension_cpm_episode, daily+count, and removes 11 old CPM pixel definitions. The PR is closed without merge despite approved review and green exact-head CI; this is not shipped behavior. The macOS counterpart #7484 has the earlier contract and a base conflict.

The complete current contract, all values, dropped pixels/parameters, frequency and tests are in cpm-pr0-episode-telemetry-summary-2026-10-16. Use it instead of the historical tables below:

  • A four-second native dashboard timeout opens an in-memory episode; an attributed response or an independent five-minute deadline closes it. The deadline does not require another navigation. Count measures completed episodes; daily is deduplicated across every outcome.
  • reason, four-state stuck, outcome, reload_state, optional response_after; four first-failure load fields; eight existing first-failure booleans; bounded bg_events. No generic app_state, open_tabs, loading_tabs, recovery_document or recovery_after is added.
  • stuck=false-one/true-one/false-many/true-many replaces the earlier PR's was_stuck. It reports observed timeouts, without testing all tabs or proving their health.
  • For confirmed stuck episodes, bg_events joins the initial history and events until first stuck with ;; ... marks dropped oldest entries. One 12-event/255-character budget can evict all initial entries. No per-phase reservation is implemented. Ages are relative to each phase; consumers must support both separators and the marker.
  • Readiness/error facts remain frozen at first failure. A later pre-stuck error can now reach the timeline; final outcome of an initially pending load is still missing.
  • No page ACK, last confirmed init stage or network_replaced_since_view is present. Extension progress requires both JS and native work; #7385/#3727 are separate unmerged proposals. #7459's separate daily+count applied pixel counts a restart, not every crash or successful recovery.
  • No identifier, URL or exact timestamp is added. Retained event sequences plus new fields still need combined distinguishability review. The triage summary quoted in the discussion listed was_stuck; approval coverage for the later four-state field/history change was not established by this documentation check.

Current implementation paths and separate fix/harness branches: cpm-web-extension-code-guide-2026-10-09#0. Текущая карта worktree и точек входа. Current PR/CI states, production truncation evidence and remaining diagnostic gaps: cpm-status-2026-10-15.

Historical proposal and validation log — 15–19 October

The following design, tables, “not requested yet”, OPEN/green states and “current” source claims belong to their recorded dates/revisions. They do not override the implementation above. Test failures, retries and scope limits are preserved.

Актуально — 19 октября 2026, error-6/P4 finding закрыт в опубликованном PR. #7379 8275bcce36, база #7376 39fe56af4c, содержит fix fc124938e0 + 2 штатные регрессии. 201 shared PASS, strict lint 4 files / 0 violations. Signed app: ON 9 PASS → OFF 6 ожидаемых functional FAIL → restored ON 9 PASS, 0 SKIP, те же бинарники; первый restored attempt 7 PASS / 2 FAIL (teardown timeout / SIGINT) сохранён, повтор выполнен без изменений и отключения проверок. CI завершён: 43 SUCCESS / 17 SKIPPED, failures/pending нет. Harness 6d04496882 содержит production head и ровно 12 review-only paths; 38 новых shared regressions относительно базы. Проверенный shipping scope: P1/P2 и независимый P4 detection; late reload остаётся default OFF, формы не менялись. Прежние открытые findings ниже — история до fix.

История ревью — 19 октября 2026, до исправления error-6/P4 в fc124938e0. Проверен опубликованный после rebase a00dc4afeb / база #7376 c7adf28e12, 7 commits / 22 paths. Остаётся 1 P2: error-6 startup может ошибочно попасть в P4 detection после позднего callback успешного retry. На текущем head: 196 существующих shared tests PASS + 2 дополнительных probes PASS / 1 новый probe FAIL. Проверочная однострочная правка только в изолированной копии даёт 199 PASS; в PR она не внесена. Pixel validators обеих платформ PASS. CI завершён: 53 SUCCESS / 25 SKIPPED, failures и pending нет; повторный probe подтвердил тот же незакрытый дефект. Предыдущие 197 unit и app 9→6→9 относятся к fc87237a47; новая база убрала один retired-telemetry тест. Подробности и границы воспроизведения — в разделе «Полное ревью после P4 detection — error-6 attribution». История ниже сохранена.

Актуально — 19 октября 2026, P4 detection без reload опубликована и проверена. #7379: production fc87237a47, 7 commits / 22 paths; review-only harness 475095b335, 12 paths вне main. Новый dailyAndCount web_extension_cpm_startup_response_missing считает P4 candidates независимо от late recovery flag, без reload и safety JavaScript. 197 unit PASS, signed macOS и iOS app builds PASS, pixel validators PASS, strict lint 6 production + 2 harness / 0. На одних подписанных app/XCTest binaries: ON 9 PASS → OFF 6 ожидаемых functional FAIL → ON 9 PASS, без skips/expected failures, SHA256 совпали. Новый detection-only case дважды подтвердил detection = 1 / finishCount = 1 / late recovery OFF / no late reload outcomes; оба late OFF controls также дали по detection = 1. CI нового head: 48 SUCCESS / 21 SKIPPED, pending/failures нет. Формы не менялись, late reload flag default disabled. PR steps и все три документа актуализированы; worktree возвращён на чистую production branch. Более ранние heads/results сохранены как история.

Актуально — 19 октября 2026, uninstall fix опубликован. #7379: production e970e8c90e, 6 commits / 22 paths; отдельный review-only harness e380cf98f7, 12 paths вне main. Удаление активного CPM context отменяет pending late-document recovery; удаление старой upgrade-версии и ошибка unload сохраняют recovery. 190 unit PASS, red-before-fix 2 PASS / 1 FAIL, signed macOS и iOS Simulator builds PASS, strict lint 11 / 0. На новом app head проверено на одних подписанных бинарниках: ON 8 PASS → OFF 6 ожидаемых functional FAIL → ON 8 PASS, без skips/expected failures; все app/XCTest SHA256 совпали. CI e970e8c90e: 48 SUCCESS / 21 SKIPPED, pending/failures нет. PR description и reviewer flag steps актуализированы с сохранением ручных правок. Формы оставлены в прежнем виде; late reload flag default disabled. Предыдущие heads/results ниже — история.

Актуально — 19 октября 2026, полный повторный review #7379. Проверен локальный 5708197362 против #7376: 22 changed paths, 187 существующих тестов PASS + 1 новый probe FAIL. Новый P2: uninstall активного CPM context не отменяет pending late-document recovery. Общий launch→navigation deadline и привязка recovery pixel к точной WKNavigation исправлены локально и прошли повторные регрессии; усиление защиты форм явно отложено пользователем, исходная проверка сохранена за default-disabled флагом. В GitHub пока 08866c7eda (CI: 48 SUCCESS / 21 SKIPPED), новые production commits не опубликованы. Локальный review-only harness 4308751d59 синхронизирован; его новый ON/OFF/ON ещё не запускался. Подробности — в конце; прежние heads/results ниже относятся к истории.

Актуально — 16 октября 2026, PR review fixes. В #7379 проверены оба inline замечания: cancellation уже покрыта, повторные 5 секунд на каждую navigation исправлены общим deadline на startup. Production 08866c7eda, 3 commits / 21 paths; review-only harness 3f4d755511, 12 test-only paths, вне main. Проверки: red-before-fix 2 FAIL, после исправления 182 unit PASS, signed macOS build и iOS shared-module build PASS, strict lint 8 / 0; на одних app/XCTest binaries ON 8 PASS → OFF 6 ожидаемых functional FAIL → ON 8 PASS, без skips. Оба review threads resolved; Danger 0 failures, только PR-size advisory; flag tracking links добавлены, defaults не менялись. Пользовательские правки и reviewer steps сохранены. Подробности этого review — в конце. Более ранние heads/results ниже сохранены как история.

Актуально — 16 октября 2026, reviewer ON → OFF → ON. В #7379 восстановлена проверка выключенных production flags. Review-only branch codex/cpm-fix-init-loss-integration-tests / 543e37164b содержит два schemes: CPM Integration Tests → 8 PASS; CPM Integration Tests - Fixes Disabled → ровно 6 functional FAIL; затем normal scheme → снова 8 PASS. Проверено на одних подписанных app/XCTest binaries, без пересборки и изменения Swift code. Production PR da126120a9, 2 commits / 21 files, не менялся; harness остаётся вне main (2 test-only commits / 12 paths). Пользовательские правки PR сохранены. Подробные результаты и artifacts — в конце; прежние односхемные steps и harness head 6e4e39e67c относятся к истории.

Актуально — 16 октября 2026, harness вынесен из PR. #7379: alex/cpm-fix-init-loss / da126120a9, база #7376, 2 коммита / 21 файл, production fixes + 18 новых shared unit regressions. Все local-only app tests, Xcode entries и DEBUG app hooks — только в codex/cpm-fix-init-loss-integration-tests / 6e4e39e67c, один дочерний commit от PR head; эта ветка не идёт в main. Проверено: production app build PASS, unit 179 PASS, harness app 8/8 PASS, strict lint 19+8 / 0. Reviewer steps в PR обновлены и пользовательские правки сохранены. Ниже сохранена датированная история; прежние 3 commits / 32 files и app harness в PR больше не актуальны.

Актуальный итог — 16 октября 2026, после force push. PR #7379 теперь поверх #7376 (alex/cpm-messaging-readiness-telemetry), head aec5be9a83, ровно 3 коммита / 32 файла. Старый worktree cpm-fix-init-loss удалён; текущая директория alex/cpm-fix-p1-p2 теперь на ветке alex/cpm-fix-init-loss. Checkpoint 367759cbc1 и backup старой истории сохранены. Проверка через production feature flags без создания/переключения коммитов: signed app 8/8 PASS ON, 6/6 функциональных FAIL OFF, unit 179 PASS, strict lint 27 / 0, pixel validators обеих платформ PASS. Новый late-reload flag default disabled. Описание PR/шаги и local-only to-be-disabled before merge annotations обновлены; GitHub CI ещё не объявляется green. Подробная финальная сверка — в конце документа. Ниже сохранена датированная история: прежние «не закоммичено», старые head/base и over-budget limitation не являются текущим статусом.

Итог замены #7379 — 16 октября 2026 (Бишкек). В alex/cpm-fix-p1-p2 исправлены оба замечания: ожидание конкретного нового context при install/upgrade и background guard независимо от diagnostics flag. Финальный signed app-набор 4/4 PASS, install/upgrade 10+10 PASS, targeted unit 170 PASS, strict lint 16 files / 0 violations, общий WebExtensions module для iOS Simulator BUILD SUCCEEDED. На тех же бинарниках с выключенными flags 4/4 функциональных negative controls FAIL, без deallocation/infrastructure errors. Коммитов нет, scratch не изменён, ZIP/schema/dependencies не менялись. Сохраняется исходный cap 5 s: startup fixture 5000 ms с WK overhead даёт callback после cap и может потерять первый ответ; этот режим остаётся воспроизводимым известным пределом. Подробности, история красных прогонов и machine summary — в конце cpm-status-2026-10-15.

Изолированная ветка фиксов — 16 Oct, 13:33 UTC. alex/cpm-fix-p1-p2 (/Users/admin/DuckDuckGo/apple-browsers.git/alex/cpm-fix-p1-p2) создана от текущего alex/cpm-messaging-readiness-telemetry / 01d4a0ec22. Выделены P1 navigation wake wait (cap 5 s) и P2 same-context background retry по реальной error 6, с существующими gate/recovery flags и ограничением частоты. Только 2 app-регрессии + 4 новых lifecycle unit-теста; прежние 22 — весь research-набор. Signed app 2/2 PASS, unit 165 PASS, strict lint 0. На тех же бинарниках оба disabled-flag контроля функционально FAIL; deallocation guard в финальном positive run PASS после test-only autorelease fix. База уже использует cpmMessagingEpisode: P2 outcome failed_measurement_response, reload_state none; доставка page initResp и неизменность context проверяются отдельно. Добавлен только read-only recorder isApplicationInBackground для guard, без изменения telemetry schema/ZIP/dependencies. Более поздние baseline/init-progress PR не перенесены. Нет коммитов, исходный scratch сохранён. Артефакты /private/tmp/cpm-p1-p2-clean-20261016/validation-summary.json; история и границы macOS injected-fault доказательства в cpm-status-2026-10-15.

Final local P1/P2 validation — 16 Oct, 12:30 UTC. Current background-only candidate: 22/22 unique app methods PASS across 2+19+1+1 runs (P2 repeated); both disabled-fix controls fail functionally. P2 restores native dashboard and page initResp on the same failed document without navigation or context replacement, with recovered_without_extension_reload / failed_navigation. The full-context-reload prototype was rejected after repeated page-delivery loss. Package: 806 tests, 14 skips, 0 failures; strict lint: 0 violations. No commits, PR mutations or telemetry schema changes. P1's 5 s bound, macOS injected-fault scope, unresolved natural iOS/P3/P5 limits and nonfatal owned-cache SQLite cleanup warning remain explicit in cpm-status-2026-10-15. Earlier pending/20-method statements are dated history.

Interpretation clarification — 16 Oct. The 20 passing app methods do not mean all production-data cases except P3 were reproduced. P1/P2 use injected delay/SIGSTOP; scoped message/native/dashboard loss tests are diagnostic fault injections absent from the shipping bundle. P5/P6 and Network tests exercise browser/WebKit lifecycle paths, under instrumented app-test conditions; occurrence of those exact triggers in affected production sessions remains a separate question. Even with no active scoped fault, the extracted extension carries runtime/DOM observation wrappers. Natural listener metadata loss, P5/tab=true, actual iOS lifecycle/device chains and P3 remain unresolved. The original longer app P5 did not pass and was narrowed to one failed navigation; its limit remains explicit.

Local app validation complete — 16 Oct 2026, 01:48 Bishkek / 15 Oct 19:48 UTC. Twenty app-hosted methods passed with 0 failures, skips or expected failures in three invocations of the same signed build: 18 together, P5 separately, persistent cache separately. This validates the requested slow-load, one-navigation/recovery, single-tab, several-tabs/one-window and all-windows diagnostics scenarios. Source-linked app P1/P2/P5/P6 and Network paths are covered; P3 was not reproduced with 20,000 cached resources, background SIGKILL self-healed, and app P5 proves one lost navigation plus controls. The earlier red joint run and long P5 attempts remain documented. See cpm-status-2026-10-15#Финальный app-hosted итог — 16 октября 2026 for the full matrix, evidence and limits. No commits, PR changes or telemetry schema changes. PR/CI and production-data statements below retain their original dated provenance.

Internal documentation update — 2026-10-15, 17:26 UTC. Current evidence, unresolved review decisions and PR stack: cpm-status-2026-10-15. This update does not approve or implement the proposed schema changes.

PR #7376 is OPEN at 619869ee84c6, review required, with no failing/pending checks; #7384/#7385 remain open and each has a failing Danger status. Their skipped checks are not completed tests. JS #3727 is open, checks successful, review required.

Source-linked P5/shared-window loss and conditional P6/main-flag replacement are now reproduced; natural metadata loss, P5/tab=true and actual production flag transitions remain unproven. The main status contains the full 14-test matrix, page-receipt controls, cold Network PID caveat, 494/499 denominator distinction and pending telemetry simplification decision. No new pixel or parameter was added by those tests. Internal ClickHouse figures stay in Obsidian, not public PR comments or issues.

Author: Alex M
Reviewer: TBD (previous reviewer: Michal)
Stakeholders: Michal, Konrad, Russell (from the previous Tech Designs; confirm for this proposal)
Project: CPM: root-cause the stuck embedded extension messaging (macOS/iOS)
Task: Improve telemetry
Previous Tech Designs: CPM breakage pixels · CPM Failure Diagnostics (cpm-m3-telemetry-privacy-triage)
Privacy Triage: not requested yet; see Privacy below.
Status (checked 2026-10-15, 17:26 UTC): PR #7376 OPEN at 619869ee84c6; REVIEW_REQUIRED; no failing/pending published checks (39 success, 18 skipped entries). Not merged; this check does not establish shipping.
Analysis this builds on: cpm-web-extension-public-attribution-2026-10-05, cpm-web-extension-breakage-session-summary-2026-10-07, cpm-web-extension-code-guide-2026-10-09 (section 3).

Background & Requirements

CPM Failure Diagnostics added process, extension and tab state to the existing failure pixels. The first release with that data (iOS 7.240.0, macOS 1.210.0) showed what it cannot tell apart:

  • Most failure snapshots look healthy: context loaded, background view alive, process responsive. The largest group (about 56% of first failures on iOS, 66% on macOS) has no visible error. A live view does not show whether the background script has run.
  • A background that is still starting (a wake that takes seconds) looks the same as one that is gone.
  • Background load error 6 (BackgroundContentFailedToLoad) is recorded, but not when it happened relative to the view, nor in which app state.
  • Recovery pixels say that CPM answered again, not whether the late answer to the failed navigation arrived, a later navigation answered, or the answer could not be attributed.

Add facts that separate slow starts from lost messages, to the existing failure and recovery pixels.

Problem Statement

Tell apart, per failure and per recovery:

  1. A background still loading when the failure was recorded, from one that finished loading or failed to load.
  2. A failure during a background wake (the view is seconds old) from one long after it.
  3. A background load error cut off by WebKit's 30 s unload timer from one that failed quickly, and the app state it happened in.
  4. A late response from a lost one: did the failed navigation answer after its grace period, did a later navigation, or neither.
  5. A failure with many loading tabs (a busy session restoration) from a quiet one.

Collect no page content, URLs or persistent identifiers.

This proposal covers diagnostic collection only. The failure detector, recovery behavior and reload logic do not change. No experiment.

Keep the existing detection. Extend the existing recorder and pixels with new optional parameters. No new pixel names.

Background readiness. When WebKit creates the background view, an observer records that the load is pending. On the next run loop turn it calls WKWebExtensionContext.loadBackgroundContent. The view already exists, so the call joins the load in progress and does not wake a background. Its completion fires once the background script has run, and records loaded(seconds since view creation) or failed. A response for a replaced view is ignored. readiness(of:) answers only for the current view. The observer is attached by the same switch as the delegate proxy (cpmBackgroundDelegateProxy).

Error 6 timing. When error 6 is recorded, the recorder also records the app state and the seconds since the failing view was created. Values near 30 s point at WebKit's unload timer.

Snapshot additions. When a failure pixel fires, the recorder adds app state, background view age, background readiness and tab counts, read synchronously on the main actor. The app supplies the app state (UIApplication.applicationState on iOS; NSApp.isActive mapped to active/inactive on macOS). Facts that cannot be read are omitted.

Recovery details. The health monitor already tracks an episode. On recovery it now says which navigation answered, and the time since the episode's first failure, bucketed. Detector behavior is unchanged.

Pixels

No new pixels. Parameters are added to existing ones.

Pixel Change
debug_web_extension_cpm_initialization_failed_after_<reason> (4 reasons × daily) Failure parameters below.
debug_web_extension_cpm_messaging_stuck_<reason> (4 reasons × daily + count) Failure parameters below.
debug_web_extension_cpm_messaging_recovered_without_extension_reload Recovery parameters below.
debug_web_extension_cpm_messaging_recovered_after_extension_reload Recovery parameters below.

<reason>: session_restoration, tab_crash, extension_reload, other. Eight failure pixels and two recovery pixels per platform. Names, triggers and frequencies are unchanged. iOS defines them in debug_pixels.json5, macOS in web_extensions.json5; both add the parameters to params_dictionary.json5.

Failure / stuck parameters

Unavailable optional facts are omitted. PIDs, URLs and tab identifiers are never sent.

Parameter Values
app_state active, inactive, background. macOS reports only active / inactive. Omitted if the app does not report it.
bg_view_age Time since the current background view was created: under_4s, 4s_to_8s, 8s_to_30s, 30s_to_2m, over_2m. Omitted if there is no background view.
bg_ready_after none (no background view), pending (still loading), failed, or time from view creation to load completion: under_1s, 1s_to_4s, 4s_to_10s, 10s_to_30s, over_30s. Omitted if readiness is not observed (observer flag off).
open_tabs Tabs in WKWebExtensionContext.openTabs: 0, 1, 2_to_5, 6_to_10, 11_to_20, 21_to_50, over_50.
loading_tabs How many of those tabs were loading: 0, 1, 2, 3_to_5, over_5.
bg_load_error_app_state App state when error 6 was last recorded for this context: none (no error 6), active, inactive, background. Omitted if unknown.
bg_load_error_after Time from view creation to that error 6: none, under_5s, 5s_to_25s, 25s_to_35s, over_35s. The 25s_to_35s bucket surrounds WebKit's 30 s timer. Omitted if unknown.

bg_view_age and bg_ready_after use buckets around the monitor's 4 s grace period and WebKit's 30 s timer. They are boundaries chosen for the questions above, not measured thresholds.

Recovery parameters

Parameter Values
recovery_document failed_navigation (the navigation that failed answered after its grace period: late, not lost), later_navigation, unattributed (a response matched an open document but no single tab).
recovery_after Time from the episode's first failure to recovery: under_4s, 4s_to_10s, 10s_to_30s, 30s_to_2m, over_2m. A failure is reported 4 s after the navigation finished.

Existing recovery_from is unchanged.

Testing

  • Unit tests: bucket boundaries, parameter serialization and omission rules, error 6 timing (including none versus unknown), readiness (loaded, failed, replaced view, observation off), app state, open and loading tabs on a real controller with a navigation that does not finish, recovery details and buckets in the health monitor. 115 tests in the affected suites pass locally.
  • Pixel validation: both platforms' schema validators run in CI.
  • Real WebKit: during development the harness was temporarily copied into this branch. A background start slowed to 5 s produced bg_ready_after=pending, bg_view_age=4s_to_8s, then recovery_document=failed_navigation with recovery_after=under_4s. This was a manual check; it is not in the PR. The CPM repro harness (PR #7378) can reproduce it in CI once it lands.
  • Privacy validation: inspect the real payloads and confirm no URLs, identifiers or message content. Not done yet.

Additional Considerations (if applicable)

Privacy

Adds enumerated, bucketed parameters to existing pixels; no page content, URLs, search queries, message payloads, tab/context identifiers or PIDs. App state, tab counts and timings are bucketed. These are new parameters on existing pixels, so Privacy Triage is required before release. I have not requested it.

Security

No new private WebKit selectors. loadBackgroundContent is a public API.

Site Breakage

No intended page-behavior changes. The one behavioral addition is the loadBackgroundContent call on a background view that already exists. It should join the load in progress and wake nothing, but the earlier delegate proxy changed the reproduction of this bug once, so check the observer with its flag on and off. A background wake the observer causes would also corrupt bg_ready_after.

Experimentation

None.

Operational

  • The observer shares the cpmBackgroundDelegateProxy switch; the recorder and its snapshot additions follow cpmDiagnosticsRecorder. No new flag. Whether sharing is acceptable needs a decision from the flag owner, because turning the proxy off also turns readiness off and the parameter disappears.
  • Update the CPM Grafana board for the new fields.
  • Diagnostic removal is still planned for approximately November 2026; no removal date is enforced in code.
  • The limits of the previous Tech Design stand: failure-only snapshots cannot measure failure rates across all process deaths or prove that every tab failed.
  • bg_ready_after tells whether the background script ran. It does not tell whether the init message for a given document reached it. That needs per-message timings (content init sent, background init received, initResp sent and received, dashboard refresh sent and received), which is the next telemetry candidate and out of scope here.

Localization / Internationalization

None.

App-hosted validation, 16 October 2026

A separate local suite now runs inside the signed DuckDuckGo.app, using actual AppDelegate lifecycle/flag callbacks, Tab/MainWindowController/WindowsManager, macOS WebExtension providers/native delegate, production monitor/recorder and system WebKit. Worktree: cpm-e2e-init, macOS/IntegrationTests/CPM/; scheme CPM Integration Tests, without profile-cleaning pre-actions. No commits or PR changes.

The ten core methods passed together (signed-core.xcresult, 0 failures): healthy baseline, slow HTTP document, slow native settings, one failed navigation followed by recovery, persistent single-tab failure, several tabs in one window, all windows including a newly opened tab, automatic M4 recovery, dashboard-transport negative control, and a runtime diagnostic-proxy flag cycle. Healthy checks require page-side initResp as well as a forwarded real native dashboard message. Fault scopes are injected into a temporary extracted copy at the extension messaging boundary; navigation/monitor events are not fabricated.

Observed library metadata: message loss gives init_stage=none; delayed settings gives received, then recovery on failed_navigation (4s_to_10s); a missing dashboard confirmation despite page receipt gives response_sent; later-document recovery is later_navigation. These are metadata captured before the platform pixel adapter/daily deduplication, not proof of an actual production HTTP payload or production causal attribution. JSON artifacts contain only owned fixture page URLs and test observations; pixel parameters remain the existing bucketed metadata.

Additional app/WebKit characterization tests cover real shared-pinned-window closure, main/embedded flag transitions, startup race, process termination, slow idle wake and the real error-6 load timeout. Their final outcomes and the preserved red experiments are tracked in cpm-status-2026-10-15#13. Integration tests в настоящем приложении — реализация и проверки. iOS lifecycle and natural listener-metadata loss remain unproven by the macOS suite. The initial unsigned CLI workaround was unnecessary; the original project signing configuration builds successfully and is used for the reported results. The temporary vault bypass has been removed.

Scope and source-linked characterization follow-up

The known-path methods also execute the real AppDelegate main/embedded flag transitions (including a first main enable), actual shared-pin window closure, the owned test host's WebKit process faults and cache reload. P5's final app method passed (signed-pinned-single-probe.xcresult, 73.806 s): after two healthy/idle cycles, real window closure causes one failure with no page initResp, tab_in_context=false, matching controller and background creation bucket 2; regular and new-tab controls remain healthy. Longer app attempts reached the enabled DEBUG MainWindow lifetime guard during the second timeout and remain documented as red experiments. Persistent P5/stuck proof belongs to the separate SPM suite, not this narrower app method.

The persistent-cache characterization now completes cleanup (signed-large-cache-session-end.xcresult, 47.519 s). A fresh UUID website/controller profile actually receives 20,000 cacheable resources and has disk-cache records; real reload changes the extension baseURL. In that run, immediate post-reload messaging was healthy and p3NoBackgroundFailure=false. Passing this test means the experiment and recovery/cleanup controls succeeded; P3 itself was not reproduced. _terminateNetworkProcess is used only in teardown of the owned test host, after evidence capture/data clearing, to permit removal of that UUID store. It adds no selector to production diagnostics and changes no telemetry schema.

P1 slow idle wake and P2 real WebKit load timeout have signed app passes; the latter records actual error 6 near the 30-second deadline after stopping the owned worker. These are macOS mechanisms, not proof of the causal attribution of iOS production groups. Runtime listener-metadata loss, iOS suspend/resume/device errors and actual production flag changes remain unresolved. The final current-source regression outcome will be recorded in the main status; original CI/PR and ClickHouse snapshots above are dated 15 October and have not been refreshed by these local app tests.

Final current-source verification

The final build uses owned UUID extension resources under unswizzled NSTemporaryDirectory(), outside TestRunHelper's shared cleanup root. The same 18-method selection that previously failed now passes completely (signed-isolated-regression.xcresult): actual Network termination fails 4/4 tabs across two windows and explicit reload/readiness restores all four; the following slow-wake test also passes. The prior deleting actor remains unidentified. Final P5 passes separately in 72.644 s; persistent cache passes separately in 43.053 s, records p3NoBackgroundFailure=false, and removes its own UUID store. All three XCTest summaries have zero failures, skips and expected failures. The 20 exported reports, source hashes and trial history are indexed by /private/tmp/cpm-app-integration-20261015/app-test-results.json. Strict SwiftLint on all 11 changed Swift files has zero violations; both Integration Tests targets contain the six new test files. Main app/XCTest use normal Apple Development signing; no unsigned or SecureVault bypass remains. The nested VPN Debug packaging deep-verify limitation is recorded in the main status and is not claimed fixed.

Rerun requested by user — 16 Oct 04:37 UTC

Current versions of the formerly failed selections passed again: 18+1+1 methods, zero XCTest failures/skips/expected failures, same signed binary/source hashes. Artifacts: /private/tmp/cpm-app-integration-20261015/rerun-failed-20261016-042858/rerun-summary.json. P3 remains negative (20k cache entries). Cache teardown logs a nonfatal SQLite vnode unlinked while in use warning for its owned store; this infrastructure warning and the historical longer P5 limitation are not claimed resolved. The current P5 repeats one failed navigation plus controls; the old two-timeout source variant was not rerun as if fixed. Repeatability does not change the controlled-fault versus production-cause boundary documented at the top of this design.

P1/P2 local fix validation — 16 Oct, background-only candidate

The first P2 full-context-reload prototype was rejected: a repeated real error-6 test lost the existing page's initResp despite a successful native dashboard. The current local candidate preserves WKWebExtensionContext and retries the public background-load API after the actual load-error notification. Its app regression requires recovery of the same failed document without navigation or context replacement, with both native dashboard and page initResp; the observed pixel is recovered_without_extension_reload / recovery_document=failed_navigation / recovery_after=30s_to_2m. The existing confirmed-hang M4 remains the full-reset fallback.

P1 prepares background on each main-frame web navigation with a real 5 s bound/cancellation; the imposed 8 s startup now yields a healthy first document. This neither accelerates worker execution nor establishes a universal fix for longer delays. P1/P2 point cases initially passed 2/2; the package passed 806 tests with 14 opt-in skips, 0 failures. Full final app matrix, disabled-fix controls and limits remain in cpm-status-2026-10-15 and /private/tmp/cpm-p1-p2-fixes-20261016/. No telemetry schema change, commit, PR mutation or iOS production attribution is implied.

Проверенный контракт замены #7379 — 16 октября 2026

alex/cpm-fix-p1-p2 объединяет ID-specific install/upgrade wait, P1 idle wake и P2 background retry. Новый context фиксируется при install до удаления старого; навигация захватывает именно этот object. isApplicationInBackground теперь отдельный input менеджера, iOS factory читает UIApplication напрямую и не зависит от cpmDiagnosticsRecorder. Diagnostics getter прежнего кандидата удалён. Retry отвергает superseded context и повторно проверяет flag/background перед WK call.

Contract regression default — 4500 ms worker delay при прежнем 5 s cap, строгие native dashboard + page initResp assertions. 4/4 app PASS, install/upgrade 10/10 + 10/10 PASS, 170 PASS unit, lint 16 files / 0 violations; iOS shared module SDK build PASS. На той же сборке gate/recovery OFF дают 4/4 ожидаемых функциональных FAIL, без teardown errors. Это не новые unique cases: повторяются 2 метода; всего в ветке 4 app + 9 новых unit methods.

Граничная конфигурация 5000 ms через CPM_APP_INTEGRATION_INSTALL_DELAY_MS сохраняет известный failure: реальные WK callbacks 5.150336/5.184716 s приходят после cap, upgrade ранее FAIL 6/10. Этот режим не исправлен, timeout не увеличен, assertions не ослаблены. Реальный iOS app suspension/resume не запускался. Все результаты, включая красную историю: /private/tmp/cpm-p1-p2-replacement-20261016/validation-summary.json, cpm-status-2026-10-15. Source hashes стабильны, ZIP/schema/dependencies и scratch не изменены, коммитов нет.

Дополнение: late background recovery — 16 октября 2026, работа продолжается

По запросу сначала сохранён прежний проверенный стейт: commit dff29dfb1e (Fix CPM background wake and installation readiness) в alex/cpm-fix-p1-p2. Предыдущие утверждения «коммитов нет» относятся к проверке до этого checkpoint. Новые изменения пока не закоммичены.

Добавлен кандидат восстановления потерянного первого документа при startup за пределами 5 s: отдельный remote flag webExtensions.cpmLateBackgroundDocumentRecovery, default disabled. Navigation cap остаётся 5 s. Кандидат привязывает документ к конкретному unfinished startup, требует настоящий missing-dashboard timeout и успешный public WK background callback; после этого допускает одну GET-перезагрузку в пределах 30 s от старта. Смена/закрытие/ошибка документа, context replacement, background app state, выключение flag, изменённые form fields/contenteditable/loading document отменяют reload. Логика независима от diagnostics flag.

Пять новых dailyAndCount pixels различают install readiness, upgrade readiness, idle background wake, error-6 background retry и late document reload. background_ready — факт успешного WK callback после использованного navigation wait (для error-6 retry — любого успешного retry), не доказательство initResp; reload_started — принятый WK reload; response_received — однозначно атрибутированный dashboard response после reload, не ACK content script. App tests отдельно требуют настоящий page initResp. macOS names заканчиваются _macos, iOS — стандартные platform/form-factor suffixes. Только outcome, appVersion и стандартные platform parameters, без URL/tab ID/form values/raw error.

На данном этапе: targeted unit suite 178 PASS, strict lint 17 Swift / 0 violations, pixel definitions + wide-event consistency/immutability validators обеих платформ PASS. Подписанная app-сборка и реальные install/upgrade 8000 ms regression runs ещё не завершены; over-budget failure пока НЕ объявлен исправленным. Новые артефакты: /private/tmp/cpm-late-recovery-20261016/.

Итог late background recovery и fix instrumentation — 16 октября 2026

Актуальный стейт: checkpoint dff29dfb1e сохранён до новых изменений; новый код/tests/pixels в alex/cpm-fix-p1-p2 остаются незакоммиченными. Новый flag webExtensions.cpmLateBackgroundDocumentRecovery default disabled, динамически проверяется до попытки и после async safety check; remote config не менялась. Navigation cap по-прежнему 5 s.

Новый CPMBackgroundReadinessRecovery.swift в shared Autoconsent получает startup UUID manager, commit/failure/response/navigation events monitor и зарегистрированный GET WKWebView от platform tabs. Документ должен commit во время известного unfinished startup; только genuine missing-response timeout вместе с successful public background callback допускают одну GET-перезагрузку в пределах 30 s startup. Изменённый/loading/closed/failed document, main-document form edits/contenteditable, background app state, flag OFF и context replacement запрещают reload. Идентичность проверяется после async JS. Результат — replacement document на том же URL, сохранённый extension context; P2 background-only recovery исходного документа остаётся отдельным механизмом. Safety check использует настоящий async WK API label contentWorld:; ранние красные app runs поймали ошибочный callback overload с Void, и вся история сохранена.

Пять отдельных dailyAndCount pixels с prefix web_extension_cpm_: install_readiness, upgrade_readiness, background_wake, background_load_retry, late_document_reload. macOS suffix _macos, iOS standard suffixes. Первые четыре: background_ready после использованного slow navigation wait (для P2 любого successful retry), без page-ACK claim; последний: reload_started и однозначный dashboard response_received после replacement navigation. Ответ исходного документа во время safety check не получает credit. Только outcome и стандартные параметры, без URL/tab IDs/field values/raw errors. Injection + PixelKitMock adapter test, definitions/validators обеих платформ PASS. Existing episode contract сохранён; document reload даёт failed_tab_response, extension reload_state=none.

Проверено на одной финальной подписанной сборке: общий набор 8/8 PASS (7 app/WebKit scenarios + adapter test); новые 8-second install/upgrade 2/2 PASS, затем 10/10 repetitions PASS; новый flag OFF 2/2 функционально FAIL, 0 skips/expected failures/teardown errors. Во всех 14 positive over-budget executions первая загрузка 5.085–5.328 s, затем ровно один reload, настоящий page initResp + native dashboard, URL/context сохранены. Edit-veto app test PASS; прежние P1/P2/install/upgrade PASS. Targeted units 179 PASS (9 новых recovery; всего 18 новых unit methods в ветке), lint 17 files / 0 violations, новый recovery без compiler warnings. Shared iOS Simulator и FeatureFlags-iOS builds PASS; полный iOS app/runtime не запускался.

Code entry points: manager background startup callback/typed fix marker; monitor backgroundReadinessRecovery и registerReadinessRecoveryDocument; macOS PrivacyDashboardTabExtension weak view + real initiating request method; iOS TabViewController main-frame GET tracking; platform factories dedicated provider; PixelFiring adapters + platform JSON5 definitions. Все 8 app methods остаются в существующем CPM file/scheme; SharedPackages files подхватывает SwiftPM без pbxproj изменений.

Все facts/history/guards/pixel semantics: cpm-status-2026-10-15, /private/tmp/cpm-late-recovery-20261016/validation-summary.json. Source/app/test binary hashes стабильны; bundled ZIP равен checkpoint; package pin side effect убран; scratch/#7379 не менялись. Это opt-in bounded GET recovery, не универсальное исправление permanent background failures/unsafe documents. Прежние P3/P5 и natural-production/iOS suspension ограничения не сняты; 22 historical research methods отдельно.

Перенос в PR #7379 поверх #7376 — 16 октября 2026

Git и состав PR

По запросу до переноса сохранён checkpoint 367759cbc17d717b05e53ab30792c077ff103a8b в alex/cpm-fix-p1-p2 (предыдущий checkpoint dff29dfb1e также сохранён). Старый чистый worktree /Users/admin/DuckDuckGo/apple-browsers.git/cpm-fix-init-loss удалён штатно; локальные ignored settings сохранены в /private/tmp/cpm-pr7379-port-20261016/retired-worktree-local-settings.tar.gz. Research worktree cpm-e2e-init и его незакоммиченные данные не менялись.

Рабочая директория остаётся /Users/admin/DuckDuckGo/apple-browsers.git/alex/cpm-fix-p1-p2, но её текущая ветка теперь alex/cpm-fix-init-loss. Финальный HEAD aec5be9a834e97984d4cbbee01a207548222427c, ровно 3 коммита / 32 изменённых файла поверх #7376, base branch alex/cpm-messaging-readiness-telemetry, base SHA 713d67419a776b235b66210b1c594ce39da6fe03:

  1. 05b499e355 — P1/P2, ожидание нового install/upgrade context и необходимые app/unit tests.
  2. c661f805b1 — late GET document recovery, независимый flag, пять fix pixels, регрессии.
  3. aec5be9a83 — маркировка local-only fault-injection suite/scheme/README как to-be-disabled before merge.

PR #7379 обновлён разрешённым force-with-lease с точным ожидаемым старым head 7ad771e227bbd68348ed7b719684783575dd7c9f; новый head/base проверены через GitHub. Старый head и промежуточная история сохранены в backup branch alex/cpm-fix-init-loss-before-force-20261016 (70869f5c69). Зависимость от #7378/research SPM harness убрана из diff; episode contract #7376 сохранён. Промежуточный перенос на прежнюю базу с 167 unit tests — историческая попытка, окончательный результат относится к новой базе и 179 tests.

PR title/description/Testing Steps переписаны под окончательный код. Коммитить или переключать test-only/fix commits для проверки не требуется. Удалены старые инструкции и placeholder GREEN_RUN_URL; используется одна подписанная сборка с переключением production flags в test fixture.

Feature flags

Механизм Remote flag Default
Install/upgrade readiness + P1 navigation wake wait webExtensions.stateRestorationGate Enabled, существующий
P2 background-only error-6 retry webExtensions.cpmMessagingHangRecovery Enabled, существующий
Late first-document GET reload webExtensions.cpmLateBackgroundDocumentRecovery Disabled, новый независимый

Флаги явно задаются fixture; ENV CPM_APP_INTEGRATION_DISABLE_P1_P2_FIXES=1 и CPM_APP_INTEGRATION_DISABLE_LATE_RECOVERY=1 выбирают соответствующие negative controls без изменения исходников или binary. В двух over-budget controls отключается late recovery при сохранённом 5 s navigation gate, чтобы изолировать новый механизм. Remote configuration не изменялась.

Финальная проверка запушенного head aec5be9a83

Новый прогон на базе #7376, macOS 26.7.1, Xcode 27.1, нормальная подпись Apple Development: Alexey Martemyanov (9SAT8X9S84) / team HKE973VLUW. Проверены identity подписи app и strict signatures app debug dylib / XCTest bundle; это не заявление о distribution signing/notarization или полной deep-проверке вложенных продуктов.

Проверка Результат
Все восемь методов dedicated app suite, соответствующие flags ON 8/8 PASS, 0 failures/skips/expected failures
Шесть recovery controls, соответствующие flags OFF, те же бинарники 0/6 PASS, 6 функциональных FAIL, 0 skips/expected failures, без teardown/deallocation errors
Targeted shared suites 179 PASS, 0 failures/skips (13 diagnostics + 9 recovery + 78 monitor + 31 lifecycle + 48 manager)
Strict lint относительно новой PR base 27 Swift files, 0 violations
Pixel schemas/formatting + wide-event consistency/immutability macOS и iOS PASS
Source/binary integrity Все 32 source hashes и 2 app/test binary hashes неизменны; git status чистый

Положительный набор: P1 slow idle wake, P2 реальная WK error 6 с background-only retry и ответом исходному документу без навигации, install, upgrade при coexistence contexts, late install, late upgrade, edited-document veto и PixelKitMock adapter. При 8000 ms startup в новых late install/upgrade runs первый документ завершился за 5.159 / 5.093 s, затем ровно один automatic reload (итого два finish), настоящий page initResp и native dashboard, URL/context сохранены. Navigation cap остаётся 5 s. Отдельные десять stress repetitions и более ранние iOS module/flags builds относятся к предыдущему checkpoint/проверке, не объявляются новым stress/iOS runtime run на этом head.

Красные controls на той же сборке: install/upgrade теряют первый native/page ответ; P1 получает response timeout; P2 достигает реальной error 6, но без flag не получает same-document recovery; оба over-budget случая не получают automatic document recovery. Это намеренные функциональные FAIL, не инфраструктурные crashes и не XCTExpectFailure. У controls и positive runs отдельные .xcresult / summaries / JSON attachments.

Local app suite, setup и dedicated scheme/README помечены to-be-disabled before merge. Они уже требуют CPM_APP_INTEGRATION=1 и пропускаются обычным CI без opt-in. Сценарии используют GUI-host и 45 s SIGSTOP только собственного background PID; deterministic unit regressions оставлены включёнными. General macOS UI Tests scheme локально не запускалась из-за её profile-clearing preaction.

Артефакты нового прогона: /private/tmp/cpm-pr7379-final-20261016/validation-summary.json, рядом enabled.xcresult, disabled.xcresult, JSON evidence, logs, signature/hash snapshots, pr-after.json, финальный PR body и CI snapshots. Bundled extension ZIP неизменён относительно base/checkpoint: SHA256 ff98a2b0c07819b2ee5ee6de67d6dd8d28696363c08c9fbc2c32255e9d9efa94; package pin side effect убран. Прежние red runs и расследовательские данные сохранены.

Новый remote CI после push запущен; локальный PASS не выдаётся за завершённый зелёный GitHub CI. Контракт fix pixels остаётся прежним: background_ready — callback readiness, response_received — dashboard correlation после reload; page ACK проверяет app assertion отдельно. Default-disabled late flag не включался в remote config. Natural production attribution, unreproduced P3, прежние P5 app ограничения и реальный iOS suspension/resume этой работой не закрыты.

GitHub checks после push

Финальная сверка CI для aec5be9a83: основные jobs ещё IN_PROGRESS/QUEUED; Danger — FAILURE, точная причина — новые pixels требуют label privacy review required, который создаёт privacy-review task в Asana. Label в этой работе не менялся. Дополнительно Danger предупреждает об отсутствующем Asana Feature Flags project task link для cpmLateBackgroundDocumentRecovery в macOS/iOS enum comments и размере PR; это warnings, не причина функциональных app failures. Значения flags и локальные ON/OFF результаты выше подтверждены независимо. Evidence: /private/tmp/cpm-pr7379-final-20261016/danger-comment.md, ci-final.json.

Вынос app harness из PR #7379 — 16 октября 2026

По запросу весь local-only app harness вынесен в отдельную review-only ветку codex/cpm-fix-init-loss-integration-tests, основанную непосредственно на очищенном alex/cpm-fix-init-loss. Тестовая ветка не предназначена для merge в main, отдельный PR на неё не создавался.

  • Production PR #7379: head da126120a94b625cf1d9705302c29099b4dbc62d, база #7376 / 713d67419a, 2 коммита, 21 файл. 7dbe2a25bb — P1/P2/install/upgrade; da126120a9 — late recovery + flags/pixels. Все 21 production/unit/schema файла побайтово совпадают с прежним aec5be9a83; поведение и defaults не менялись.
  • Harness branch: head 6e4e39e67c64907127bd17197a932b0117a4cb09, parent ровно production head da126120a9, один дополнительный commit, 11 test-only paths. Это пять Swift app-test files + README, CPM scheme и PBX registrations, DEBUG manager factory/config storage/loopback navigation hooks в AppDelegate, ConfigurationStore, Tab.
  • Все app hooks и Xcode project changes исключены не только из финального diff PR, но и из его двух новых коммитов. 18 новых deterministic shared unit methods остаются в production PR; восемь app methods — только в harness branch.
  • В harness комментариях прежнее to-be-disabled before merge заменено на ясное review-only назначение: эта ветка не идёт в main. Explicit scheme opt-in сохранён. Старые checkpoints и исходная история сохранены; дополнительный backup codex/cpm-fix-init-loss-before-harness-split-20261016 -> aec5be9a83.
  • Reviewer instructions в PR: unit suites на PR branch; git fetch origin, git switch --detach origin/codex/cpm-fix-init-loss-integration-tests; открыть workspace, выбрать CPM Integration Tests / My Mac, ⌘U, ожидать 8 PASS / 0 skips; затем вернуться git switch --detach origin/alex/cpm-fix-init-loss. Production description и пользовательские правки сохранены. Исторические intentional-red controls не возвращены в reviewer steps.

Артефакты разделения: /private/tmp/cpm-harness-split-20261016/: manifest с production/harness paths и исходными SHA256, раздельные patches, build/unit/lint/signing logs и snapshots PR description. Точные окончательные результаты новой проверки и remote SHA — ниже.

Проверка после разделения

  • Production da126120a9: обычная macOS Browser Debug app build PASS без harness; нормальная Apple Development подпись, team HKE973VLUW; strict app dylib verification PASS.
  • Production shared regressions: 179/179 PASS, 0 failures/skips; 18 новых unit methods сохранены в PR.
  • Review-only harness 6e4e39e67c: полный xcodebuild test (эквивалент Product → Test), 8/8 PASS, 0 failures/skips/expected failures, отдельная подписанная app/XCTest сборка. Все 32 source hashes неизменны во время run; strict dylib/XCTest signature checks PASS.
  • Strict lint: 19 production Swift files / 0 violations, 8 harness Swift files / 0 violations. PBX syntax и scheme XML валидны; каждый из пяти harness Swift files зарегистрирован ровно по одному разу в обоих native Integration Tests targets. Выполнен normal signed target, не отдельный App Store runtime run.
  • Подтверждены remote SHA обоих branches и GitHub PR diff: production da126120a94b625cf1d9705302c29099b4dbc62d, harness 6e4e39e67c64907127bd17197a932b0117a4cb09; parent harness совпадает с production head. Production PR остаётся на базе #7376. В рабочей директории снова alex/cpm-fix-init-loss, git status чистый.
  • validation-summary.json, pr-after.json, remote-heads.txt, harness-enabled.xcresult и JSON evidence находятся в /private/tmp/cpm-harness-split-20261016/. Generated Package.resolved side effect сохранён и убран из рабочей копии; production dependencies/ZIP не менялись.
  • Новые шесть disabled controls после branch-only split не повторялись: предыдущие 6/6 functional FAIL на эквивалентном production/harness code остаются историческим evidence в /private/tmp/cpm-pr7379-final-20261016/. Нового stress/iOS runtime run не заявляется. P3, прежние P5 app и natural-production/iOS ограничения сохраняются. Remote CI нового head — отдельная незавершённая проверка, snapshot ci-after-split.json.

Ранние формулировки о local-only suite внутри production PR и необходимости disable перед merge описывают прежнюю структуру. В актуальном PR этих файлов и hooks нет; review-only branch целиком остаётся вне main.

Возврат проверки production feature flags OFF → failures — 16 октября 2026

При упрощении reviewer instructions ошибочно удалён необходимый negative-control шаг. В PR #7379 восстановлен полный ON → OFF → ON workflow с конкретными Xcode schemes; остальные пользовательские правки сохранены.

В review-only branch codex/cpm-fix-init-loss-integration-tests добавлен commit 543e37164b369c8da8b6734e500af4a203944943, только два файла: новый shared scheme CPM Integration Tests - Fixes Disabled и README с точными cases/flags/ожидаемыми failures. Эта ветка теперь содержит 2 test-only commits / 12 paths сверх production da126120a9; в main она не идёт. Production PR остаётся 2 commits / 21 files, его head/code/unit regressions не менялись.

  • CPM Integration Tests → 8 tests должны PASS.
  • CPM Integration Tests - Fixes Disabled → автоматически выбирает ровно 6 recovery methods и задаёт обе fixture ENV variables CPM_APP_INTEGRATION_DISABLE_P1_P2_FIXES=1 / CPM_APP_INTEGRATION_DISABLE_LATE_RECOVERY=1. Ожидаются 6 functional FAIL / 0 PASS / 0 skips.
  • Снова CPM Integration Tests → все 8 должны PASS.

Ручное редактирование ENV или выбор отдельных tests reviewer больше не нужны. OFF scheme через fixture отключает реальные production flags: webExtensions.stateRestorationGate для install/upgrade/slow wake, webExtensions.cpmMessagingHangRecovery для error-6 retry, webExtensions.cpmLateBackgroundDocumentRecovery для late GET recovery. Late recovery выключен и в ранних controls, чтобы не маскировать их; в двух over-budget controls navigation gate сохраняется ON.

Ожидаемые причины FAIL: потерянный native/page first response после install/upgrade; CPM timeout после slow wake; timeout same-document recovery после реальной WK error 6; timeout automatic first-document recovery в late install/upgrade. Setup failures, host crashes или skips не подтверждают работу флага. Полные test names и mapping находятся в README тестовой ветки. В PR сохранены checkout/test/return commands и добавлен возврат к ON scheme.

Артефакты этой проверки: /private/tmp/cpm-flag-controls-20261016/; compiler/test Swift sources и production ref не менялись. Предыдущие 179 unit PASS / production build PASS остаются предыдущей проверкой, не объявляются новым unit/build run.

Финальная проверка ON → OFF → ON

Baseline normal scheme на 6e4e39e67c ранее дал 8/8 PASS. После добавления только OFF scheme/README на 543e37164b выполнены оба shared schemes через xcodebuild test-without-building -workspace DuckDuckGo.xcworkspace -scheme … на тех же подписанных app/XCTest binaries:

Run Результат
CPM Integration Tests - Fixes Disabled 6 failed / 0 passed / 0 skipped / 0 expected failures, exit 65
CPM Integration Tests после OFF 8 passed / 0 failed / 0 skipped / 0 expected failures, exit 0

У OFF все шесть failure records сопоставлены точным test names и ожидаемым функциональным причинам; никаких deallocation/setup failures или подмены через XCTExpectFailure. Возврат ON восстанавливает PASS для прежних P1/P2/install/upgrade, обоих late cases, edit veto и pixel adapter. SHA256 app debug dylib и XCTest binary неизменны до/после обоих runs, Swift sources не менялись относительно baseline harness. Remote config и production defaults не редактировались.

Artifacts: /private/tmp/cpm-flag-controls-20261016/validation-summary.json, off.xcresult, on.xcresult, summaries, exported JSON evidence, binary-hashes-before.json, pr-after.json, source/branch verification. Это новая runtime-проверка переключения flags, без нового production build/unit run. Reviewer теперь выбирает два готовых schemes: не редактирует ENV вручную, не выбирает шесть methods и не переключает commits. Production PR и прежние P3/P5/natural-production/iOS ограничения сохраняются.

16 октября 2026 — исправления замечаний review #7379

Production head: 08866c7eda9b1395f7c0baf9887c827bd3f59ec5, branch alex/cpm-fix-init-loss, PR #7379, база #7376 / alex/cpm-messaging-readiness-telemetry / 713d67419a. Три commits / 21 changed paths. Новый commit Share CPM startup deadline across navigations изменяет 8 существующих Swift files; app fixture/hooks в production diff не возвращены. Production и review-only branch обновлены обычным push без переписывания истории.

Что проверено и исправлено

  • Замечание о неотменяемом Task.value: исходное замечание уже было закрыто реализацией cancellable AsyncStream bridge и regression testBackgroundWakeWaitIsBoundedWhenWebKitIgnoresCancellation. Проверено повторно на текущем коде: timeout освобождает navigation, даже когда реальный startup task не реагирует на cancellation; физический WebKit startup не отменяется.
  • Повторные пять секунд на каждом navigation: замечание оказалось актуальным по поведению, несмотря на устаревшее имя файла в тексте. Раньше каждый waiter имел отдельный deadline. Теперь manager возвращает стабильный Task текущего startup, а coordinator хранит один bounded wait для его identity. Оба уже подготовленных waiter и последующие navigation после timeout используют завершившийся wait и не платят ещё по 5 секунд.
  • Новый startup/replacement получает собственный deadline. cancelAll() отменяет только navigation wait и очищает его cache. Startup completion очищается при matching uninstall/unload/reload/error-6 retry или замене context; поздний callback старого task не может очистить текущий startup. Timeout сам по себе не отменяет background: поздний успешный callback по-прежнему может запустить отдельный late-document recovery.
  • В Mac PrivacyDashboardTabExtension и iOS TabViewController вызов provider ограничен main-frame HTTP(S), поскольку получение task теперь сразу запускает подготовку background. Iframes и другие URL schemes не начинают этот startup через navigation gate.
  • Добавлены три CI unit regressions: testTimedOutBackgroundStartupDoesNotDelayLaterNavigations (включая waiter, подготовленный до истечения deadline), testNewBackgroundStartupCanWaitAfterEarlierStartupTimesOut, testCancelAllReleasesPendingBackgroundNavigation. Test double сохраняет identity pending startup; зависший callback моделируется неотменяемым task, затем continuation явно освобождается при cleanup.

Feature flag tracking и review status

Default/config flags не менялись: stateRestorationGate и cpmMessagingHangRecovery сохраняют прежние default; отдельный cpmLateBackgroundDocumentRecovery остаётся false. Remote configuration не редактировалась. Для нового flag добавлены реальные per-platform задачи в Apple Feature Flags Registry и ссылки непосредственно над enum case:

Оба review threads проверены и resolved; открытых inline threads после readback — 0. Danger на 08866c7eda: 0 failures / 1 warning, только advisory о размере PR (1090 added lines); предупреждение об отсутствующих flag tracking links исчезло. Отдельная Privacy Review task уже существовала, дубликат не создавался.

Проверки и отдельная test branch

  • До исправления две новые проверки дали 2/2 functional FAIL, после успешной компиляции: повторный navigation wait и освобождение через cancelAll.
  • После исправления пять выбранных shared suites: 182 PASS / 0 failures (13 diagnostics + 9 readiness recovery + 78 monitor + 34 lifecycle + 48 manager). Относительно базы PR теперь 21 новый shared unit method.
  • Strict SwiftLint: 8 changed Swift files / 0 violations.
  • Production macOS Browser Debug, обычная Apple Development signing, build PASS. Подпись app debug dylib проверена. Shared WebExtensions module для iOS Simulator build PASS; это не full iOS app build и не runtime validation iOS suspension/resume.
  • Review-only codex/cpm-fix-init-loss-integration-tests / 3f4d7555113d547797b45ff6b2c7b883efedd520 синхронизирована merge нового production head; отдельный doc-only commit актуализировал README (7 новых coordinator regressions, 21 shared regression суммарно). Над production — два прежних harness commits + sync merge + README correction; diff всё ещё ровно 12 test-only paths, 8 app methods и два shared schemes. Эта ветка не идёт в main.
  • Description #7379 изменена только в двух местах для shared deadline и риска зависшего callback. Пользовательские правки и понятные Xcode steps ON → OFF → ON, названия schemes и ожидаемые 8 PASS / 6 FAIL / 8 PASS сохранены. Коммитить или редактировать Swift для reviewer run не нужно.

Финальный runtime cycle на одном наборе подписанных app/XCTest binaries:

Scheme / запуск Passed Failed Skipped Результат
CPM Integration Tests — ON 8 0 0 PASS
CPM Integration Tests - Fixes Disabled — OFF 0 6 0 Все шесть functional failures совпали с ожидаемыми симптомами
CPM Integration Tests — ON повторно, без сборки 8 0 0 PASS

OFF действительно отключает production flag для соответствующего сценария: install/upgrade/slow-wake потеряли первый ответ, P2 не дождался same-document recovery после фактического error 6, late install/upgrade не дождались automatic first-document recovery. expectedFailures в XCTest — 0: OFF остаётся явным красным контрольным запуском, а не ignored CI failure. Fixture setup/host crash/skips не засчитаны как воспроизведение. SHA256 app dylib и XCTest executable совпали до OFF, после OFF и после повторного ON. Бинарники собраны на sync head d0922bb277; финальный test-branch commit 3f4d755511 меняет только README.

CI snapshot 08866c7eda на 16:19 UTC: 31 SUCCESS, 12 SKIPPED, 3 QUEUED, 5 IN_PROGRESS; failures отсутствуют. SwiftLint, macOS/iOS pixel validation и Danger — SUCCESS. Полный CI ещё не объявлен зелёным: оставшиеся unit/UI/release jobs были pending/running.

Артефакты этого прогона: /private/tmp/cpm-pr7379-review-fixes-20261016/. red-tests.log — red-before-fix; unit-final.log, lint-final.log, production-build-final.log, ios-module.log — final validation. Отдельные app-on*, app-off*, app-on-restored* содержат xcresult summaries и exported evidence. SHA256 app/XCTest сохранены до OFF и после каждого последующего run; review/PR/Danger/CI snapshots и validation-summary.json находятся там же.

Это не новая декларация воспроизведения всех production причин. Ограничения прежнего исследования P3/P5 и iOS runtime сохраняются. Точные два новых navigation/cancellation failures сначала воспроизведены deterministic shared tests; восемь app methods проверяют реальные WebKit/app пути существующих install/upgrade, P1/P2 и late recovery сценариев. В ON evidence P2 снова записан фактический WKWebExtensionContextErrorDomain:6; late install/upgrade завершили первый navigation примерно за 5.18 / 5.10 секунды, затем получили отдельный recovery reload, без увеличения navigation timeout.

19 октября 2026 — полный повторный review после точечных правок

Объём. Повторно прочитан весь production diff: локальный alex/cpm-fix-init-loss / 57081973629e1ad43b9312fee479d27e34232abf против alex/cpm-messaging-readiness-telemetry / 713d67419a (#7376), 5 commits / 22 changed paths; manager/lifecycle, native callers обеих платформ, recovery/health monitor, flags, pixel adapters/definitions и shared tests. Опубликованный #7379 пока остаётся на 08866c7eda: 3 commits / 21 files; его CI snapshot — 48 SUCCESS, 21 SKIPPED, без failures. Это не CI непушенных исправлений.

Сохранённые исправления предыдущего review. Launch gate переносит уже израсходованный deadline на тот же pending startup; следующий navigation не платит ещё пять секунд. Safety preflight отделён от синхронного reload; attribution вооружается после проверок и сопоставляется с конкретной WKNavigation из принятого automatic reload, включая синхронный didStart. После await повторно проверяются flag, app state, document identity и 30-секундный срок. Пять новых regression methods увеличили выбранные suites со 182 до 187 PASS (13 diagnostics + 13 readiness recovery + 78 monitor + 35 lifecycle + 48 manager). Оба production builds macOS/iOS Simulator и strict lint десяти изменённых Swift files прошли на этом коде; logs сохранены в /private/tmp/cpm-pr7379-review-selected-fixes-20261016/.

Формы — явно отложено пользователем. После сообщения «пока не парься на счёт форм, оставить как есть оно за фича флагом» document-start tracker, новые conservative veto и четыре form-safety tests убраны отдельным коммитом 5708197362. Исходный JavaScript predicate побайтно совпадает с 08866c7eda; новая instrumentation не установлена ни на macOS, ни на iOS. Известное ограничение для controlled inputs с изменяемым defaultValue и Shadow DOM остаётся нерешённым; результаты предыдущего реального WKWebView воспроизведения не отменены. Независимый webExtensions.cpmLateBackgroundDocumentRecovery по-прежнему default disabled на обеих платформах. Форма не заявляется исправленной.

Новый P2 — удаление extension не инвалидирует поздний reload. WebExtensionManager.uninstallExtension после реальной выгрузки вызывает clearEmbeddedBackgroundStartup(identifier:), но не инвалидирует document recovery. Если успешный startup уже запустил async safety preflight и в это время отключить/удалить активный embedded context, late-recovery flag может остаться включённым. Document identity сохранена; после завершения preflight вызывается reload closure для уже отключённого CPM. Изолированный testFreshReviewUninstallInvalidatesPendingLateRecovery использовал production manager и default loader: context действительно исчез из controller, installation record удалён, затем reload callback вызван 1 раз вместо 0. Следует инвалидировать recovery удаляемого активного context; удаление старой версии при upgrade не должно отменять recovery её замены. Production-код в ходе повторного review не исправлялся.

Проверка finding. Production sources скопированы побайтно (96 файлов) в изолированный package; добавлен только временный probe. Финальный запуск: 188 методов выполнены, 187 PASS / 1 assertion FAIL, без падения host. Первый запуск временного probe упал в WebKit dealloc искусственно созданной WKNavigation (CFRetain NULL); этот тестовый setup исправлен, и затем получен именно функциональный failure callback count. Артефакты: /private/tmp/cpm-pr7379-full-review-20261019/selected-tests-final.log, review-results.json, source-copy.json. В production tests этот probe не добавлен.

Harness и публикация. Локальный codex/cpm-fix-init-loss-integration-tests / 4308751d593bcc63abfb4baaced83e35bd19255f обычным merge синхронизирован с 5708197362; README исправлен на 26 новых shared regressions и прежнюю защиту форм. Над production по-прежнему ровно 12 harness-only paths, 8 app methods и два ON/OFF schemes; они не идут в main. Удалён только собственный generated Package.resolved diff от предыдущего test run. Рабочая production branch чистая. Production и harness commits пока не push; PR body не перезаписан. Старый ON 8 PASS → OFF 6 functional FAIL → ON 8 PASS относится к опубликованному 08866c7eda / test branch 3f4d755511; на новом локальном head этот app cycle ещё не повторён.

Замечание о стиле URL check. Для HTTP(S) подходит URL.NavigationalScheme.hypertextSchemes из Common; initializer сохраняет регистр, поэтому lowercased необходимо сохранить. Это ответ на вопрос, source replacement не выполнялся.

19 октября 2026 — исправление uninstall/preflight race и push

Production e970e8c90eca76e55217f75c13122735a72664c5, branch alex/cpm-fix-init-loss, #7379, база #7376 / 713d67419a. Опубликованы все три локальных commits после 08866c7eda; итоговый diff — 6 commits / 22 paths. Push обычный fast-forward, без переписывания истории. Review-only codex/cpm-fix-init-loss-integration-tests / e380cf98f7e9709085ce76289211f3e1e43c8395 синхронизирована обычным merge, над production по-прежнему ровно 12 harness-only paths; они не идут в main.

Исправление. До unload запоминается, удаляется ли текущий выбранный embedded context. После успешного unload его background document recovery инвалидируется, включая уже ожидающую async safety preflight. Неудачный unload выходит до invalidation; удаление старого context при upgrade не отменяет recovery replacement. Добавлены постоянные shared regressions testUninstallingActiveEmbeddedContextCancelsPendingDocumentRecovery, testUninstallingOldEmbeddedContextPreservesReplacementDocumentRecovery и testFailedUninstallPreservesActiveDocumentRecovery. Первые два используют production loader с настоящими WKWebExtensionContext; третий моделирует ошибку unload и проверяет сохранение live context. HTTP(S)-checks в native navigation callers macOS/iOS переведены на URL.NavigationalScheme.hypertextSchemes с сохранением lowercased.

Проверки. До fix новые три tests: 2 PASS / 1 functional FAIL — активное удаление оставляло выполняющийся reload callback. После fix пять выбранных shared suites: 190 PASS / 0 failures (13 background diagnostics + 13 readiness recovery + 78 monitor + 35 lifecycle + 51 manager), всего 29 новых shared regression methods относительно базы PR. Unit run выполнен в изолированной копии 96 побайтно совпадающих production source files. Полные macOS и iOS Simulator builds — PASS; macOS app подписан Apple Development, team HKE973VLUW, strict verification всего app bundle PASS. Strict lint всех 11 непушенных Swift files — 0 violations. Схемы/имена/параметры/frequency pixels не менялись.

Формы и flags. По явному указанию пользователя новая защита форм не возвращена. Original JavaScript predicate побайтно совпадает с 08866c7eda; known limitation controlled/defaultValue и Shadow DOM остаётся. Независимый webExtensions.cpmLateBackgroundDocumentRecovery всё ещё default disabled на обеих платформах. Deadline launch→navigation и attribution по конкретной WKNavigation сохранены из предыдущих локальных исправлений и теперь опубликованы.

Документация и app validation. PR body точечно уточняет общий launch/navigation deadline, invalidation при удалении активного context и точную WKNavigation attribution. Пользовательские правки, testing branch link и ON 8 PASS → OFF 6 functional FAIL → ON 8 PASS instructions сохранены. README harness обновлён: 8 новых manager regressions / 29 новых shared methods. На новом head первый ON: 8 PASS; OFF: ровно 6 functional FAIL, 0 PASS/skips/expected failures. Проверены реальные причины отказа: install/upgrade/slow-wake first response, P2 same-document recovery timeout и late install/upgrade automatic-reload timeout. App/XCTest SHA256 до и после OFF совпали. Повторный ON завершился 8 PASS; SHA256 до OFF, после OFF и после повторного ON совпали. CI опубликованного e970e8c90e: 48 SUCCESS / 21 SKIPPED, failures/pending нет. Старые app результаты не перенесены на новый head.

Артефакты: /private/tmp/cpm-pr7379-uninstall-fix-20261019/ (unit-green.log, unit-evidence.json, lint.log, mac-build.log, ios-build.log, signature logs, heads.json, PR snapshots); red control — /private/tmp/cpm-pr7379-full-review-20261019/uninstall-red.log.

Итог app validation и CI на опубликованном head

Production e970e8c90e, review-only harness e380cf98f7. Все три запуска выполнены на одних Apple Development-signed app/XCTest binaries; OFF и повторный ON — test-without-building.

Запуск Passed Failed Skipped Expected failures
CPM Integration Tests — первый ON 8 0 0 0
CPM Integration Tests - Fixes Disabled 0 6 0 0
CPM Integration Tests — повторный ON 8 0 0 0

OFF failure reasons проверены по xcresult: install/upgrade/slow-wake потеряли первый ответ; P2 дождался реального WebKit error 6, но не получил same-document recovery; late install/upgrade не дождались automatic first-document reload. Это шесть намеренно красных функциональных контролей, без host crashes/setup failures/skips. Все 8 ON assertions восстановились после включения flags. SHA256 app debug dylib и XCTest executable совпали до OFF, после OFF и после повторного ON.

Из exported ON evidence: P2 записал actualBackgroundLoadError=[6] и затем прошёл проверки ответа оригинальному document без context replacement или ручной навигации; последующие existing-tab/new-tab/new-window assertions также PASS. При 8-секундном startup первая navigation завершилась за 5.167 s (install) / 5.089 s (upgrade), затем был ровно один automatic GET reload (finishCount=2), реальный page initResp и оба этапа pixel reload_started / response_received. Эти измерения включают локальную загрузку документа после прежнего 5-секундного gate; его лимит не увеличен.

CI опубликованного e970e8c90e завершён: 48 SUCCESS / 21 SKIPPED, failures/pending нет. GitHub readback подтвердил оба remote heads, прежнюю базу #7376 / 713d67419a и точное сохранённое PR body. Production worktree возвращён на alex/cpm-fix-init-loss, tracked/untracked diff пуст; обе ветки up to date. Новых production изменений после validation нет. Формы оставлены как согласовано; independent late-recovery flag default disabled.

Артефакты /private/tmp/cpm-pr7379-uninstall-fix-20261019/: validation-summary.json, три app-*-summary.json и .xcresult, exported attachment folders, app-on-evidence-summary.json, три hashes-*.json, pr-final.json, remote-heads.txt. Прежние промежуточные snapshots выше сохранены как история.

19 октября 2026 — P4 detection независимо от late-document reload

Запрос: считать затронутые документы/установки при выключенном webExtensions.cpmLateBackgroundDocumentRecovery, без автоматической перезагрузки страницы.

Опубликовано: production alex/cpm-fix-init-loss / fc87237a476cca58a17fde69b3091b8e99602e03 в #7379, база #7376 / 713d67419a, 7 commits / 22 changed paths. Отдельный review-only harness codex/cpm-fix-init-loss-integration-tests / 475095b33535467f9d63eda6d593cf95242d0449, по-прежнему 12 harness-only paths вне main. Обе ветки опубликованы обычным fast-forward push. Ручные правки PR description сохранены; reviewer steps обновлены на 9 PASS → 6 ожидаемых functional FAIL → 9 PASS.

Что именно считается

Новый web_extension_cpm_startup_response_missing (macOS: web_extension_cpm_startup_response_missing_macos), частота dailyAndCount, без custom parameters. Daily оценивает число затронутых установок за день; count — число подходящих документов. Это не число уникальных людей за всё время.

Сигнал возникает один раз на документ, если HTTP(S)-документ закоммичен во время известного ещё незавершённого первого monitored background startup данного embedded context, ожидание CPM dashboard response завершилось timeout, а WebKit startup callback успешно завершился в пределах 30 секунд от начала startup. Порядок callback и timeout не важен. Обычные последующие idle wakes того же context, здоровые/сменившиеся/отменённые документы, invalidated context, failed startup и истёкшее 30-секундное окно исключаются. Это P4 candidate signature, не доказательство потери именно initResp и не доказательство единственной первопричины; исторические P4/P6 и bg_events наблюдения ниже остаются в силе.

Детекция не зависит от late recovery flag, GET/form reload eligibility и нахождения приложения на переднем плане. Она не запускает safety JavaScript, reload или дополнительную WebKit background load. URL, tab ID, значения форм и raw errors в pixel не передаются. First-startup identity учитывается слабым набором WKWebExtensionContext; проверено, что WKWebExtensionContext использует NSObject identity equality. Это отдельный счётчик, а не переименование late_document_reload/response_received: прежние recovery pixels продолжают означать действия/результат восстановления.

Возможность reload по-прежнему проверяет flag и условия безопасности. Для документа, отслеживаемого при выключенном флаге, позднее включение флага не разрешает retroactive reload. Navigation wait limit не увеличен. Исходный form predicate не изменён, ранее отложенное усиление защиты форм не добавлялось; default late recovery flag остаётся disabled.

Проверки production и app fixture

  • 197 shared unit tests PASS / 0 failures: 13 diagnostics + 20 recovery + 78 monitor + 35 lifecycle + 51 manager. В этом изменении добавлено 7 regression methods; всего 36 новых shared regressions относительно базы.
  • Покрыты OFF без preflight/reload closure, обе очередности timeout/readiness, once-per-document и несколько табов, idle wake exclusion, healthy/navigation/cancel/invalidate/failed/expired exclusions, независимость detection/recovery outcomes и PIIFree daily/count metadata.
  • Production strict lint: 6 изменённых Swift files / 0 violations; harness strict lint: 2 / 0. macOS/iOS pixel definitions и обе wide-event validation/schema immutability проверки PASS.
  • Полные signed macOS и iOS Simulator app builds PASS. Обычная Apple Development signing сохранена.
  • App fixture: новый CPMBackgroundRecoveryIntegrationTests.testLateStartupIsDetectedWithRecoveryDisabledWithoutReload явно выключает production late recovery flag, задерживает реальный background startup на 8 секунд, требует реальный dashboard timeout, detection count = 1, один finish исходного документа, отсутствие late_document_reload outcomes и здоровую следующую ручную навигацию. P1/P2 fixture также проверяет, что idle wake не увеличивает P4 counter; pixel adapter проверяет имя/частоту/параметры.
  • Signed app ON 9 PASS → OFF 6 functional FAIL → ON 9 PASS, без skips/expected failures, на одних бинарниках. app-on.xcresult, app-off.xcresult, app-restored.xcresult и их summaries/attachments сохранены. SHA256 app debug dylib = 7d3a3c9f1a772a24b2e502a3e8f07db78603e8a4d44a9cfd68de12f2f9dca52e; XCTest executable = 4c28d4bf9a69ccd4f0c24b67d25bf5b492d47a68f343270bfc74a7505071194a, до OFF / после OFF / после ON совпали.
  • Новый detection-only positive case дважды PASS при late recovery flag OFF: реальный first-document timeout, detection = 1, finishCount = 1, отсутствуют late_document_reload outcomes; следующая ручная навигация получает native dashboard и page initResp, счётчик остаётся 1. Доказательства: detection-only-evidence.json, ON attachment 9567542F-EF42-4C5A-8FFC-ACF716ABC09F.json, restored attachment CA7E1D06-9140-4D8E-B119-363B43D4CA8B.json.
  • Все шесть OFF failures проверены по именам и причинам: install/upgrade/slow wake теряют первый ответ, P2 получает настоящий WebKit error 6 и timeout same-document recovery, late install/upgrade получают timeout автоматического восстановления. Оба late OFF controls дали detection = 1 и ни одного late reload event. Setup/host failures не использованы как red controls. Доказательства: off-control-evidence.json, validation-summary.json.
  • CI production head fc87237a47: 48 SUCCESS / 21 SKIPPED, pending и failures нет. PR head/base/description проверены чтением после публикации; pr-final.json. Worktree чистый и возвращён на alex/cpm-fix-init-loss; обе локальные ветки совпадают с origin.

Локальные artifacts: /private/tmp/cpm-p4-detection-20261019/: unit.log, unit-evidence.json (96 production source files byte-identical), lint.log, harness-lint.log, четыре pixel validation logs, mac-build.log, ios-build.log, context-identity.log, heads.json, pr-body.md, app result bundles, detection-only-evidence.json, off-control-evidence.json, validation-summary.json, три SHA256 snapshots, pr-final.json. Исторические результаты предыдущего head e970e8c90e (190 / 8→6→8) выше/ниже сохранены и не являются результатами нового head.

Полное ревью после P4 detection — error-6 attribution (19 октября 2026)

Проверен полный diff #7379 относительно #7376: manager/install/upgrade/uninstall/reload, общий launch/navigation deadline и cancellation, WebKit navigation identity, обе платформенные интеграции, runtime flags, P4/health-monitor evidence и pixel adapters/definitions, а также shared regressions и reviewer instructions. Ревью начато на fc87237a47 / 713d67419a; во время проверки опубликовано перебазирование на a00dc4afeb95b3fbbbb95dc50ce450c49004f3e2 / c7adf28e1254da79d788125033474db737b11b6d. Затронутая логика manager/recovery/lifecycle не изменилась; замечание отдельно повторено на новом head. Полный diff по-прежнему 7 commits / 22 paths.

Открытое замечание P2 — failed startup с error 6 не инвалидируется в P4 detector. WebExtensionManager.swift:319–320: error notification завершает только manager startup task через clearEmbeddedBackgroundStartup(), сохраняя startup и его документы в CPMBackgroundReadinessRecovery. Если WebKit сохраняет pending load callbacks до удачного retry, старый callback приходит с nil; backgroundCompleted(oldID, succeeded: true) делает уже провалившийся first startup успешным для P4. При timeout документа и завершении retry до 30 секунд detector посылает web_extension_cpm_startup_response_missing. Это смешивает известный error-6 failure/retry с P4 candidates, вопреки заявленному исключению failed startups.

Порядок соответствует upstream WebKit implementation: didFailLoadWithError записывает error и выгружает background view, recordError асинхронно публикует notification; pending actions исполняются после успешной background load. Исходники сохранены вместе с review artifacts. Для исправления нужно инвалидировать данные именно провалившегося startup до освобождения его wait, а поздние callbacks этого startup игнорировать.

Доказательство: временный CPMP4FullReviewTests.testError6FirstStartupMustNotBecomeP4WhenOldCallbacksCompleteAfterRetry проходит через production manager, notification observer, реальный health monitor/timeout и pixel instrumentation. Публичные WebKit completions управляются в subclass context; известный error 6 вызывает production retry, затем retained callbacks завершаются с nil. На текущем head получен detection count = 1 вместо 0. Это детерминированный regression probe порядка public API, не новый natural-trigger signed-app reproduction. Предыдущие настоящие app 9→6→9 сохранены как отдельное доказательство на прежнем head и не подменяют этот probe.

В изолированной копии вставка backgroundRecovery?.invalidate() перед clearEmbeddedBackgroundStartup() в ветке совпадающего context устраняет дефект. На актуальном head весь выбранный набор с тремя probes: 199 PASS / 0 failures. Затем проверочная production-правка из копии убрана; production worktree/PR не изменены, commit/push не делались. Это проверка причины, а не опубликованный fix.

Проверки и artifacts

  • Опубликованный прежний fc87237a47: 197 штатных shared tests PASS; probes 2 PASS / 1 FAIL; временный candidate fix 200 PASS.
  • Актуальный a00dc4afeb: 196 штатных shared tests PASS, probes 2 PASS / 1 FAIL, всего 199 tests / 1 FAIL. Разница 197→196 — удалённый retired-telemetry тест в обновлённой базе #7376, не потеря P1/P2/P4 регрессий.
  • Актуальный head с candidate fix только в копии: 199 PASS. Два дополнительных positive probes подтверждают detection при late flag OFF + background app state и независимость текущего startup от failed callback предыдущего startup.
  • macOS/iOS pixel definitions, formatting, wide-event consistency и generated schema immutability PASS. git diff --check PASS; production worktree чистый. Исходники и штатные тесты копии сверены с текущим Git head (153 tracked paths); временный probe — единственный дополнительный test file.
  • Новый head CI на момент завершения проверки: 31 SUCCESS / 14 SKIPPED / 4 IN_PROGRESS / 3 QUEUED, failures нет, завершение не заявлено. Старый green CI 48/21 относится к fc87237a47.
  • Review-only harness tracking head остаётся 475095b335, содержит прежний production fc87237a47 и 12 harness-only paths. App ON 9 PASS → OFF 6 functional FAIL → ON 9 PASS здесь повторно не запускался; после текущего rebase/correction точный новый head этими runs не объявляется проверенным.
  • Формы сохранены в ранее явно согласованном scope: исходная проверка и default-disabled late recovery flag. Отложенное усиление формы повторно не предъявлялось как новый finding. Других новых actionable дефектов по полному diff не подтверждено.

Artifacts: /private/tmp/cpm-pr7379-after-p4-review-20261019/: review-summary.json, CPMP4FullReviewTests.swift, candidate-fix.diff, shared-tests.log, probes.log, probes-with-candidate-fix.log, rebased-head-with-probes.log, rebased-head-with-candidate-fix.log, четыре pixel validation logs, snapshots WebKit implementation и pr-final.json. Исходная тестовая копия после проверки возвращена к production source; candidate patch сохранён отдельно.

Финальный контроль #7379 — 19 октября 2026

Head остаётся a00dc4afeb, база c7adf28e12; production diff не изменился после полного review. Остаётся один открытый P2 error-6/P4 attribution: проверочная production-правка в PR отсутствует. Повторный запуск трёх изолированных probes на точном head: 2 PASS / 1 FAIL, detection count 1 вместо 0 в ранее найденном случае. Это тот же управляемый public-API regression probe, не новый natural-trigger app run.

CI актуального head завершён: 53 SUCCESS / 25 SKIPPED, failures и pending нет. Два GitHub review threads resolved, новых открытых threads нет; это не означает, что локально воспроизведённый P4-дефект исправлен. Краткое описание PR и 10 однострочных reviewer steps ON → OFF → ON проверены; таблица feature flags удалена по запросу пользователя. Production worktree чистый; код PR в ходе финального контроля не менялся.

Повторный log: /private/tmp/cpm-pr7379-final-review-20261019/probes.log; PR/CI snapshot: /private/tmp/cpm-pr7379-final-review-pr.json; review threads snapshot: /private/tmp/cpm-pr7379-final-review-threads.json. Детали причины, предыдущие 196 shared PASS и candidate-only 199 PASS — в предыдущем разделе.

Исправление error-6/P4 finding в production PR — 19 октября 2026

Первоначальная публикация fc124938e0

Опубликован fc124938e040533e8ea9ef04df9d313d0e9d5dcb в #7379, поверх a00dc4afeb: 2 изменённых файла, 8 commits / 22 paths относительно #7376. Observer принимает только background-load error 6 из WKWebExtensionContextErrorDomain. Для совпадающего pending context он инвалидирует startup/document recovery до clearEmbeddedBackgroundStartup(); retained successful callbacks после retry уже не могут объявить этот failed startup успешным P4 или запустить document preflight.

Штатные тесты теперь в PR, в WebExtensionManagerTests.swift:

  • testFailedFirstStartupCannotReportP4OrReloadAfterRetainedCallbacksSucceed: actual production observer/manager/health-monitor path, retained public WebKit callbacks, late recovery flag OFF и ON; после error 6 нет P4 detection и document preflight.
  • testUnrelatedErrorPreservesCurrentFirstStartupDetection: error 6 superseded context и code 6 другого error domain не сбивают текущий startup и его корректный P4 detection.

До production fix официальный первый regression method красный при обоих состояниях late flag (3 assertion failures), obsolete-context control PASS. После исправления 198 штатных shared tests PASS / 0 failures: 13 diagnostics + 20 recovery + 77 monitor + 35 lifecycle + 53 manager. Всего 38 новых shared regressions относительно текущей базы. Strict SwiftLint: 2 changed files / 0 violations. Полный iOS Simulator app build PASS с обычными настройками проекта.

Harness обновлён 475095b335 → f4f135766a7fd67096ebc6a973919cb5a464d7ec обычным merge/push, без переписывания истории. Конфликты в manager/shared tests разрешены точным production-кодом. Актуальный production head — предок harness; diff ровно 12 harness-only paths, старые telemetry/test deletions больше не возвращаются. README обновлён: 38 новых shared regressions, 10 manager regressions. Тестовые steps в PR остаются 9 PASS → OFF 6 functional FAIL → ON 9 PASS.

Первоначальный app этап: первый build-for-testing выявил ссылки fixture на удалённые telemetry API. Исправлен только harness (eb3865b594): evidence строится через текущий public episode metadata adapter, добавляется локальный raw view count без отправки synthetic pixel. Затем signed ON дал 9 PASS на production fc124938e0. Фикс уже опубликован; предыдущая candidate-only правка больше не описывает актуальное состояние. Формы и default-disabled late recovery flag сохранены.

Artifacts: /private/tmp/cpm-pr7379-error6-fix-20261019/: red-before-fix.log, shared-tests.log, lint.log, ios-build.log, heads-and-checks.json, app-build.log/app-build.xcresult, pr-progress.json; все последующие app bundles также сохранены в этой папке.

Итог после обновления telemetry/main и WebKit error API

Пока выполнялась проверка, production обновлён обычными merge до 8275bcce368ea63b3777b42b6007beb48d768409, база #7376 — 39fe56af4c35bf034d570f04dd58f59bd41eb2b6. fc124938e0 — предок опубликованного PR, его fix и обе штатные регрессии сохранены. Текущий diff: 10 commits / 23 paths. Safe WebKit error copying и изменения base/main учтены; retired EventsListener mock удалён из изолированной package-копии.

На обновлённом production 201 selected shared tests PASS / 0 failures: 14 diagnostics + 20 recovery + 77 health monitor + 35 lifecycle + 55 manager. Относительно текущей базы #7376 — 38 новых shared regressions, включая обе новые error-6/P4 проверки; первая покрывает late recovery OFF и ON. Strict SwiftLint на 4 изменённых Swift files: 0 violations. Первоначальный полный iOS Simulator app build PASS относится к fc124938e0; для текущего 8275bcce36 завершились зелёным iOS PR Checks и iOS UI Tests в CI.

Harness опубликован 6d04496882ad25e05dceb622305a50c7e51aeb37, содержит актуальный production 8275bcce36; diff ровно 12 fixture-only paths, вне main. История синхронизации сохранена: f4f135766a → eb3865b594 → 6d04496882, обычные merge/push. README отражает 38 новых shared regressions и 10 manager regressions. Параллельные незакоммиченные правки alex/cpm-fix-p1-p2 и отдельного alex/cpm-fix-init-loss-production не трогались и не включались в validation; app запускался из чистого checkout /private/tmp/cpm-pr7379-error6-fix-20261019/source. После тестов он возвращён на detached production 8275bcce36; production-ветка уже занята параллельным worktree, её повторный checkout был безопасно отклонён Git.

После смены базы app build сначала остановился на устаревшем локальном workspace lockfile; выполнено разрешение зависимостей. Затем выяснилось, что reused DerivedData импортирует старые standalone .swiftmodule вместо свежих PackageFrameworks (конкретно отсутствовал DataClearingActionSkipping из нового BrowserServicesKit). Сохранены 11 подтверждённых устаревших модулей в stale-standalone-modules/ с manifest; исходники не менялись. После этого подписанная app-сборка прошла. Подпись: Apple Development, Team HKE973VLUW; host macOS 26.7.1 (25G241).

Фактическая app-матрица на одном build:

  • ON: current-app-on-3.xcresult — 9 PASS / 0 FAIL / 0 SKIP.
  • OFF: current-app-off.xcresult — 0 PASS / 6 functional FAIL / 0 SKIP; install, upgrade и slow wake теряют first response; error-6 recovery, late install и late upgrade завершаются ожидаемым recovery timeout. Host/setup failures отсутствуют; это отрицательный контроль, не успешный test run.
  • Первый restored ON: current-app-restored.xcresult — 7 PASS / 2 FAIL / 0 SKIP: P2 functional recovery завершился, но views не освободились за teardown budget; следующий install host остановился с SIGINT. Этот результат сохранён как failed, retained root cause не установлен; подробности ниже.
  • Полный restored ON retry: current-app-restored-retry.xcresult — 9 PASS / 0 FAIL / 0 SKIP. Выполнен test-without-building, проверки/assertions не ослаблялись. SHA256 app debug dylib и XCTest executable совпали до OFF, после OFF и после restored ON; compilation между фазами не было.

P4 detection-only method прошёл в обоих успешных ON runs: late flag OFF, detections=1, finishCount=1, нет late reload/recovery events. Это счётчик candidate signature, а не доказательство конкретного root cause каждого пользовательского инцидента. Новый shared regression отдельно исключает из P4 известный failed startup после retained successful callback.

CI текущего head завершён: 43 SUCCESS / 17 SKIPPED, 0 failures / 0 pending; macOS PR Checks, iOS PR/UI Checks, BSK, lint и pixel schema зелёные. Сохранены final-pr.json и current-ci-runs.json. Пользовательские title и лаконичное PR description сохранены: 10 точных однострочных steps, отдельный harness, ON → OFF → ON, без таблицы feature flags и служебных local-validation секций.

Итог для rollout: error-6/P4 review blocker закрыт в production PR; P1/P2 и независимый P4 detection проверены. Late document reload остаётся default OFF. Shadow DOM / controlled form hardening по просьбе пользователя отложен; включение late reload в production — отдельный scope. Flaky teardown/host failure review-only harness не скрыт и не считается функциональным PASS.

Полный evidence index: /private/tmp/cpm-pr7379-error6-fix-20261019/validation-summary.json; logs + .xcresult всех попыток, exported app attachments, current-app-restored-first-diagnostics/, p4-detection-only-evidence.json, три SHA256 manifests, harness-only-paths.txt, final-pr.json. Старые результаты и failed attempts сохранены.

Промежуточный app-run: teardown / SIGINT — 19 октября 2026

На чистом harness 6d04496882 (production 8275bcce36) первый ON завершился 9 PASS, OFF — 0 PASS / 6 ожидаемых functional FAIL / 0 SKIP, SHA256 app/test modules совпали. Первый restored-ON (current-app-restored.xcresult) завершился 7 PASS / 2 FAIL / 0 SKIP: testBackgroundLoadFailureRecoversOriginalDocument прошёл CPM assertions, но TestRunHelper.swift:453 не дождался освобождения window views за 5 секунд; следующий testInstallDuringSessionInitIsDelivered остановился с SIGINT, runner перезапустил host. P2 evidence подтверждает native dashboard + page initResp после recovery для existing tab, new window и new tab; этот run всё равно считается неуспешным. В production DEBUG есть ensureObjectDeallocated(..., .interrupt) → raise(SIGINT); связь с конкретным удерживающим reference пока не доказана, retained root cause не установлен. Функциональные ожидания и deallocation checks не отключались. Полные attachments, diagnostics, summary и логи сохранены в /private/tmp/cpm-pr7379-error6-fix-20261019/current-app-restored-first-*; начатый полный restored-ON retry на тех же бинарниках (current-app-restored-retry.xcresult) затем завершился 9 PASS / 0 FAIL / 0 SKIP. SHA256 app/test modules совпали; source и assertions между попытками не менялись. Это не отрицательный контроль, failures не исключаются из истории.

Проверка отчёта о трёх падениях late-startup app tests — 19 октября 2026

Исходный screenshot: failed testLateStartupIsDetectedWithRecoveryDisabledWithoutReload, testOverBudgetInstallRecoversFirstDocumentWithoutExtendingNavigationWait, testOverBudgetUpgradeRecoversFirstDocumentWithoutExtendingNavigationWait; остальные 6 methods зелёные. Assertion text и macOS/Xcode reviewer run не предоставлены, поэтому идентичность конкретной причины его каждого failure не утверждается. На Virfield macOS 27 воспроизведены все три имени и найдены ошибки timing assumptions в harness.

Опубликованный harness: 29da2c1587571e91f85915c35c8322f273e07eb0, branch codex/cpm-fix-init-loss-integration-tests. Обычный fast-forward push от d26a1c55d1; локальный чистый worktree alex/cpm-fix-p1-p2 также fast-forward обновлён. Новые изменения затрагивают ровно три существующих файла: CPMAppIntegrationHarness.swift, CPMBackgroundRecoveryIntegrationTests.swift, README.md. Production PR #7379 остаётся на 674bb809f2, base alex/cpm-messaging-readiness-telemetry (#7376); production files, flags/defaults, reload safeguards и 5-second navigation timeout не менялись. Production head — ancestor harness; полный diff harness относительно production по-прежнему содержит только 12 harness paths, без новых submodule changes. Оба shared schemes автоматически задают flags: normal CPM_APP_INTEGRATION=1; disabled дополнительно задаёт оба DISABLE overrides=1 и выбирает ровно 6 recovery methods. Ручной шаг включения late recovery в PR instructions не пропущен; текущие 10 шагов PR сохранены, README уточнён.

Исходный d26a1c55d1 на host macOS 26.7.1 (25G241) / Xcode 27.1 (27A9275) дал: reported 3 methods 3 PASS / 0 FAIL / 0 SKIP; полный disabled 0 PASS / 6 ожидаемых functional FAIL / 0 SKIP; следующий normal 9 PASS / 0 FAIL / 0 SKIP. На чистой Virfield macOS 27.0 (26A428), Xcode 27.0 (27A266a), arm64 исходный harness дал normal 5 PASS / 4 FAIL / 0 SKIP: edited-document и over-budget install истекали на 6.5-second first-document precondition; следующие P4-detection и over-budget upgrade падали с SIGINT. Disabled дал 0 PASS / 6 FAIL, но часть была precondition/host failures, поэтому этот исходный VM run не считается успешным отрицательным контролем. Пример normal install: policy callback 16:05:46.736120Z, fixture timeout 16:05:51.770356Z, didStart 16:05:51.806345Z — fixture бросал ошибку за 36 ms до release корректного пятисекундного gate, включив холодную подготовку окна/WebKit в общий бюджет. Незавершённые unstructured navigation tasks продолжали работу во время teardown перед следующими SIGINT.

Промежуточный вариант с прогревом окна, отдельным измерением реального coordinator waiter и structured late navigation cleanup убрал precondition/SIGINT cascade, но на VM дал 6 PASS / 3 FAIL, затем disabled 0 PASS / 6 FAIL, затем normal снова 6 PASS / 3 FAIL на неизменных binaries. Ровно три reported methods требовали failure/recovery от здоровой страницы: при 8-second startup WebKit 27 доставлял настоящий native dashboard и page initResp через ~3 секунды после release gate, до 4-second response deadline. Поэтому отсутствие missing-response/reload было корректным поведением app. Late-startup fixture delay увеличен до 12 секунд, чтобы пересечь и 5-second gate, и 4-second response deadline; обычный P1 idle-wake остаётся 8 секунд. Используется реальное приложение, AppDelegate/Tab/lifecycle coordinator, system WebKit, CPU delay в extracted test copy extension и настоящие ответы; ACK/ошибки/пиксели не фабрикуются.

Checkpoint 8a27a69776 включил эти harness fixes. Первая локальная 12-second попытка: 2 PASS / 2 FAIL, оба over-budget cases проверяли P4 count до реального background completion; после ожидания callback локальные четыре methods дали 4 PASS / 0 FAIL. Первый полный 12-second VM run: 7 PASS / 2 FAIL — P4-only ошибочно запрещал естественный поздний original response после уже зарегистрированного timeout, а install проверял response_received через ~38 ms после reload finish без отдельного ожидания. Follow-up 0a6d90e4c0 сохраняет исходный failed probe, P4 detection=1, finishCount=1 и отсутствие reload при recovery OFF, но допускает поздний original response. Recovery требует reload_started, ровно два finish, ACK уже нового документа и отдельное ожидание attributed response_received с точным списком outcomes. Локальные четыре methods после этого: 4 PASS / 0 FAIL / 0 SKIP. Несвязанный перевод P2 navigation Task→async let затем убран в ddee0e5be0: финальный P2 method сохраняет исходную Task и timing. Это ограничение diff, а не заявленный фикс повторного WebKit failure. Локальный отдельный P2 после возврата исходной Task: 1 PASS / 0 FAIL / 0 SKIP. 29da2c1587 добавляет README-only описание оставшегося failure. Strict SwiftLint двух изменённых Swift files: 0 violations, diff checks clean.

Финальный VM цикл на коде ddee0e5be0 (published head 29da2c1587 отличается только README): normal 9 PASS / 0 FAIL → disabled 0 PASS / 6 ожидаемых functional FAIL → normal 8 PASS / 1 unexpected P2 FAIL; везде 0 SKIP. Все три исходных reported methods и edited-document PASS в обоих normal runs. Disabled failures проверены по причинам: install/upgrade/slow wake не получают первый ответ в срок, P2 не восстанавливает исходный документ, late install/upgrade не выполняют automatic recovery; host crashes/setup errors не засчитаны как controls. Финальные measured gate waits: install 5.00827 s, upgrade 5.01224 s; после OFF соответственно 5.01076 s, 5.00807 s. При release startup оставался pending; оба recovery cases имеют finishCount=2 и оба reload outcomes. P4-only имеет detections=1, finishCount=1, без reload/recovery outcomes. App/test SHA-256 до/после всех трёх phases совпали и совпали с локальным payload; пересборки между phases не было. Полный green 9 → 6 expected red → 9 на финальной версии не подтверждён; последний enabled run действительно красный из-за P2.

Оставшийся P2: retry тоже иногда получает настоящий background-load error 6. Два отдельных normal runs 0a6d90e4c0 дали 8 PASS / 1 P2 FAIL, но тот же неизменный payload после disabled дал 9 PASS / 0 FAIL. В первой failed попытке второй error 6 пришёл через 30 секунд после первого (16:36:14.455Z → 16:36:44.468Z, retry PID 3001); повтор дал 16:40:38.693Z → 16:41:08.707Z, PID 3265. Контроль единственного P2 на исходном published d26a1c55d1 в той же VM также дал 0 PASS / 1 FAIL / 0 SKIP с повторным error 6, поэтому явление воспроизводится и без новых late-startup fixes. Для baseline retry PID 3952 успешно сняты background/app stack samples: WebKit 22625.1.29.11.27, background footprint 11.3 MB, main thread в XPCServiceMain/xpc_main/NSRunLoop/Mach wait, 0% CPU; app main thread в XCTest/AppKit run loop. Эти стеки не показывают CPU busy-loop и совместимы с неустановившимся XPC/bootstrap connection, но точная root cause не доказана. Console VM была разблокирована/активна; crash/OOM report в собранных логах не найден. Failure не объявляется infrastructure-only и не игнорируется. Финальный normal после OFF снова поймал его; README явно считает это unexpected enabled-scheme failure, а не валидный отрицательный контроль. Production-изменений для второго error 6 в этой работе нет.

Все raw xcresults, logs, JSON attachments, generated .xctestrun/flag environment, app/test hashes, export manifests и samples сохранены в /private/tmp/cpm-pr7379-three-late-failures-20261019/: vm-baseline/, vm-eight-second-intermediate/, vm-twelve-intermediate/, vm-verified-first/, vm-confirmation/ (включая baseline-p2.xcresult и samples), vm-final/. SHA-256 manifests экспортированных VM bundles совпали с оригиналами; финальный экспорт проверен по 3820 files. Локальные failed/positive attempts также сохранены отдельно. Первая transfer попытка пересеклась с Xcode build и завершилась rsync exit 23 до test execution; stable copy затем успешно запустила baseline. Deep signature verification локального Debug build сообщал missing/invalid sealed resource во вложенном VPN helper PrivacyConfig.framework; это не засчитано как причина reported failures. Использовался Apple Development signed host app/test build, guest signing identities отсутствуют, private signing keys в VM не передавались. Virfield lease lease-671a00b65fc4efdfc9b0df677a0ff51f, expiry 2026-10-19T17:49:35Z; VM не удалялась без отдельного разрешения.

#7379: review fixes и CI — 20 октября 2026

Область этой сверки — только #7379; она не меняет статус merge/rollout других CPM PR. Production head 9effd97877bbaf5918f59083b17a8c5e7d11492c, review fix f08aefe1b8, база alex/cpm-messaging-readiness-telemetry / da8e714b33. Все шесть human review threads получили ответы и resolved.

  • Удалены CPMRecoveryInstrumentation, WebExtensionCPMRecoveryInstrumentation и manager wrapper. Recovery и тесты используют непосредственно WebExtensionPixelFiring / реальные WebExtensionPixelEvent.
  • iOS/macOS adapters снова вызывают статический PixelKit.fire: shared instance определяется при отправке, не при создании struct. Имена, параметры и частоты CPM pixels сохранены.
  • MacOSCPMDiagnosticsFeatureFlags снова private в production; доступ и pixel injection нужны только отдельному review harness.
  • У cpmLateBackgroundDocumentRecovery собственный doc comment; описание hang recovery возвращено к cpmMessagingHangRecovery.
  • По последнему явному указанию пользователя применён предложенный reviewer focus guard: допустим только отсутствующий focus или document.body; страницы с любым iframe консервативно исключены из автоматического reload. Это предотвращает проверенные focused Shadow DOM / iframe случаи, но не является журналом всех document edits: синхронизация mutable defaults и ранее изменённый, затем потерявший focus shadow content полностью не закрыты.
  • Добавлены 5 обычных shared-package WKWebView регрессий, остающихся в production PR: edited input; edited iframe после ухода focus; focused edited Shadow DOM input; non-GET veto; pristine GET с реальным завершившимся reload. Загружается локальный URL через WKURLSchemeHandler, затем вызывается реальный production registerDocument(in:webView:isGET:) и safety JavaScript. Отказ от reload не подавляет independent P4 detection.

Проверки: до обновления базы 260 selected PASS; после merge базы и окончательного выделения main-actor CPM setup — 267 PASS / 0 FAIL (CPM, lifecycle, manager), strict SwiftLint 8 files / 0 violations. В отдельной source copy с исходными guards оба новых iframe/Shadow DOM теста дают нежелательный реальный reload и 2 failed tests / 6 assertions; с исправлением проходят. Это red controls, не проигнорированные CI failures. Pixel validators и formatting обеих платформ PASS; wide-event consistency/schema checks PASS после merge commit.

CI: прежний failed workflow 39272483366 на 674bb809f2 падал crash процесса xctest в ConfigurationFetcherTests.testFetchAllWhenAssetsAreModifiedThenAllFetchedConfigurationsAreReturned. Извлечённый .ips: SIGBUS / EXC_BAD_ACCESS, triggered stack swift_retain → Foundation Locale.preferredLanguages → APIRequest.Headers.acceptLanguage → ConfigurationFetcher.fetch(all:); второй thread тоже читает Locale. Это установленное место падения, не установленная причина corruption/race и не доказательство infrastructure-only. Код Configuration/Networking не менялся. Attempt 2 SUCCESS без изменения binaries/source этого head. На новом 9effd97877 все checks завершены: 43 SUCCESS / 17 SKIPPED, 0 FAILURE, 0 pending; merge state CLEAN. Зелёные workflow: BSK, macOS PR checks, iOS PR checks, а также UI/PIR, pixel validation, SwiftLint и Danger. Итог повторно проверен по опубликованному head; 0 открытых review threads.

После f08aefe1b8 GitHub не запускал checks из-за DIRTY merge state с текущей базой. Merge da8e714b33 разрешил два конфликта (manager и pixel enum), сохранив обе стороны; CPM setup вынесен в @MainActor configureCPMMonitoring(), чтобы соблюсти strict complexity lint. Force push не использовался. Ранее существовавшие локальные Package.resolved изменения не включены в commits.

Harness: codex/cpm-fix-init-loss-integration-tests / 0b1d6771fe опубликован и содержит production 9effd97877 как ancestor; ровно 14 fixture-only paths, 43 новых production shared regressions унаследованы. Служебные visibility/pixel seams остаются только там; live PixelKit lookup в harness тоже выполняется при fire. Signed build-for-testing PASS, Apple Development / Team HKE973VLUW, strict harness lint 2 files / 0 violations; использован новый locked artifact cache. Новый полный app ON/OFF/ON пока не выполнялся: прежний macOS 27 результат 9 PASS → 6 expected FAIL → 8 PASS / 1 unexpected P2 FAIL остаётся историческим фактом; повторный настоящий WebKit error 6 на P2 retry этим review fix не исправляется.

webExtensions.cpmLateBackgroundDocumentRecovery по-прежнему default disabled на iOS и macOS; P4 detection работает независимо и не требует reload или safety-script evaluation. Этот проход не включает rollout flag и не доказывает готовность включать late reload для всех документов.

Все промежуточные результаты сохранены в /private/tmp/cpm-pr7379-comments-ci-20261020/: CI .xcresult/.ips и raw log, replies/resolution JSON, normal/red-control test logs, lint/validators, merge logs и harness build logs. При подготовке WK fixture loadHTMLString сначала дал 9 assertions из-за отсутствия history item; заменён реальной navigation. Промежуточный synthetic WKNavigation() в reload spy вызвал локальный SIGTRAP (CFRetain(NULL) в WKNavigation dealloc); fixture теперь вызывает super.reload() и ждёт реальный finish. Первая harness build попытка использовала stale absolute artifact paths; повторная подготовлена со свежим locked package cache.

#7379: independent P2 background-load recovery flag — 20 октября 2026

По запросу пользователя P2 same-context retry отделён от полной перезагрузки extension context. Production 55a42802a6bf1210a51642c3ae59504078ad82d3 опубликован в #7379. Review-only harness a6e6835a5f9eac783f6c64ec9467deb9302535b2 содержит этот head и по-прежнему не предназначен для main.

  • Новый remote subfeature — webExtensions.cpmBackgroundLoadRecovery, Config(defaultValue: .enabled) на обеих платформах, macOS category .webExtensions, local override разрешён стандартным default. Общий WebExtensionsSubfeature и обе production factories подключены к отдельному isCPMBackgroundLoadRecoveryEnabled closure.
  • Новый flag проверяется при решении о retry и повторно перед deferred execution. Он управляет только retry фонового контента после error 6 в том же context; прежние rate limit, foreground checks и защита от конкурентного restart сохранены.
  • webExtensions.cpmMessagingHangRecovery управляет full-context restart после подтверждённого messaging hang. Retry работает при restart OFF; restart работает при retry OFF.
  • stateRestorationGate, late GET recovery default OFF и независимый P4 detection не менялись. Этот проход не исправляет известный повторный error 6 на P2 retry в macOS 27 и не объявляет полный app ON/OFF/ON зелёным.
  • Remote override добавляется в duckduckgo/privacy-configuration под subfeature cpmBackgroundLoadRecovery родителя webExtensions. Пока subfeature отсутствует в remote config, применяется новый enabled default; если remote config явно задаёт состояние, он имеет приоритет. Generated embedded config здесь не редактировался; remote rollout не выполнялся. По уточнению пользователя комментарии нового flag на обеих платформах и в WebExtensionsSubfeature ссылаются на отдельную feature-flag задачу; она заменяет первоначальную ссылку на задачу P1/P2 fix. Comment-only update опубликован: production 8d8b5bee0f, harness b1b9a047e3; изменены только три URL-комментария, strict SwiftLint 3 files / 0 violations. Результаты unit/build и CI выше относятся к указанному 55a42802a6; для comment-only обновления повторный build/tests не запускался.

Регрессии: обновлён existing runtime kill-switch test; добавлены 4 метода: actual background retry при hang recovery OFF, confirmed-hang restart при retry OFF, veto queued retry после runtime disable, и error-6 notification при retry OFF / restart ON. 271 selected CPM/lifecycle/manager PASS / 0 FAIL; в production PR теперь 47 новых shared test methods относительно базы. Изолированный контроль с прежними isCPMMessagingHangRecoveryEnabled() в обоих retry guards дал 4 failed methods / 10 assertions; исходники production для контроля не менялись.

Платформы и CI: strict production SwiftLint 7 files / 0 violations, fixture lint 2 / 0; signed macOS app + integration test build PASS, Apple Development / Team HKE973VLUW. Полный local iOS app build на concrete iOS 27 simulator destination PASS (ios-build-verified.log / ios-build-verified.xcresult); app не запускался. Новый flag и production iOS factory также успешно компилировались для arm64 и x86_64 в первом generic build. Первый generic build остановился в существующем packaging script из-за отсутствия TARGET_DEVICE_OS_VERSION; concrete retry первоначально упёрся в заполненный диск. Удалены только собственные воспроизводимые compiler intermediates, app/test products и исходники сохранены; финальный concrete build успешно завершился. Промежуточный sandbox-запуск не получил доступ к Xcode simulator services; успешный финальный запуск использовал разрешённый доступ к build services. CI точного 55a42802a6 на 20 октября, 14:16 UTC: 39 SUCCESS / 13 SKIPPED / 4 IN_PROGRESS, 0 failures, merge state UNSTABLE из-за незавершённых проверок; это ещё не CI GREEN. Прежние 43 SUCCESS / 17 SKIPPED относятся к 9effd97877.

Harness: P2 метод переключает .cpmBackgroundLoadRecovery; .cpmMessagingHangRecovery остаётся false, так что P2 positive теперь отдельно проверяет retry без full restart. Negative scheme отключает новый P2 flag через прежний CPM_APP_INTEGRATION_DISABLE_P1_P2_FIXES; остальные controls и девять app methods сохранены. README (включая mapping P2 flag и 47 production regressions) обновлён; PR description дополнен одной строкой, существующие reviewer steps сохранены. Новый полный app ON/OFF/ON не запускался.

Артефакты: /private/tmp/cpm-pr7379-independent-retry-flag-20261020/ — normal/red-control test logs, lint, signed harness build/signature, iOS build и CI watch, PR description before/after. Существовавшие до работы локальные Package.resolved изменения не включены в commits; production dependency diff SHA256 по-прежнему 66123735bfe51a00cb1775b5526cf6b9c0310aee79d23fc0e4e47b1b62cbdcdb.