Files
obsidian-vault/work/projects/cpm-web-extension-code-guide-2026-10-09.md
T

170 KiB
Executable File
Raw Blame History

title, date, tags, updated
title date tags updated
CPM Web Extension — карта кода по worktree и строкам 2026-10-09
work
cpm
webkit
2026-10-20

CPM Web Extension — карта кода по worktree и строкам

#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.

Проверено 20 октября 2026: карта ниже отражает существующие worktree и опубликованные heads; старые line numbers и результаты в архивных разделах относятся к своим ревизиям. PR/CI — cpm-status-2026-10-15#2. PR и quality gates. Пользовательский dirty Package.resolved в telemetry worktree сохранён.

0. Текущая карта worktree и точек входа

Все пути относительно /Users/admin/DuckDuckGo/apple-browsers.git/.

  • Episode telemetry: alex/cpm-telemetry-pr0, ветка alex/cpm-messaging-readiness-telemetry, head 5d1cb4abd2, #7376. PR закрыт без merge, CI зелёный. Начинать с report/payload, затем monitor, diagnostics/encoder, recorder и readiness observer. Полный contract — cpm-pr0-episode-telemetry-summary-2026-10-16.
  • Тесты episode/state transitions: SharedPackages/WebExtensions/Tests/WebExtensionsTests/CPMMessagingHealthMonitorTests.swift; payload/timeline — соответствующие Diagnostics/Recorder tests в том же каталоге. Definitions и dictionaries — обе платформы, {iOS,macOS}/PixelDefinitions/pixels/. Новый stuck — четыре значения; bg_events — initial;until-first-stuck, общие 12 events/255 chars, ... означает усечение. Initial phase не имеет зарезервированного бюджета.
  • macOS telemetry: alex/cpm-telemetry-macos-release, ветка alex/cpm-messaging-readiness-telemetry-macos-release, 3fb13b81fe, #7484. Старый was_stuck, без двухфазного timeline; release-base conflict. Это не идентичная копия текущего #7376.
  • P1/P2/P4: alex/cpm-fix-init-loss-production, alex/cpm-fix-init-loss, 674bb809f2, #7379 на telemetry branch. Главные точки — Manager/WebExtensionManager.swift, Autoconsent/CPMBackgroundReadinessRecovery.swift и Pixels/WebExtensionPixelFiring.swift внутри WebExtensions Sources. Independent startup_response_missing не зависит от default-OFF late reload; recovery outcomes не являются page ACK. CI BSK красный. Отдельный app harness — alex/cpm-fix-p1-p2, codex/cpm-fix-init-loss-integration-tests.
  • Network recovery: alex/cpm-network-process-recovery, f41c7b7047, #7459 на telemetry branch; watch/restart, manager wiring и CPMNetworkProcessRecoveryTests.swift. Applied pixel в metadata/обоих definitions: daily+count, no custom params, только после принятого restart. Нет доказательства recovery и нет network_replaced_since_view в episode. Harness: alex/cpm-network-process-integration-tests, codex/cpm-network-process-integration-tests.
  • P3 stable origin: alex/cpm-p3-stable-base-url, dd96018da9, #7493 на telemetry branch; production default ON, remote kill switch. Это уже опубликованный ограниченный CPM origin policy, не старый глобальный M2 prototype. Harness alex/cpm-p3-integration-tests, codex/cpm-p3-integration-tests; full P3 failure остаётся невоспроизведённым.
  • P5 shared pinned close: #7473 MERGED 20 октября 2026 в release/macos/1.213.0, merge 9bcce0264e; финальный reviewed/tested head 574e9288ae, worktree alex/cpm-p5-pinned-window-close. Default ON + remote failsafe, CI зелёный. Harness остаётся отдельно: alex/cpm-p5-integration-tests, codex/cpm-p5-release-integration-tests @ add6e514fe. Один доказанный tab-lifecycle mechanism; rollout не подтверждён.
  • Большой rewrite: alex/cpm-episode-telemetry, 7e8128c94f — альтернативный prototype, не реализация #7376. Не читать CPMEpisodeTelemetry.swift/CPMEpisodeSummary.swift как текущий PR.
  • Старый самостоятельный harness #7378 и baseline #7384 закрыты без merge. Native progress #7385 и JS #3727 открыты и не встроены в #7376; end-to-end delivery требует обеих сторон и обновлённого extension bundle.

Для ручной проверки именно terminal-report contract — CPM Breakage Testing Steps. Прежние commands/counts/line mappings ниже сохранены как история, а не инструкции для текущего head.

P5 после merge

Факты merge, результаты и ограничения — cpm-status-2026-10-15#P5 — merged 20 октября 2026. Merge commit 9bcce0264e; локальный production worktree сохраняет финальный PR head 574e9288ae. Ссылки/строки ниже относятся к этому локальному head.

  • Window close и единый ownership helper: explicit tab closes → unregister → didCloseWindow; guard на app registry + requesting context находится на строке 639, helper — 655. Closing-state не хранится.
  • WebKit tabs/activeTab delegate: исключает только выжившие tabs при закрытии; activeTab согласован с closing list, реальная selection не меняется.
  • Failsafe: webExtensionSharedPinnedTabWindowClose, default ON, remote webExtensions.sharedPinnedTabWindowClose; registry task.
  • Unit regression проверяет WebKit openTabs после настоящих context callbacks и app register/unregister; flag-OFF reproduction — строка 143. Эти unit tests вошли в PR.
  • Не вошли в merge: реальные app-window tests, пять CPM fixture Swift files, dedicated schemes/DEBUG hooks и isolated controller configuration. Они только в alex/cpm-p5-integration-tests, branch codex/cpm-p5-release-integration-tests @ add6e514fe; README — macOS/IntegrationTests/CPM/README.md. Это 13 review-only paths относительно production head; public WebExtensionManager API в merged production diff не меняется.
  • Evidence для 574e9288ae: 209 unit PASS; app ON 9 → OFF 5 expected failures + 1 healthy control → ON 27 PASS, одинаковые 4 886 файлов bundle; build/signing/lint/CI PASS. Manifest: /private/tmp/cpm-p5-pr-comments-20261019/validation.json. Эти тесты не убивают процесс. History-based window restoration отдельно не проверялась; last-window close → new window проверен.

