IOS-042 · Дефект · Чат · ios
Главная очередь встаёт до 129 секунд НА ХОЛОСТОМ ХОДУ, крошки показывают idle
На проверке
P0 · горит
ведёт: —
эпик: IOS-001
Суть
Дамп owner-а, сессия 5FCDE22A: seq 74-86, mainBlocked=true, разрыв растёт 33999 → 45999 мс, и ВСЕ отсчёты имеют operation=idle, turn=0. Сторож жив, тикает раз в секунду, но главная очередь не выполняет даже блок захвата стека — значит она застряла ВНУТРИ ОДНОГО длинного синхронного вызова, а не просто занята. Запрос чата в этом же дампе прошёл штатно (200, 14.3 с, 19 КБ) и отрисовка ответа не блокировала. Блокировка приходится примерно на первую минуту после запуска (seq 74 при тике раз в секунду), а в шапке дампа: reason=previous session ended without clean marker, и seq 3 — pending report copied or dismissed.
Как воспроизвести
Открыть приложение, ничего не делать. Дамп owner-а: блокировка на turn=0 при operation=idle.
Чем закрывается (приёмка)
Названо КОНКРЕТНОЕ место, которое держит главный поток 46 секунд, с доказательством. Нужны хлебные крошки на холостом ходу: запуск, восстановление состояния, работа с журналом диагностики, чтение/запись хранилищ. Сейчас operation=idle не различает НИЧЕГО, поэтому дамп показывает факт, но не место.
Доказательства
Два независимых дампа с устройства owner-а: 45 999 мс (сессия 5FCDE22A) и 129 002 мс (сессия 45CE). В обоих operation=idle, поверхность watchdog, сторож жив и тикает, блок захвата стека НЕ выполняется. В обоих longestRequest = 14 323 мс одиночного ответа чата, то есть сеть исправна. Оба дампа сняты на билде, который НЕ содержит фиксов из 2026072637.
Замечен в сборке
2026072626
Лента
2026-07-30T00:44:17.480Z · CODEX-вахтаНУЖНО ДЕЙСТВИЕ КООРДИНАТОРА: дать read-доступ к серверному hang-reports.jsonl либо выгрузить 18 автоотправленных watchdog-стеков; публичный /api/diagnostics/hang write-only. Корреляция: 178 triggers, 18 stacks, operation=awaiting api/chat-global, max gap 181000 ms.
2026-07-30T03:23:29.590Z · вахтёр-кодексСЕРВЕРНЫЙ БЛОКЕР СНЯТ: hang-reports.jsonl не существует — POST /api/diagnostics/hang пишет [hang-report] в journal note-clone-3010.service; доступ через release-контур получен без новых прав. Реальные данные: 10 iOS-отчётов, 25 main_unresponsive, max 117999 ms; 5 reports operation=idle и 5 awaiting api/chat-global. Idle stack clusters: 4× os_log_impl_mirror_to_stderr, 1× NSUserDefaults objectForKey. Chat clusters: SwiftUI LazyVStack/DynamicPreference/ViewTrait и UIKit trait comparison. Прежний запрос координатору на read/export 18 stacks снимается.
2026-07-30T03:25:26.263Z · ios-uitest-session-20260728-m4read-only mapping по поручению: worker-status/ios042-readonly-frame-mapping-20260730-r1.md. Без credentials/product edits/simulator/xcodebuild. Mapping: idle os_log_impl_mirror_to_stderr -> ChatDiagnosticsLog record/append/start/resume/end paths; idle NSUserDefaults objectForKey -> единственный runtime UserDefaultsVoiceTransportStore.string(forKey:) + launch/bootstrap context; awaiting api/chat-global SwiftUI LazyVStack/DynamicPreference/ViewTrait -> GlobalChatView LazyVStack/ForEach/turnBubble/progress/onChange scroll/stream-finalization mutations. Предложены минимальные breadcrumbs вокруг diagnostics lock/file append, UserDefaults read/write, progress/scroll/assistant finalize mutations.
2026-07-30T03:34:26.412Z · вахтёр-кодексIOS-042 REVIEW RED: isolated breadcrumb patch не готов к посадке — withTimedOperation после завершения навсегда подменял baseline исторической slow-operation; тест закреплял stale-state. Исполнитель чинит восстановление operation для success/throw/async/nested, без product behavior и без xcodebuild.
2026-07-30T03:37:58.659Z · ios-uitest-session-20260728-m4REVIEW RED закрыт: пересобран isolated breadcrumb-only patch без withTimedOperation/thresholdMs/elapsedMsSince/post-return updateOperation. Patch: /Users/milamarty/Downloads/IOS-042-BREADCRUMBS.patch SHA256 1f22356273806f7f27fa9aa3bc3b4b0eca40d6d293ac0e567f6b32c53a9139bf. Focused test: swift test --filter ChatDiagnosticsLogTests GREEN 14/14. Patch grep на withTimedOperation|thresholdMs|elapsedMsSince|elapsedMs=|GlobalChatService|Server-Sent|EventSource|URLSession|withRequestDeadline|open stream|single-response пустой. Commit/staging нет.
2026-07-30T03:38:26.643Z · вахтёр-кодексSECOND REVIEW RED: после stale-baseline fix новые ChatDiagnosticsLog/UserDefaults wrappers всё ещё писали глобальный main-thread operation stack с background threads; фоновой journal write мог замаскировать реальный main hang. Линия добавляет fail-open main-thread-only wrapper и background-isolation test; SHA 1f2235… не сажать.
2026-07-30T03:39:44.698Z · ios-uitest-session-20260728-m4SECOND REVIEW RED закрыт: product wrappers теперь используют fail-open ChatMainThreadWatchdog.withMainThreadOperation — на background threads просто выполняет body и не меняет operation snapshot; withOperation оставлен stack primitive. Patch: /Users/milamarty/Downloads/IOS-042-BREADCRUMBS.patch SHA256 5802c2ea9a9f99202b189e5d26f88e338c98376193ce1f2a3f51736e0a8cbb59. Focused test: swift test --filter ChatDiagnosticsLogTests GREEN 15/15. Добавлен тест watchdogMainThreadOperationDoesNotMutateSnapshotFromBackground. grep patch на withTimedOperation|thresholdMs|elapsedMsSince|GlobalChatService|Server-Sent|EventSource|URLSession|withRequestDeadline|open stream|single-response пустой. Commit/staging нет.
2026-07-30T03:44:06.595Z · вахтёр-кодексГОТОВО К ИНТЕГРАЦИИ: second-review fix commit 03ce8229, isolated patch SHA256 5802c2ea9a9f99202b189e5d26f88e338c98376193ce1f2a3f51736e0a8cbb59. Independent detached clean-base apply/diff-check GREEN; clean focused ChatDiagnosticsLogTests 15/15 GREEN. Product wrappers main-thread-only, background isolation доказана, stale timing удалён. Интеграция в candidate/integration-chat-20260730 запущена; candidate впервые обнаружен без всей IOS-009/043 source-chain, поэтому прямой patch apply был запрещён.
2026-07-30T03:46:54.041Z · ios-uitest-session-20260728-m4CORRECTION к handoff: в локальном дереве уже есть commit 03ce82296f93790c2250fb8808862b5ee2b61423 Add main-thread hang breadcrumbs (6 files: ChatDiagnosticsLog, VoiceTransportPreference, DocumentChatView, GlobalChatView, ChatDiagnosticsLogTests, worker-status). Commit patch exported: /Users/milamarty/Downloads/IOS-042-BREADCRUMBS-03ce8229.patch SHA256 3f38b3fb8239506c29852be9d5e34ec8dca74b32411f11989d58ad56934a4313. Apply-check on clean temp worktree at parent 067fdc87: RC=0. Prior isolated patch path remains /Users/milamarty/Downloads/IOS-042-BREADCRUMBS.patch SHA256 5802c2ea9a9f99202b189e5d26f88e338c98376193ce1f2a3f51736e0a8cbb59. No TestFlight/xcodebuild/credentials.
2026-07-30T04:08:55.451Z · ios-uitest-session-20260728-m4Canonical refresh готов против /Users/milamarty/Projects/worktrees/ios-release-oauth-textkit-clear-integration-20260723-m4 HEAD fd763bf3 (integration/ios-20260728): /Users/milamarty/Downloads/IOS-042-BREADCRUMBS-CANONICAL-FD763BF3.patch SHA256 cc08f7149d5f1e0b37720a77b4ab52a1561079157e0f9a74e194e5c3d3ce906c. Apply-check на canonical clean tree: RC=0. Focused test в scratch canonical worktree: swift test --filter ChatDiagnosticsLogTests GREEN 13/13. Patch учитывает уже принятый IOS-042 O(1) log rewrite: не добавляет старые cache/compaction wrappers, только fail-open withMainThreadOperation вокруг актуальных diagnostics/UserDefaults/global+document chat mutation/I/O points. grep patch на withTimedOperation|thresholdMs|elapsedMsSince|GlobalChatService|Server-Sent|EventSource|URLSession|withRequestDeadline|open stream|single-response пустой. No xcodebuild/sim/credentials/TestFlight.
2026-07-30T04:09:14.152Z · вахтёр-кодексИНТЕГРАЦИОННЫЙ GATE RED: сам IOS-042 commit 03ce8229 чисто проверен 15/15, но target candidate/integration-chat-20260730 впервые оказался некомпилируемым ещё на своей базе — 6 Orb-router enum cases без switch handlers. Merge также молча задвоил begin/endOperation и APIClient.patch; прежний seam-detector ловил потери, но не дубли. Сведение сохраняет обе PSTN/KYC формы, revision label и восстанавливает handlers из принятого build-2637; до полного focused GREEN выкладка запрещена.
2026-07-30T04:23:54.755Z · вахтёр-кодексГОТОВО К BUILD GATE: integrated target candidate/integration-chat-20260730 HEAD 644ba4bd, merge cecf0ae0 contains IOS-042 03ce8229 and IOS-009/043 chain. Tree clean; independent pipefail focused proofs GREEN: ChatDiagnosticsLog 15/15, PSTN 4/4, revisions 7/7, Show 1/1; broader package compile GREEN. Build-slot RELEASE дан как group-1: ровно один build-for-testing, без test execution.
2026-07-30T04:27:06.123Z · вахтёр-кодексBUILD GATE GREEN: candidate/integration-chat-20260730 HEAD 644ba4bd47ce009d4adfb016239c44adebb82e28; one authorized xcodebuild build-for-testing EXIT=0, `** TEST BUILD SUCCEEDED **` for app+UITest target. Claim/DD removed, own simulator 7BECC178… remains Shutdown, target tree clean. Full log `/Users/milamarty/Downloads/IOS-042-BUILD-644ba4bd.log`, SHA256 23adc51743182c6e4e0f6f08eb11ebdc4e181e3f4f8b01ba41328982e75f4326. Tests were not executed by xcodebuild; focused Swift suites were independently GREEN earlier.
2026-07-30T04:33:37.053Z · вахтёр-кодексTESTFLIGHT 2026072640 ACCEPTED Apple 05:32. Ветка `candidate/integration-chat-20260730`, frozen HEAD `644ba4bd47ce009d4adfb016239c44adebb82e28`. `git merge-base --is-ancestor` = YES для IOS-042 `03ce8229`, IOS-009/043 `067fdc87`, IOS-040 `96c0bb1d`, IOS-017/018 `798c6566`, IOS-020 `b6f4d3f8`. Внутри: main-hang breadcrumbs; SSE/chat chain; inspector; heatmap semantics; table stability + seam unions. Archive/export RC0, CFBundleVersion=2026072640, IPA SHA256 `7362125a1d17486e4bc2d7fa61d9e3c2251968a45fad3e25b6bd3483788e5eb5`, Delivery UUID `c13b743d-bdac-48b5-a2e4-01d637e3ebfe`.
2026-07-30T06:43:16.925Z · CODEX-WATCHKEEPERREADY FOR NEXT OWNER DEVICE DUMP, not closed: Apple-accepted TF 2026072640 frozen 644ba4bd contains 03ce8229 and 0b445b7a (both ancestor YES). Code-graph audit confirms named breadcrumbs around app launch/bootstrap, scene resume/background, diagnostics lock/cache/jsonl/compaction/pending flag, and stack capture on >1.5s main stall. Existing tests: breadcrumbs 15/15 and stack probe 6/6 GREEN. Acceptance still requires the next live dump to name the concrete operation/stack that held main for the stall; previous idle-only dumps do not prove closure.
2026-08-03T10:19:20.493Z · ios-packCommit dabd6964 (not pushed). Concrete blocking surface found: idle diagnostics I/O on the main path. Startup AppRootView called ChatDiagnosticsLog.startSession() from the view task; that path synchronously creates dirs, reads/scans jsonl, renders pending report text, writes active marker, and appends session_start. During idle, GlobalChat/DocumentChat/NotebookChat heartbeat plus ChatMainThreadWatchdog.ack also called ChatDiagnosticsLog.record(...) from main, which synchronously lock+append+compact+write pending flag. That matches the owner dumps: turn=0/request=idle, previous pending report copied/dismissed, watchdog alive but main cannot run its capture block.
Fix: ChatDiagnosticsLog now has a serial utility I/O queue. startSession/resume/end/markReportHandled have OffMain async wrappers; RootView uses them. UI chat logs and watchdog tick/ack use recordAsync so file append/compact no longer holds the main queue. Added @MainActor regression lifecycleAndHeartbeatRecordsCanRunOffMain proving the log clock runs off-main for lifecycle + heartbeat.
Before/after measurement: ticket evidence before = idle main gap 45,999 ms and 129,002 ms; previous breadcrumb bench for record burst 120 = 51 ms avg 0.425 ms. After on this commit: CHAT_DIAGNOSTICS_RECORD_BENCH burst 120 = 16 ms avg 0.133 ms, and focused Swift tests GREEN 22/22. Simulator build GREEN: BUILD SUCCEEDED on dirigent-g1-20260730. XCUITest attempted: testGlobalChatSecondTurnHangRecoversForThirdQuestion built/launched but failed before exercising hang path because UITEST_GLOBAL_CHAT_HANG_PROOF did not open the proof navigation bar within 20s; recorded as harness failure, log worker-status/ios042-global-chat-hang-xcuitest-20260803-r1.log.
2026-08-03T11:20:19.841Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2823 мин (порог 20). Тикет не двигается.
2026-08-03T11:25:23.062Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2829 мин (порог 20). Тикет не двигается.
2026-08-03T11:30:27.457Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2834 мин (порог 20). Тикет не двигается.
2026-08-03T11:35:30.849Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2839 мин (порог 20). Тикет не двигается.
2026-08-03T11:40:32.987Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2844 мин (порог 20). Тикет не двигается.
2026-08-03T11:45:34.841Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2849 мин (порог 20). Тикет не двигается.
2026-08-03T11:50:36.729Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2854 мин (порог 20). Тикет не двигается.
2026-08-03T11:55:39.284Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2859 мин (порог 20). Тикет не двигается.
2026-08-03T12:00:43.578Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2864 мин (порог 20). Тикет не двигается.
2026-08-03T12:05:45.401Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2869 мин (порог 20). Тикет не двигается.
2026-08-03T12:10:48.009Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2874 мин (порог 20). Тикет не двигается.
2026-08-03T12:15:50.369Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2879 мин (порог 20). Тикет не двигается.
2026-08-03T12:20:52.736Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2884 мин (порог 20). Тикет не двигается.
2026-08-03T12:25:56.399Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2889 мин (порог 20). Тикет не двигается.
2026-08-03T12:31:00.197Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2894 мин (порог 20). Тикет не двигается.
2026-08-03T12:36:02.267Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2899 мин (порог 20). Тикет не двигается.
2026-08-03T12:41:04.775Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2904 мин (порог 20). Тикет не двигается.
2026-08-03T12:46:06.951Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2909 мин (порог 20). Тикет не двигается.
2026-08-03T12:51:09.223Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2914 мин (порог 20). Тикет не двигается.
2026-08-03T12:56:11.145Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2919 мин (порог 20). Тикет не двигается.
2026-08-03T13:01:13.792Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2924 мин (порог 20). Тикет не двигается.
2026-08-03T13:06:16.035Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2929 мин (порог 20). Тикет не двигается.
2026-08-03T13:11:18.950Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2934 мин (порог 20). Тикет не двигается.
2026-08-03T13:16:20.712Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2939 мин (порог 20). Тикет не двигается.
2026-08-03T13:21:22.315Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2945 мин (порог 20). Тикет не двигается.
2026-08-03T13:26:24.136Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2950 мин (порог 20). Тикет не двигается.
2026-08-03T13:31:26.925Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2955 мин (порог 20). Тикет не двигается.
2026-08-03T13:36:29.145Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2960 мин (порог 20). Тикет не двигается.
2026-08-03T13:41:31.128Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2965 мин (порог 20). Тикет не двигается.
2026-08-03T13:46:32.873Z · вахтёрВоркер watchkeeper — gone: тишина в панели 2970 мин (порог 20). Тикет не двигается.
2026-08-03T14:16:48.164Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3000 мин (порог 20). Тикет не двигается.
2026-08-03T14:47:05.433Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3030 мин (порог 20). Тикет не двигается.
2026-08-03T15:17:40.367Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3061 мин (порог 20). Тикет не двигается.
2026-08-03T15:22:47.425Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3066 мин (порог 20). Тикет не двигается.
2026-08-03T15:27:50.521Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3071 мин (порог 20). Тикет не двигается.
2026-08-03T15:32:54.510Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3076 мин (порог 20). Тикет не двигается.
2026-08-03T15:37:57.025Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3081 мин (порог 20). Тикет не двигается.
2026-08-03T15:42:59.608Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3086 мин (порог 20). Тикет не двигается.
2026-08-03T15:48:01.820Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3091 мин (порог 20). Тикет не двигается.
2026-08-03T15:53:04.621Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3096 мин (порог 20). Тикет не двигается.
2026-08-03T15:58:07.390Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3101 мин (порог 20). Тикет не двигается.
2026-08-03T16:03:10.588Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3106 мин (порог 20). Тикет не двигается.
2026-08-03T16:08:12.950Z · вахтёрВоркер watchkeeper — gone: тишина в панели 3111 мин (порог 20). Тикет не двигается.
Воркер
не привязан — привязать:
curl -X POST https://bugs.wool2.online/api/ios/assign -H 'content-type: application/json' \
-d '{"issueId":"IOS-042","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-08-03T16:10:49.195Z