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

67 KiB
Executable File
Raw Blame History

Актуально — 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.

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

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.