Архив кратких обновлений — 16–19 октября

Актуально — 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 не являются текущим статусом.

App integration update — 16 октября 2026, 01:48 Бишкек. В cpm-e2e-init добавлены 20 методов настоящего app-hosted CPM suite: финальные 20/20 PASS, 0 failures/skips/expected failures, группы 18+1+1 на одной signed build. Схема CPM Integration Tests; файлы/guards/запуск/ограничения — §5 ниже, полный реестр и история — cpm-status-2026-10-15#Финальный app-hosted итог — 16 октября 2026. Без commits. Карта остальных worktree/PR ниже сохраняет свою датированную сверку 15 октября.

Актуальная карта — 15 октября 2026. Текущий статус PR/CI, данные и все 14 новых P5/P6 результатов: cpm-status-2026-10-15 (§2, §5, §10–12). Датированные исходные разделы 1–4 ниже сохранены; их «ничего не закоммичено», номера строк и общий worktree описывают 9 октября, а не текущее состояние.

Историческая карта worktree и запусков — 15–19 октября

Корень: /Users/admin/DuckDuckGo/apple-browsers.git/. Проверены git worktree list, HEAD и наличие тестовых файлов. Единого worktree со всеми suites нет. Общая база в истории не включает local dirty/untracked файлы; особенно это относится к remaining-failures и scratch init-progress E2E.

Worktree Ветка / текущий HEAD Назначение и границы
alex/cpm-web-extension-remaining-failures та же; a0717cf098cd Основное расследование без A/B watchdog: P1 (3 wake), P2 (9 load failure), P3 (2 cache/cleanup), новые P5/P6 (12 lifecycle + 2 flag). Все 28 repro opt-in; CPMRepro/ untracked. Production dirty telemetry — прежняя копия, не переносить вместе с тестами
cpm-repro-harness alex/cpm-repro-harness; dfb96279196d PR #7378: базовый harness, быстрые CI-контроли, медленные сценарии и raw WebKit characterization; без новых P5/P6
cpm-fix-init-loss — историческая строка; worktree удалён 16 Oct alex/cpm-fix-init-loss; 7ad771e227bb PR #7379: A, первые init при install/upgrade mid-session; красное/зелёное доказательство отдельно от remaining-failures
alex/cpm-fix-init-loss-production — актуально 19 Oct Production alex/cpm-fix-init-loss; published 8275bcce36 PR #7379 / база #7376 39fe56af4c: 10 commits / 23 paths, 38 новых shared regressions, 201 штатный PASS. Error-6/P4 attribution исправлен fc124938e0 + 2 штатные регрессии при late flag OFF/ON. CI 43 SUCCESS / 17 SKIPPED, без failures/pending. Незакоммиченные параллельные изменения worktree не включены в validation; чистый checkout /private/tmp/cpm-pr7379-error6-fix-20261019/source возвращён на production head. Формы/default late OFF не менялись
Временно alex/cpm-fix-p1-p2; app validation выполнен в чистом /private/tmp/cpm-pr7379-error6-fix-20261019/source codex/cpm-fix-init-loss-integration-tests; published 6d04496882 Harness содержит production 8275bcce36; 9 app methods, ровно 12 paths вне main, README: 38 новых shared regressions. Signed app ON 9 PASS → OFF 6 functional FAIL → restored ON 9 PASS; detection-only OFF без reload PASS дважды; SHA256 app/test modules совпали. Первый restored 7 PASS / 2 FAIL (teardown/SIGINT) сохранён, повтор без изменения binaries/assertions. Параллельные dirty edits исходного worktree не трогались
cpm-fix-network-crash alex/cpm-fix-network-crash; local f1085846e7ff B поверх A; 5 network/termination сценариев в FullFailure + 11 watchdog unit tests. Remote PR #7381 остаётся на 39f94e12eaa4, красный Non-Sandbox; локальный fix не запушен
cpm-fix-pixels alex/cpm-fix-pixels; d6d800846d1f A/B + PR0, измерение first_load_wait/background_restart; отдельный PR не зарегистрирован в текущем статусе
alex/cpm-messaging-readiness-telemetry та же; 619869ee84c6 PR0 #7376: readiness/failure/recovery параметры, CI без failure/pending, review required
cpm-readiness-baseline alex/cpm-readiness-baseline; 99ecf8b12787 #7384 поверх PR0: baseline readiness; Danger=FAILURE
cpm-init-progress-native alex/cpm-init-progress-native; 46f25175c7c4 #7385 поверх baseline: init_stage, 11 CPMInitProgress unit tests; Danger=FAILURE. Нужен JS privacy-extension#3727
cpm-e2e-init scratch/cpm-e2e-init; 46f25175c7c4 (HEAD сохранён, без новых commits) Прежний scratch native init-progress/SPM harness плюс новые 20 app-hosted XCTest methods в macOS/IntegrationTests/CPM/ и схема CPM Integration Tests; результаты и ограничения — §13 status. Наличие HEAD, совпадающего с #7385, не означает наличие untracked suites в PR
alex/cpm-web-extension-ready-handshake та же; a0717cf098cd Старый объединённый локальный A/B harness и slow-wake-with-fixes; архив сравнения. Текущие PR A/B нарезаны в worktree выше
cpm-stable-base-url alex/cpm-stable-base-url; 570c2f8ef479 Старый M2 experiment: меняет baseURL всем extensions, не доведён и не прогнан через нужный integration harness. Прежнее «production-ready» в старых планах не является актуальным итогом

CI статусы — read-only snapshot GitHub 15 октября, 17:26 UTC. Подробные head/base/checks и все оговорки — основной статус; локальные воспроизведения не дают зелёного CI незапушенному коду.

0.1. Файлы remaining-failures и полный охват

Путь тестов — SharedPackages/WebExtensions/Tests/WebExtensionsTests/CPMRepro/.

Файл Что искать
CPMReproLifecycleHypothesisTests.swift:30 12 методов: nil/previous controller, startup healthy control, source-linked shared-window close + unrelated-window control, forgotten live tab, listener metadata, long documents/dashboard loss, host main-actor stall
CPMReproProductionFlagTests.swift:30 2 метода: главный flag true→false→true даёт P6; true→true не меняет manager; embedded-only cycle сохраняет controller и работает после explicit ready wait
CPMReproBackgroundLoadFailureTests.swift:31 9 методов P2: ≥30-секундный медленный запуск, 10-секундный контроль, file/script/bindings ошибки и четыре отрицательных process/load проверки
CPMReproExtensionLoadCleanupTests.swift:36 2 метода P3: relaunch и reload при большом Network cache и смене baseURL
CPMReproWakeExperimentTests.swift:25 3 метода P1: 5/12-секундный wake и сравнение readiness signals
CPMReproTestCase.swift:37 Базовый opt-in CPM_REPRO=1, Options, cleanup. existingTabs (68) предоставляет сохранённые view до load нового context
CPMReproHarness.swift:258,269,296 open/close additional window через production eventsListener; adopt existing view. :175 watcher без strong reference через await; :365 content marks
CPMReproTabs.swift:29,148,165 Реальные WKWebView, navigation gate/monitor callbacks, window/tab delegates и multiple-window provider
CPMReproDelayedResource.swift:26 Реальный 35-секундный image subresource; URL уникален на каждую навигацию
CPMReproPrelude.swift DOM init/initResp marks, trace всех autoconsent payloads, startup/listener test seams
CPMReproSupport.swift:43,92,175,213 Pixel recorder; optional native-method suppression; temporary instrumented extension copy; WebKit process SPI

Результаты: все 14 новых методов P5/P6 имеют pass по нескольким запускам; последние обычные tests — 478 XCTest / 28 skipped / 0 failures (10.469 с), strict SwiftLint восьми изменённых файлов — 0. P1/P2/P3 в этом продолжении заново не запускались. Таблица всех 14, начальные красные результаты, log paths и SHA-256 — основной статус §12.

0.2. Browser → WebKit paths

P5: MainWindowController.windowWillClose (611–640) фильтрует сохраняемые tabs только для явных didCloseTab, затем unregister и didCloseWindow. MainWindowController+WKWebExtensionWindow.tabs(for:) (31) всё ещё возвращает loaded pinned + regular tabs. WindowControllersManager.unregister (178) не очищает closing-window collections. WebKit внутри WebExtensionContext::didCloseWindow сам вызывает didCloseTab для каждого delegate tab; тот попадает в forgetTab. runtimeSendMessage возвращает tab-not-found до wake. Проверены текущий browser worktree и macOS tag 1.210.0+macos; shared-window effect исполнен на системном WebKit.

P6: AppDelegate.setupWebExtensions/initializeWebExtensions (2153–2166, 2209–2221) и shared FeatureFlag/WebExtensionFeatureFlagHandler.swift: main disable → uninstall + clear references; enable при manager=nil → новый manager/controller без пересоздания старых WKWebView. WebExtensionTab::webView отвергает неправильный controller. Только test-controlled main-flag cycle доказан; исторические данные не подтверждают такой production transition. Default main flag enabled; повторный true и embedded-only toggle не заменяют controller.

WebKit source checkout: /Users/admin/Downloads/WebKit_sparse, HEAD 99051d5d08cd9f19ec76ce599f7539d070b1ae09:

  • Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionContextCocoa.mm:1351,1419;
  • Source/WebKit/UIProcess/Extensions/Cocoa/API/WebExtensionContextAPIRuntimeCocoa.mm:129;
  • Source/WebKit/UIProcess/Extensions/Cocoa/WebExtensionTabCocoa.mm:339.

Это карта source contract и system-WebKit проверки, не утверждение о полном совпадении checkout с shipped binary. В SPM исполняются production shared classes и WebKit, а app-side host callbacks/delegates реализованы harness.

0.3. Команды и предусловия

Из alex/cpm-web-extension-remaining-failures/SharedPackages/WebExtensions:

CPM_REPRO=1 CPM_REPRO_P5_P6=1 swift test --disable-automatic-resolution --filter 'CPMReproLifecycleHypothesisTests|CPMReproProductionFlagTests'
CPM_REPRO=1 CPM_REPRO_P5_P6=1 swift test --disable-automatic-resolution --filter 'CPMReproProductionFlagTests|CPMReproLifecycleHypothesisTests/testClosing'
CPM_REPRO=1 swift test --disable-automatic-resolution --filter CPMReproWakeExperimentTests
CPM_REPRO=1 swift test --disable-automatic-resolution --filter CPMReproBackgroundLoadFailureTests
swift test --disable-automatic-resolution --skip-build

Первая команда всех 14 дана для повторения: в текущей сессии 14 методов проверялись раздельными группами. --skip-build применим после актуальной сборки. Для P3 нужны CPM_REPRO_CACHE_URL (server /fill.html?n=N) и CPM_REPRO_CACHE_ENTRIES (default 20000; заполнение порядка 10 минут), затем filter CPMReproExtensionLoadCleanupTests.

Выделенный PR-harness в cpm-repro-harness имеет быстрые tests без общего opt-in и requireLocalRun для тяжёлых; raw WebKit characterization требует также CPM_REPRO_WEBKIT=1. Новые P5/P6 живут только в remaining-failures и в PR-harness ещё не переносились.

Environment P5/P6: macOS 26.7.1 (25G241), Xcode 27.1 (27A9275), embedded bundle 2026.9.29. M4 в этих 14 tests выключен, gate включён, Network PID прогрет до context-load; production bundle zip не правился, temporary copy содержит trace/DOM instrumentation. Нативные flags в production не переключались.


Архив карты на 9 октября. Все следующие разделы сохранены для старых source line references и истории экспериментов; текущие точки входа и статус — выше.

Контекст: cpm-web-extension-breakage-session-summary-2026-10-07 (раздел 10), cpm-web-extension-repro-and-fix-2026-10-08. Номера строк — на 9 октября. Ничего не закоммичено. Корень всех worktree — /Users/admin/DuckDuckGo/apple-browsers.git/; пути ниже даны от корня worktree. SP = SharedPackages/WebExtensions/Sources/WebExtensions, TP = SharedPackages/WebExtensions/Tests/WebExtensionsTests.

Worktree Ветка, база Что внутри
alex/cpm-web-extension-ready-handshake та же, a0717cf098 Фиксы + основной harness
alex/cpm-web-extension-remaining-failures та же, a0717cf098 Прод-код без фиксов, error 6 телеметрия (старая копия), репро error 6, очистки, медленного пробуждения
alex/cpm-messaging-readiness-telemetry та же, main 92e09cdbbc Телеметрия фазы 1 (включает error 6) — кандидат на первый PR
cpm-stable-base-url alex/cpm-stable-base-url, старая база 570c2f8ef4 Эксперимент со стабильным baseURL

1. Фиксы — alex/cpm-web-extension-ready-handshake

Цепочка: навигация → coordinator спрашивает менеджер → менеджер проверяет watchdog и незавершённый первый старт background → при сбое монитор зовёт перезапуск.

  1. SP/Lifecycle/WebExtensionLifecycleCoordinator.swift:79-93 — initialLoadWaiter, его вызывают обе платформы на каждой main-frame навигации. Было: после открытия стартового gate → nil. Стало: :89 зовёт manager.prepareEmbeddedBackgroundForNavigation() и ждёт его не дольше initialLoadTimeout (5 с, :91-92).
  2. SP/Manager/WebExtensionManager+EmbeddedBackground.swift (новый):
    • :35 prepareEmbeddedBackgroundForNavigation() — сначала watchdog.restartBackgroundIfStale() (:36), потом возвращает waiter, если идёт первый старт background только что установленного extension.
    • :45 trackEmbeddedBackgroundStartup(identifier:) — запускает context.loadBackgroundContent() (:49) как Task и держит его в embeddedBackgroundStartup, пока не завершится. Зачем: WebKit при первой загрузке нового идентификатора грузит background сразу и теряет init, пришедший до выполнения скрипта (317981).
  3. SP/Manager/WebExtensionManager+EmbeddedExtensions.swift:178-180 — после installationStore.add для .embedded вызывается trackEmbeddedBackgroundStartup. Покрывает установку и обновление посреди сессии (на запуске это уже делал стартовый gate).
  4. SP/Manager/WebExtensionManager.swift:
    • :134-139 — свойства embeddedBackgroundWatchdog и embeddedBackgroundStartup.
    • :167 — параметр init isEmbeddedBackgroundRecoveryEnabled (по умолчанию { true }, к удалённому флагу не подключён).
    • :186 — создание watchdog.
    • :217-221 — healthMonitor.onEpisodeStarted → restartBackgroundIfResponsive(reason:): перезапуск по первому сбою.
    • :757 — в делегате didCreateBackgroundWebView watchdog получает новую background view.
  5. SP/Lifecycle/EmbeddedBackgroundLivenessWatchdog.swift (новый):
    • :63 init — все зависимости подменяемые (PID, перезапуск, проба отзывчивости).
    • :76 backgroundWebViewDidChange — запоминает view и PID Network-процесса, запускает периодическую проверку.
    • :85 restartBackgroundIfStale — PID Network-процесса сменился (или исчез) → перезапуск. Это и есть детектор «Network-процесс упал, worker мёртв».
    • :107 restartBackgroundIfResponsive — перезапуск по сбою, только если процесс ответил на return 1 за 1 с (:166-170). Замороженный не трогаем: убийство остановленного процесса давало глухой новый worker.
    • :137 периодическая проверка раз в 1 с; :156 _networkProcessIdentifier (SPI через KVC); :173-180 перезапуск через _killWebContentProcessAndResetState — WebKit поднимает новый worker, и чинятся даже уже открытые документы.
  6. SP/Autoconsent/CPMMessagingHealthMonitor.swift:96-100 — колбэк onEpisodeStarted; :656-658 — вызывается на первом сбое нового эпизода, только для failureReason == .other (не session restoration).
  7. SP/Manager/WebExtensionManaging.swift:164-168 — требование протокола; :176-178 — реализация по умолчанию { nil }, чтобы моки и платформы не ломались.

Тесты:

  • TP/EmbeddedBackgroundLivenessWatchdogTests.swift — 11 unit-тестов (:48–:150): смена PID, исчезновение Network-процесса, отзывчивый и неотзывчивый процесс, выключатель, stop(), периодическая проверка.
  • TP/WebExtensionLifecycleCoordinatorTests.swift:193, :217, :227, :243 — навигация ждёт первый старт; не ждёт, если готов; ожидание ограничено 5 с; при выключенном gate ничего не готовится. Мок — :667.
  • TP/CPMMessagingHealthMonitorTests.swift:50, :61, :71 — onEpisodeStarted на первом сбое; не на session restoration; снова для нового эпизода.
  • Harness TP/CPMRepro/ (запуск: CPM_REPRO=1 swift test --filter CPMRepro из SharedPackages/WebExtensions):
    • CPMReproSingleTabTests.swift — 10 тестов одной вкладки: холодный старт :32, обновление на запуске :46, установка/обновление посреди сессии :64, :87 (до фикса терялись), перезапуск :111, :128, после reload :146, :165, пробуждение :187, падение background :206.
    • CPMReproFullFailureTests.swift — краш Network-процесса :33, :38, :55 (без M4); смерть worker'а через SPI :76 и удаление регистраций :85 (стоит одну навигацию); не-триггеры :124, :129, :136.
    • CPMReproWebKitTests.swift — 7 тестов, нужен CPM_REPRO_WEBKIT=1: защиты выключены, утверждают, что баги WebKit ещё есть (:45 потеря init при первой загрузке, :80/:87/:151 мёртвый worker, :97 только перезапуск background чинит открытые документы, :133 сообщение из страницы background не доходит до worker'а).
    • CPMReproWakeExperimentTests.swift:27-28 — эксперимент, не для коммита: медленное пробуждение 5 и 12 с с фиксами. Для него в CPMReproHarness.swift свойство storage сделано не private.

2. Расследование без фиксов — alex/cpm-web-extension-remaining-failures

Прод-код как в релизе; harness перенесён без watchdog, с production-recorder'ом, поэтому сбои дают те же параметры пикселей, что в проде.

  • TP/CPMRepro/CPMReproHarness.swift: :51 recorder диагностики; :191 contextErrorCodes; :196 папка установленного extension; :203 prependToBackgroundScript — дописывает код в начало background-скрипта на диске (WebKit читает его заново на каждом пробуждении); :212 PID Network-процесса; :262 loadRealPage (для наполнения кэша).
  • TP/CPMRepro/CPMReproBackgroundLoadFailureTests.swift — error 6, 9 тестов, все с проверками:
    • :59 новый процесс background заморожен на 45 с при пробуждении → только :6, bg_load_error_after=25s_to_35s. Это таймер выгрузки WebKit.
    • :70 10 с → error 6 нет.
    • :79, :89, :96 — другие пути к error 6 (нет файлов, скрипт бросает, нет browser) — быстрые, under_5s; в проде их сигнатур нет.
    • :104, :111, :118, :125 — условия, которые error 6 не дают.
  • TP/CPMRepro/CPMReproExtensionLoadCleanupTests.swift:49, :69 — задержка очистки при смене baseURL на перезапуске и reload. Нужен локальный сервер: CPM_REPRO_CACHE_URL, CPM_REPRO_CACHE_ENTRIES (наполнение ~10 мин).
  • TP/CPMRepro/CPMReproWakeExperimentTests.swift — эксперимент, не для коммита:
    • :27 старт worker'а 5 с на пробуждении → initialization_failed с сигнатурой группы 1, затем поздний ответ.
    • :28 12 с + навигация → stuck → M4.
    • :31 сигналы готовности: isLoading=false через 0,1 с (бесполезен), completion loadBackgroundContent и первое нативное сообщение — ровно на старте worker'а.
  • Продовые изменения здесь (CPMMessagingDiagnostics*, JSON5, WebExtensionManager+iOS.swift, AppDelegate.swift) — старая копия телеметрии error 6, она целиком перенесена в worktree телеметрии. Отсюда не коммитить.

3. Телеметрия фазы 1 — alex/cpm-messaging-readiness-telemetry

Только параметры пикселей, поведение детектора не меняется.

  1. SP/Autoconsent/CPMMessagingDiagnostics.swift:
    • :29 ApplicationState, :38 провайдер состояния приложения в CPMAppSessionDiagnostics.
    • :50 CPMBackgroundReadiness: noBackground / pending / loaded(seconds) / failed.
    • :109-123 новые поля снимка (error 6, applicationState, возраст view, готовность, вкладки).
    • :182-188 имена параметров (bg_load_error_*, app_state, bg_view_age, bg_ready_after, open_tabs, loading_tabs).
    • :217-231 сериализация: error 6 — none, если ошибки не было, и опускается, если неизвестно; остальные опускаются при nil.
    • Бакеты: :248 error 6 (вокруг таймера 30 с), :258 возраст view, :269 готовность (вокруг 4 с монитора и 30 с WebKit), :285 число вкладок.
  2. SP/Autoconsent/CPMBackgroundReadinessObserver.swift (новый) — откуда берётся bg_ready_after:
    • :52 observe на создании view: ставит pending и на следующем шаге run loop (:56) зовёт loadBackgroundContent. View уже есть, поэтому вызов лишь присоединяется к идущей загрузке и ничего не будит.
    • completion → loaded(секунды от создания view) или failed; ответ для заменённой view игнорируется.
    • :34 загрузчик подменяется в тестах; :72 readiness(of:) — только для текущей view.
  3. SP/Autoconsent/CPMMessagingDiagnosticsRecorder.swift:
    • :125, :141 наблюдатель; :223 сброс при новом контексте.
    • :311-316 наблюдение включается тем же флагом, что и delegate proxy (cpmBackgroundDelegateProxy).
    • :413-415 поля error 6; :426 состояние приложения; :430-431 возраст view и готовность; :435-438 open_tabs / loading_tabs из context.openTabs и webView(for:).isLoading.
    • :503-517 recordContextErrors — при error 6 фиксирует состояние приложения и секунды от создания view.
  4. SP/Pixels/WebExtensionPixelFiring.swift:
    • :71, :73 — у recovery-событий появился details (по умолчанию nil, старые вызовы не ломаются).
    • :85 CPMMessagingRecoveryDetails: failed_navigation (опоздавший ответ) / later_navigation / unattributed + :108 бакеты recovery_after.
    • :181-188 параметры пикселя.
  5. SP/Autoconsent/CPMMessagingHealthMonitor.swift:
    • :451-452 неатрибутированный ответ закрывает stuck → unattributed.
    • :712-716 обычное восстановление: тот же упавший замер → failed_navigation, иначе later_navigation.
    • :722 recoveryDetails — секунды от первого сбоя эпизода.
  6. Приложения: iOS/DuckDuckGo/WebExtensions/WebExtensionManager+iOS.swift:107-114 (UIApplication.applicationState), macOS/DuckDuckGo/Application/AppDelegate.swift:122-123 (NSApp.isActive).
  7. JSON5:
    • словари iOS/PixelDefinitions/pixels/params_dictionary.json5 (:602 recovery, :619 error 6, :643 готовность и вкладки) и macOS/.../params_dictionary.json5 (:677, :694, :718);
    • определения — iOS debug_pixels.json5, macOS web_extensions.json5: по 8 пикселям сбоя и 2 пикселям восстановления.

Тесты:

  • TP/CPMMessagingDiagnosticsTests.swift:
    • бакеты :135, :144, :149; полный набор параметров :154;
    • error 6 :279, :417;
    • готовность: загрузилась :304, упала :327, заменённая view :343, наблюдение выключено :360;
    • состояние приложения :377; вкладки на реальном контроллере с незавершающейся загрузкой :384.
  • TP/CPMMessagingHealthMonitorTests.swift: опоздавший ответ :1061, следующая навигация :1081, unattributed :1095, бакеты :1112, обновлённый тест параметров :1119.
  • Проверка на реальном WebKit (harness временно копировался): медленное пробуждение 5 с → bg_ready_after=pending, bg_view_age=4s_to_8s, затем recovery_document=failed_navigation, recovery_after=under_4s.

4. Стабильный baseURL — cpm-stable-base-url

  • SP/Loading/WebExtensionLoader.swift:56, :93, :134, :154, :158-165 — в makeContext выставляется context.baseURL = webkit-extension://<uniqueIdentifier>/; если из идентификатора не собрать URL — ошибка invalidIdentifier.
  • TP/WebExtensionLoaderDelegateTests.swift:61-94 — 2 теста: URL выставлен до загрузки; неверный идентификатор → загрузка не начинается.
  • Открыто: сейчас меняет URL всем extension (нужно — только встроенным без web_accessible_resources); не прогнан через harness (M4, краш Network-процесса, обновление); старая база.

5. App-hosted CPM integration tests — 16 октября 2026

Worktree /Users/admin/DuckDuckGo/apple-browsers.git/cpm-e2e-init, branch scratch/cpm-e2e-init, HEAD 46f25175c7c42766cab23ea39f447f075c7bdd24, без commits. Новая схема macOS/DuckDuckGo-macOS.xcodeproj/xcshareddata/xcschemes/CPM Integration Tests.xcscheme выбирает только две CPM classes, отключает parallel testing и включает CPM_APP_INTEGRATION=1. В ней нет Review-profile wipe/pre-action или killall tests-server.

Файл в macOS/IntegrationTests/CPM/ Роль
CPMAppIntegrationTests.swift 10 deterministic baseline/diagnostics/scope/recovery tests: slow HTTP/native, одна навигация, одна таба, несколько табов одного окна, все окна, M4, dashboard transport, proxy flag
CPMAppKnownFailureIntegrationTests.swift 10 characterization methods: actual AppDelegate flags, shared-pin window closure, Network/background crashes, first install, slow idle wake, frozen WebKit load timeout, 20k persistent-cache reload
CPMAppIntegrationHarness.swift Реальные AppDelegate/WindowsManager/MainWindowController/Tab, production navigation/monitor/recorder, JSON attachments, owned windows/data stores, bounded cleanup
CPMAppIntegrationSupport.swift Реальный macOS native handler/provider/delegate с fault boundary; recorder transport before daily dedup; extraction через production storage; in-memory installation store; test-only PID/background SPI
CPMAppIntegrationBridge.swift Instrumentation только распакованной временной extension copy: page initResp mark, реальные runtime messages и scoped drop/release controls
CPMAppFixtureServer.swift Owned HTTP loopback, eight-second resource delay, cacheable 2KiB resources with unique URLs
README.md Повторение, signing, flags, все сценарии, ограничения причинной интерпретации

Все 6 Swift files включены в Integration Tests и Integration Tests App Store. Минимальные production seams: optional manager controllerConfiguration с прежним default; DEBUG AppDelegate factory с двумя guards; отдельный ConfigurationStore directory для CPM test host; разрешён только loopback HTTP в opted-in integration Tab; macOS diagnostics flag adapter доступен через @testable без изменения поведения. SecureVault/AppMain bypass отсутствует. Существующие dirty ZIP/SPM files сохранены.

Запускать с project signing defaults, как в Xcode; unsigned override оказался ошибкой bootstrap и удалён. CLI run recipe находится в README. Для реального 30s WebKit timeout нужен test-host env CPM_APP_INTEGRATION_EXPENSIVE=1; для persistent cache — CPM_APP_INTEGRATION_CACHE=1, при необходимости CPM_APP_INTEGRATION_CACHE_ENTRIES, execution allowance 2400 s. Cache case лучше выбирать отдельно; этот opt-in включает fresh persistent UUID configuration в harness. Обычные запуски используют nonpersistent stores.

Артефакты /private/tmp/cpm-app-integration-20261015/: signed .xcresult, logs, exported JSON, app-test-results.json (история результатов и hashes исходников). Финальные результаты сверять с §13 cpm-status-2026-10-15, не считать каждый characterization test доказательством воспроизведения причины. P3 может пройти с отрицательным outcome; background crash может самоизлечиться. App P5 ограничен одной потерянной навигацией и контролями: более длинная попытка прерывалась DEBUG guard закрытого окна в XCTest. Persistent P5/stuck доказан отдельно SPM, что не превращает app attempt в green. iOS/device-only причины и естественная потеря listener metadata этим suite не доказаны.

App harness isolation follow-up: extension resources now use an owned UUID directory under unswizzled NSTemporaryDirectory(), outside com.duckduckgo.macos.tests. The latter is a shared FileManager swizzle target that TestRunHelper removes on host initialization/bundle completion. A preceding joint run passed 16/18 but lost its Network-test extension resource before reload (extensionNotFound), then the next wake test hit INT. The deleter was not identified; latest status must include that red run and the resource-isolation recheck, rather than treating prior isolated passes as a green combined suite. CPMAppExtensionStorage.resolveInstalledExtension still delegates to production and adds only missing-folder/root logging.

Финальная сверка §5: signed-isolated-regression 18/18, signed-isolated-pinned 1/1 (72.644 s), signed-isolated-cache 1/1 (43.053 s). Все summaries: 0 failures, 0 skipped, 0 expected failures. В последнем cache run 20k ресурсов за 39.113 s, post-reload probe 0.900 s, P3 не воспроизведён, UUID store удалён. Все 20 JSON exported в одноимённые *-evidence/ directories; /private/tmp/cpm-app-integration-20261015/app-test-results.json содержит текущие hashes исходников и всю per-method историю. HEAD 46f25175c7c42766cab23ea39f447f075c7bdd24 сохранён, исходный dirty ZIP не менялся. Финальный strict lint: 11 Swift files, 0 violations; PBX и scheme XML валидны. Предыдущие red attempts сохранены, не превращены в pass; единый invocation всех 20 не выполнялся.

16 Oct clarification/rerun: all 20 current app methods passed again in 18+1+1 groups, same signed build and source hashes; /private/tmp/cpm-app-integration-20261015/rerun-failed-20261016-042858/rerun-summary.json. This is an instrumented app-test environment, not an unchanged shipping binary. P1/P2 delay/SIGSTOP and message/native/dashboard loss are imposed faults; P5/P6/Network use real lifecycle paths but their production occurrence/causal attribution is a separate claim. Old long P5 is still outside the verified app scope; P3 remains unreproduced. Cache teardown has a recorded nonfatal SQLite warning. Submodules are not required by these CPM cases: privacy-reference-tests resources map to Unit Tests targets, SnapshotReferences to snapshot testing support, not XCUI accessibility snapshots. Neither submodule was initialized or modified by this rerun.

Локальный кандидат P1/P2 — 16 октября 2026 (без commits)

Worktree cpm-e2e-init, HEAD всё ещё 46f25175c7c42766cab23ea39f447f075c7bdd24. Эта секция дополняет прежнюю карту: #7379 не изменялся, новая работа пока только локальная.

  • WebExtensionLifecycleCoordinator.initialLoadWaiter: после launch gate проверяет подготовку background на каждом HTTP(S) main-frame navigation. Await ограничен прежними 5 s и отменой navigation; AsyncStream позволяет освободить navigation даже при callback WebKit, игнорирующем cancellation. Жизненный цикл load/sync этим не блокируется.
  • WebExtensionManaging.prepareEmbeddedBackgroundForNavigation: новый protocol hook с no-op default для лёгких conformers. Реализация — WebExtensionManager.swift, без нового project file.
  • WebExtensionManager.loadEmbeddedExtensionBackgroundContent: публичный callback API + одна shared startup task на текущий context. Error notification завершает/очищает старую readiness task, чтобы новая попытка не приклеилась к завершённому старому startup.
  • WebExtensionManager.recoverEmbeddedBackgroundLoadFailure: собственный текущий embedded context, настоящий domain/code 6, существующий recovery kill switch, known app_state != background, отсутствие M4 in-progress и cooldown 60 s. Повторяется только background load; context/Tab/controller не заменяются. Полный M4 reload остаётся при confirmed stuck. Старый full-context P2 prototype отброшен: он терял page initResp в existing tab при повторе.
  • CPMAppKnownFailureIntegrationTests.testSlowBackgroundWakeKeepsFirstNavigationHealthy: actual idle + 8 s worker delay, первый документ получает native+page без detector failure.
  • ...testFrozenBackgroundRecoversAutomaticallyForNextNavigation: actual one-tab idle wake, owned SIGSTOP 45 s, настоящий error 6. Требует native+page на том же failed document до новой navigation, тот же объект context и recovery_document=failed_navigation; затем healthy existing/new-window/new-tab.
  • Raw P1 и P3 characterization отключают navigation gate; P5 остаётся с gate включённым и ожидает bucket bg_view_creations=3_to_5: подготовка P1 создаёт дополнительный background перед rejected unknown-tab message. P5 tab-registration loss и healthy controls по-прежнему проверяются.

Артефакты и snapshots: /private/tmp/cpm-p1-p2-fixes-20261016/. before-changes.tar.gz сохраняет прежние dirty changes; point-fixes.diff предназначен для delta этой работы. Начальный background-only result — 2/2 PASS, пакет 806/14 skipped/0 failures. Общий run/negative controls/P5/cache ещё выполняются; окончательный исход — в cpm-status-2026-10-15. Зелёный случай относится к macOS с imposed timing/process faults; natural iOS cause по-прежнему не доказан.

Финальная сверка P1/P2, 16 октября 12:30 UTC: работа завершена без commits. validation-summary.json: 22/22 уникальных app methods PASS, positive groups 2+19+1+1 (P2 повторён), 0 failures/skips/expected failures; оба disabled-fix controls functional FAIL. unit-package-background-retry.log: 806 / 14 skipped / 0 failures; strict lint 6 файлов — 0 violations. Source hashes после сборки не менялись, прежние dirty files/ZIP сохранены. Окончательный P2 — background-only retry и same-document native+page recovery, не context replacement. Предыдущая full-reset реализация отвергнута после повторной потери page initResp. Current patch — /private/tmp/cpm-p1-p2-fixes-20261016/point-fixes.diff; P5 ожидает дополнительный view от P1, P3 остаётся отрицательным на 20,000 resources. Cache assertions прошли, но teardown снова имеет известный SQLite vnode warning для owned UUID. Подробная проверенная матрица/ограничения и весь red-history — cpm-status-2026-10-15.

Отдельный worktree P1/P2 — 16 октября 2026

/Users/admin/DuckDuckGo/apple-browsers.git/alex/cpm-fix-p1-p2, branch alex/cpm-fix-p1-p2, от alex/cpm-messaging-readiness-telemetry (01d4a0ec22), без коммитов. Отличается от полного scratch research-набора:

  • WebExtensionLifecycleCoordinator.initialLoadWaiter: после launch открывает ограниченное 5 s ожидание background wake; cancellation-safe AsyncStream, существующий gate flag.
  • WebExtensionManager.prepareEmbeddedBackgroundForNavigation / loadEmbeddedExtensionBackgroundContent: один startup job на конкретный context object, public WK callback, release pending callers при error/reload.
  • Observer WKWebExtensionContext.errorsDidUpdateNotification / recoverEmbeddedBackgroundLoadFailure: error 6 только своего embedded context, существующий recovery flag, current background guard, throttle 60 s; повтор background load без context replacement. M4 reload остаётся fallback.
  • Recorder isApplicationInBackground: читает уже существующий appSession lifecycle provider, не добавляет telemetry dimension.
  • macOS/IntegrationTests/CPM/: пять Swift-файлов, ровно два app-теста CPMBackgroundRecoveryIntegrationTests, сокращённая инфраструктура; схема CPM Integration Tests. Реальные app windows/tabs/native handlers/WebKit, неизменный bundled ZIP, extracted startup-delay и page initResp observation, SIGSTOP только своего background PID. Scoped drop/cache/Network/P3/P5 сценарии остались в research worktree.
  • Четыре новых метода WebExtensionLifecycleCoordinatorTests: wake после launch, bounded non-cancellable callback, cancellation, disabled flag. Всего 6 новых test methods; 22 — весь прежний app-набор.

Текущая база уже перешла на episode contract. Test-only diagnostics proxy фиксирует реальный first-failure вызов, не синтезируя monitor events. P2 требует terminal failed_measurement_response / reload_state=none плюс page initResp исходного документа до другой навигации и ту же context identity. Signed app 2/2 PASS; unit 31+134=165 PASS; strict lint 14 files / 0 violations. Оба disabled-flag контроля на той же сборке функционально FAIL. Test autorelease pools исправили deallocation guard без отключения проверок. Source hashes и исходный scratch неизменны; schemas/ZIP/dependencies в diff не менялись. Артефакты и полная история: /private/tmp/cpm-p1-p2-clean-20261016/validation-summary.json, cpm-status-2026-10-15. Границы P1 cap / macOS injection / неустановленного natural iOS trigger сохраняются.

Объединение #7379 с P1/P2 и независимый lifecycle guard — 16 октября 2026

Текущий alex/cpm-fix-p1-p2 семантически заменяет #7379 в пределах прежнего navigation timeout 5 s:

  • WebExtensionManager+EmbeddedExtensions.installEmbeddedExtension вызывает trackEmbeddedBackgroundStartup(identifier:) именно для вновь установленного embedded context.
  • Manager сохраняет preferred context, а prepareEmbeddedBackgroundForNavigation захватывает конкретный context object. Fallback учитывает append-порядок installation store и не выбирает произвольный context при неизвестном порядке нескольких версий. loadEmbeddedExtensionBackgroundContent(in:) coalesces job на тот же object.
  • recoverEmbeddedBackgroundLoadFailure игнорирует superseded context. Состояние background приходит через самостоятельный isApplicationInBackground provider; iOS factory читает UIApplication.shared.applicationState независимо от diagnostics flag. Старый diagnostics getter удалён. Перед queued retry повторно проверяются flag/background.
  • Два install/upgrade-теста #7379 адаптированы в CPMBackgroundRecoveryIntegrationTests рядом с P1/P2. Реальный upgrade даёт context sets [0,1,2,1]; assertions требуют native dashboard + page initResp первого документа, а не просто загрузку context. Default delay 4500 ms.
  • Пять новых manager unit tests проверяют coexistence/newest selection, fallback после удаления replacement, diagnostics=nil + background→foreground, runtime kill switch и отказ retry старого context. Вместе с четырьмя lifecycle tests в ветке 9 новых unit methods.

Финальная валидация: общий signed app 4/4 PASS; install/upgrade 10/10 + 10/10 PASS на той же сборке; targeted unit 170 PASS, strict lint 16 files / 0 violations; WebExtensions generic iOS Simulator module BUILD SUCCEEDED. Все 4 disabled-flag controls функционально FAIL без teardown errors. Коммитов и изменений scratch/ZIP/schema/dependencies нет.

Локальные [CPM Background] logs показывают медленный WK callback (>=1 s) и release gate по deadline. Они подтвердили предел: fixture 5000 ms даёт фактическую готовность после 5 s cap и может потерять первый upgrade document (6/10 ранее). Этот over-budget режим не исправлен и сохраняется через CPM_APP_INTEGRATION_INSTALL_DELAY_MS=5000; здоровые contract regression cases проверяют 4500 ms. Это не доказательство всех natural production causes и не реальный iOS suspension/resume run. Артефакты и история: /private/tmp/cpm-p1-p2-replacement-20261016/validation-summary.json, cpm-status-2026-10-15.

Дополнение: 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 не выполнялся. Для traceability использована существующая задача самого P1/P2 fix.

Регрессии: обновлён 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.