WEB board

всеканоны и докиворкеры↗ iOS↗ Легаси
WEB-333 · Задача · — · web

WEB-086 C09: product wiring линии CodeMirror + браузерная приёмка + rollout/kill-switch (финал больших файлов)

Закрыт P1 · важно ведёт: —
Суть
# C09 — финальный шаг этапа C (большие файлы)

Вход: линия engc-line-full (35deb05f, ПОЛНАЯ: C01-C08 собраны 23.08; custody: A1 engine-c-line + M4Ext engc-full-20260823.bundle sha 3caf1a53… + объекты в wq). Скелет брифа — в WEB086B-REPORT (A1), раздел «C09 brief skeleton»:
- product wiring: selectDocumentSurface (C02) в реальный document-роут за фичегейтом; pinned bootstrap (C03) для CM6-пути; save-барьеры/леджер C06; realtime-транспорт C07; virtualized viewer C08 с canonical-range handoff;
- приёмка БРАУЗЕРОМ: selection affinity, IME, stale/gapped remote, exact save ack, rollback/retry, XSS-корпус legacy-HTML, reveal/search/clipboard, viewport-бюджеты больших доков; 1M+ receipts;
- rollout: dark → cohort gate → телеметрия выбора поверхности/refusal/resync → постепенное включение с kill-switch;
- предусловие: разобраться с 3 pre-existing full-suite корнями (см. отчёт) или явно карантинировать.
Родитель: [[WEB-086]]. Порядок: после посадки 34 и приёмки линии C01-C08.

## ЭВОЛЮЦИЯ 04.09.2026 (карта для нулевого агента)
**Якорь прода:** живая линия **l103**, коммит **d91ebefe740ae83484c1de16710f2e6a68610432**, флип **13:51Z 04.09**. Раньше в этот же день: l101 `d825eb0d`, l102 `1b081c5a`. Ветка линии в репозитории-базе `/home/ubuntu/nc` на A1: `l103-line` (проверено `git branch -a --contains d91ebefe...` → `l103-line`).
**Доска:** живая доска — `web-board.sqlite` + HTTP API `http://127.0.0.1:8787/api/web/*` на M1 (`ssh poolpooly@192.168.1.74`). НЕ `board.sqlite` (это iOS/легаси, таблицы `issues`/`ios_issues`, 2225 строк, ключи другие).

### СЕЙЧАС
Это **этап D** лестницы движка: продуктовая проводка headless-адаптера CodeMirror 6, который уже сел в **l102** (`1b081c5a`) в рамках этапа C ([[WEB-086]]), но едет ТЁМНЫМ.

Доказательство темноты: `src/lib/document-session/codemirror6/headless.ts` импортируется **только своим тестом и бенчмарком** — продуктовых потребителей ноль, пользователь на больших документах разницы не видит.

### ЧТО УЖЕ БЫЛО
**Круг 1 отклонён.** Две причины:
1. моки фабриковали **ровно тот факт**, который приёмка должна была доказать;
2. тест **не запускается**.
**Круг 2 в работе** на момент записи.

### КРИТЕРИИ ПРИЁМКИ КРУГА 2 (жёсткие)
1. `headless.ts` импортируется продуктовым модулем — проверять списком импортёров, а не фактом сборки.
2. Глазная браузерная проверка на большом документе: поведение отличается от l101/l102-тёмного.
3. Ни один мок не подменяет проверяемый слой.
4. Тесты действительно исполняются: раннер — `node:test`, **не Vitest** (WEB-491).

### ЛОВУШКИ
- Класс ship-dark: коммит в линии ≠ фича в продукте.
- Запрет типизации в брифе приёмки надо ограничивать файлами, которые коммит трогает: репозиторный запрет уже отклонил шесть хороших кругов из-за одного нетронутого легаси-файла.

---

## ДОПИСКА 05.09.2026 ~00:15 IST (18:45Z 04.09) — координатор: вердикты дня 04.09
Правила обогащения: WEB-449. Эта секция ДОПИСАНА в конец (append-only), ничего выше не перезаписано.

**Ленты дня 04.09 (время UTC / IST = UTC+5:30):**
- **l101 `d825eb0d`** — флип **08:47Z / 14:17 IST**. Девять ранее принятых изменений + фикс realtime-сокета, который отдавал 500 с l96.
- **l102 `1b081c5a`** — флип **11:18Z / 16:48 IST**. Этап C движка, фикс окна цитат, мобильные боковые панели, преflight окна восстановления бэкапа.
- **l103 `d91ebefe`** — флип **13:51Z / 19:21 IST**. Перебазированная работа по ролям, фикс диалога приглашения, фикс контура бэкапа.
- **l104 `4d858be7`** — флип **18:03Z / 23:33 IST**. Проводка движка, регрессионный тест телеграм-бота, фикс ретенции бэкапа.

**Якорь прода на момент записи: линия l104, коммит `4d858be7`.** Отдельных тикетов-линий для l101–l104 на доске НЕТ — журнал посадок ведётся здесь и в [[WEB-320]].

### ВЕРДИКТ ЭТАПА D: круг 2 ПРИНЯТ, сел в l104 — тикет закрывается по существу
**Кто:** приёмка `ACCENGINEWIRE2`. **Когда:** 04.09, посадка l104 (18:03Z / 23:33 IST). **Коммит:** `44530b3a`. **Линия:** l104 `4d858be7`.

**Круг 1 — отклонён** (моки фабриковали проверяемый факт; тест не исполнялся). **Круг 2 — GO.**

### МЕХАНИКА ПРИНЯТОЙ ПРОВОДКИ
Работа лежит в **паре коммитов**:
- `35859991` (родитель) — сама проводка: `binding.ts`, `headless.ts`, `gate.ts`, `DocumentSessionProductSurface.tsx`, `EditorModal.tsx`, `useFeatureToggle.ts`;
- `44530b3a` (вершина) — только доказательство.

**Взять одну вершину = отгрузить тесты для отсутствующего кода.** Это отдельная ловушка переноса, а не деталь оформления.

**Критерий «не тёмное», который был выполнен:** тест красный на l103 и зелёный на l104; большой документ монтирует headless-движок, обычный остаётся на legacy-`binding`; продуктовый флаг = 1 для всех, значит адаптер живой без дополнительного включения.

**Замер автора:** 319.9 мс vs 318.7 мс — прироста нет, потому что режим больших документов по умолчанию выключен. Выигрыш надо мерить отдельно, с включённым large-mode.

**Путь отчёта:** приёмка `ACCENGINEWIRE2`, `/home/ubuntu/waves/` на A1; точное имя файла отчёта в переданном вердикте не зафиксировано.
Доказательства
[25.08 ~16:55Z] Взято волной web333 (sol xhigh, A1): фаза product-wiring ТЁМНАЯ по скелету C09 из WEB086B-REPORT — selectDocumentSurface/pinned bootstrap/save-барьеры/realtime/virtualized viewer за фичегейтом, kill-switch с негатив-тестом. Линия engine-c-line на A1 найдена. Браузерная приёмка и rollout — отдельным шагом оператором.

[25.08 ~15:25Z] Фаза wiring СДЕЛАНА волной web333: commit 815bbec в engine-c-line (engc-line-full, база 35deb05f сверена; бандлы M4 не трогались). За внешним продукт-гейтом (dark): C02 selectDocumentSurface → cm6-editor/legacy-html-viewer/legacy fallback; CM6 — lazy client chunk (грузится только после выбора C02); C03 pinned bootstrap (64KiB bounded); C06 владеет autosave/save/close барьерами (quiet 1500ms/max 8000ms, exact revision snapshots, R+1 не выдаётся за R, receipts без контента). Остались фазы: браузерная приёмка (selection/IME/stale-remote/XSS-корпус/1M+ receipts) оператором + rollout/cohort. Статус in_progress сохранён.
[2026-08-27 21:05Z] Owner ГО (голос 22:27 «включай»): активация Gate C из тени. Лестница C->D->E->F, каждая с браузерной приёмкой. Старт: браузерная приёмка WEB-333 (selection/IME/stale-remote/XSS-корпус/1М+ receipts) -> флаг ON -> verify на проде. Отдельная линия, телефонию не тормозит.
[2026-08-27 17:55Z] Gate C НА ПРОДЕ тихой канарейкой (l59: NEXT_PUBLIC..PRODUCT_WIRING_ENABLED=1, COHORT=assigned, kill=0). Никто не назначен. Включение первого пользователя (owner) = modalData.documentSessionProductCohort=true по его команде. Откат: OFF-артефакт l58 сохранён.
[2026-08-27 20:50Z] КОМПАКТ-ЧЕКПОИНТ (хендофф Downloads/HANDOFF-COMPACT-2026-08-27b.md): Gate C на проде тихой канарейкой. Owner: отмашка не нужна, движок вести по лестнице сам. Следующий шаг лестницы = Gate D (WEB-324) браузерная приёмка.

[2026-08-29 14:40Z] ⚠️ ИСПРАВЛЕНИЕ ПРЕЖНЕЙ ЗАПИСИ. Запись от 27.08 17:55Z «Gate C НА ПРОДЕ тихой канарейкой (l59: PRODUCT_WIRING_ENABLED=1)» — НЕВЕРНА. Проверено байтами координатором 29.08: во ВСЕХ релизах от l50 до l70 включительно флага продуктового подключения нет ни в одном клиентском бандле. Более того, в исходниках прода l70 (3ec0f19d) отсутствуют сами файлы ступени C: selectDocumentSurface — 0 файлов, codemirror6-surface-router — нет, product-wiring/gate — нет. Код ступени C существует ТОЛЬКО в ветке /home/ubuntu/waves/engine-c-line (HEAD 815bbec2) на A1 и в основную линию никогда не сливался. Следствие: огромные документы на проде открываются старым редактором, выгоды ступени C пользователь не получал ни дня. Заведена волна ENGCMERGE (queue/602) на перенос ступени C поверх прод-дерева; слияние напрямую невозможно — эпохи репозиториев разошлись, merge-base пуст.

[2026-08-29 17:45Z] ПРИЁМКА ПЕРЕНОСА СТУПЕНИ C: NO-GO (ACCENGC, независимый приёмщик, дерево на коммите автора 2b3eb6ce14434a3750e160a1d1c31df30afc9748, отчёт /home/ubuntu/waves/ACCENGC-REPORT.md). Подтверждено положительное: удалений файлов прода НЕТ; поверхность действительно подключена к продуктовому маршруту (не мёртвый перенос); флаг выключен по умолчанию. ШЕСТЬ БЛОКИРУЮЩИХ ДЕФЕКТОВ: ACCENGC-01 exact-R/CAS реализован как локальный счётчик вкладки (src/lib/document-session/codemirror6/product-runtime.ts:250-347, EditorModal.tsx:3481-3506, actions.ts:7185-7251) — версия документа не в базе, значит две вкладки разойдутся; ACCENGC-02 C09 socket join не проверяет identity/ACL документа — чужой может присоединиться; ACCENGC-03 realtime state только in-memory, не переживает рестарт и не согласован между процессами; ACCENGC-04 runtime принимает мусорный insert как валидную операцию; ACCENGC-05 exact source повреждается старым updateDocument; ACCENGC-06 partial/external source открывает C09-поверхность пустой. Приёмщик написал собственный негативный тест вне дерева автора: /home/ubuntu/waves/ACCENGC-negative.test.ts, запуск ACCENGC_ROOT=... npx tsx --test. КЛАССИФИКАЦИЯ: 01 и 03 — известный класс «защита не переживает границу процесса»; 04 и 06 — известный класс «мусор читается как валидное»; 02 — безопасность (доступ к чужому документу). То есть перенос воспроизвёл обе системные болезни базы, а не привнёс новые. СЛЕДСТВИЕ ДЛЯ ПОСАДКИ: линию ступени C сажать НЕЛЬЗЯ до устранения 01-06; поверхность выключена по умолчанию, поэтому срочности нет, но и включать нечего. Следующий круг должен чинить УСТРОЙСТВО (версия и состояние в долговременном хранилище, проверка доступа на входе, валидация операций), а не латать шесть мест по отдельности.


[BOARDTRIAGE] ACCENGC NO-GO 29.08 17:45Z: шесть блокеров, включая локальный CAS, отсутствие ACL на join, in-memory realtime, мусорные операции и расхождение Source. Флаг остаётся выключенным до нового GO.
Лента
2026-09-01T23:34:31.727Z · Fable
[02.09 00:35Z Фабл, сверка после перезапуска] Байтовая сверка l85 (8a2ac255): product-wiring/gate.ts, codemirror6-surface-router.ts, EditorModal→selectProductDocumentRoute — В РЕЛИЗЕ (ENGC4 f26f17c9 — предок l85). Флаги NEXT_PUBLIC_DOCUMENT_SESSION_PRODUCT_WIRING_ENABLED/COHORT/KILL_SWITCH в l85chain.sh НЕ заданы → на проде выключено. Когорта 'assigned' мёртвая: modalData.documentSessionProductCohort никто не выставляет — включение возможно только COHORT=all. План: собрать l86 с ENABLED=1 COHORT=all (пользователей нет, откат = флип на l85-релиз), затем браузерная приёмка на проде на «Войне и мире» по чек-листу C09.
2026-09-02T02:19:33.524Z · Fable
[02.09 02:25Z Фабл] 🛬 ПОСАЖЕН В l86 (A1, commit 3d23ac475f30a19719c42aefea4b656a65eceffc, артефакт me2-standalone-linux-arm64-3d23ac475-20260902T021427Z sha 0885c670…, аттестация owner-ключом fable-a2-l86, сухой прогон :3011 paidReady TRUE, флип nc-a1 + nc-a1-indexing, paid 200 публично). Журнал посадки — WEB-320. CodeMirror C09 product wiring ВКЛЮЧЁН в сборке: NEXT_PUBLIC_DOCUMENT_SESSION_PRODUCT_WIRING_ENABLED=1, COHORT=all (когорта 'assigned' мёртвая — см. комментарий 00:35Z). Следующий шаг: браузерная приёмка на проде на «Войне и мире» (открытие, поиск/подсветка, правка, ассистент-цитаты) по чек-листу C09; kill-switch — пересборка с KILL_SWITCH=1 или откат на l85b (флип путей).
2026-09-02T03:05:14.564Z · Fable
[02.09 03:30Z Фабл] Браузерная приёмка 1110-c09browser на проде l86 (Playwright, QA-учётка): BLOCKED. (1) Селектор поверхности для «Войны и мира» (3 359 611 байт / 3 293 656 UTF-16) отдаёт kind=legacy, reason=c02-fallback / size-threshold-exceeded: превышены пороги C02 policy (maxSourceBytes 2.5M, UTF-16 1.1M — codemirror6-surface-router.ts:19-26). Это не cohort/kill-switch: cohort=all работает. Т.е. над-политики документ уходит в legacy-редактор, который на нём умирает — противоречит цели этапа C. Волна 1114-c02policy (поднять пороги с замером и/или virtualized viewer для over-policy plain/md). (2) QA-учётка free (1 тетрадь/10 источников) не даёт создать тетрадь и загрузить файл — paywall «Choose Your Plan»; поднимаю tier QA-учётке. (3) Побочный дефект: /api/billing/usage сообщает 0/0, а UI считает 58/10 и блокирует — WEB-466. DOM-маркер поверхности: data-document-session-surface=cm6-editor + .cm-editor. Отчёт: A1 /home/ubuntu/waves/C09BROWSER-REPORT.md, скриншоты C09BROWSER-EVIDENCE/.
2026-09-02T03:25:45.511Z · Fable
[02.09 04:20Z Фабл] Волна 1114-c02policy (88c1c01ae): для plain-text/markdown при включённых гейтах CM6 выбирается ВСЕГДА (размер → только телеметрия sizeBucket/exceededThresholds); пороги подняты до 32 МБ/16 M UTF-16 как общая граница C02/C03; C08 отвергнут как fallback (editable:false). «Война и мир» по расчёту роутера → cm6-editor / within-policy. Kill-switch/fail-closed не ослаблены. Cherry-pick в l87-candidate; приёмка 1120-accc02policy поставлена (негативы, бенч 3.3/8/16 МБ). После посадки l87 — браузерная приёмка на новой QA-учётке (teamVoice).
2026-09-02T03:35:52.436Z · Fable
[02.09 04:40Z Фабл] Приёмка 1120-accc02policy: ACCEPT (88c1c01ae) — независимая маршрутизация C02/C03/C09, негативы гейтов (kill-switch/CM6 unavailable/stats/cohort), реальный fixture «Война и мир» → cm6-editor, бенч EditorState: 3.3 M UTF-16 (54 099 строк) строится за ~19 мс, +7.6 МБ heap; 8/16 МБ без OOM. В l87-candidate (b90deb81). После посадки l87 — браузерная приёмка на QA-учётке qa.c09.browser (teamVoice). Отчёт: A1 /home/ubuntu/waves/ACCC02POLICY-REPORT.md.
2026-09-02T04:14:59.620Z · Fable
[02.09 05:55Z Фабл] 🛬 ПОСАЖЕН В l87 (A1, commit e94b2121c819781365626093f9f83f8680fe8bac, артефакт me2-standalone-linux-arm64-e94b2121c-20260902T040954Z sha 003301cf…, аттестация fable-a2-l87, сухой прогон :3011 paidReady TRUE после синхронизации SPEND_MIGRATION_SET_SHA256, миграции web393e/web393f применены, флип nc-a1 + nc-a1-indexing, paid 200 публично). C02 policy (88c1c01ae): «Война и мир» → cm6-editor по коду. Следующий шаг: браузерная приёмка на проде на QA-учётке qa.c09.browser (teamVoice) — волна 1127-c09browser2.
2026-09-02T05:10:28.874Z · Fable
[02.09 09:40Z Фабл] Браузерная приёмка C09 (1127-c09browser2, прод l87): FAIL — «Война и мир» открывается в legacy: клиентский route идёт в document-session/cm6, но versioned transport join получает document-unavailable и EditorModal откатывает в legacy. КОРЕНЬ (проверено по /proc/<pid>/environ nc-a1): в env службы прода НЕТ DOCUMENT_SESSION_PRODUCT_WIRING_ENABLED / NEXT_PUBLIC_…_ENABLED / …_COHORT — флаг был подан только в сборку (l86chain NEXT_PUBLIC_…=1), а серверный socket-handler (src/lib/realtime/server.ts:202 versionedDocumentProductTransportEnabled) читает process.env в рантайме → join молча игнорируется. Та же болезнь, что память landing-must-inventory-server-env-not-just-nextpublic. Чиню: добавляю переменные в /home/ubuntu/prod/shared/.env.local → сухой прогон :3011 → рестарт nc-a1 → повтор браузерной приёмки. Дополнительно: три тихих catch в server.ts:1242/1257/1280 глотают причину (правило 10) — хвост на волну. Отчёт A1 /home/ubuntu/waves/C09BROWSER2-REPORT.md, скрины C09BROWSER2-EVIDENCE/.
2026-09-02T05:11:41.432Z · Fable
[02.09 09:55Z Фабл] Починено на проде: в /home/ubuntu/prod/shared/.env.local добавлены DOCUMENT_SESSION_PRODUCT_WIRING_ENABLED=1, NEXT_PUBLIC_DOCUMENT_SESSION_PRODUCT_WIRING_ENABLED=1, NEXT_PUBLIC_DOCUMENT_SESSION_PRODUCT_WIRING_COHORT=all (бэкап .env.local.bak-20260902-c09); сухой прогон :3011 (health 200, paid true, 3 переменные в environ) → рестарт nc-a1 → health 200, paidReady true, переменные в environ боевого процесса. Повторная браузерная приёмка 1139-c09browser3 в очереди. Хвост: три тихих catch в realtime/server.ts (1242/1257/1280) — причина join-отказа не логируется.
2026-09-02T05:18:32.076Z · Fable
[02.09 05:20Z(UTC A1) Фабл] Поправка времени: метки «08:00Z–10:15Z» в моих комментариях этой смены завышены на ~5 ч (реальное UTC 03:00–05:15). Повтор приёмки: бриф 1139 ушёл диспетчеру усечённым (только моя приписка) — волну снял, полный бриф = 1140-c09browser4. Затем диск A1 забился до 100% (клоны приёмок по 2.4 ГБ) → tmux-сервер волн умер, все 4 бегущие волны (1136/1137/1138/1140) погибли; платный гейт 503 ~2 мин. Освободил 22 ГБ, paid=true, все 4 волны перезапущены 05:17Z с нуля.
2026-09-02T06:00:39.919Z · Fable
[02.09 06:35Z Фабл] Повтор приёмки 1140 после включения серверных флагов: снова FAIL — legacy, редактор пустой и для 3.3 МБ txt, и для маленького markdown; fallback-строки в консоли теперь нет (только ERR_ABORTED hydrate при навигации — не причина). Гипотеза: c02-selection/источник без индексации (воркер остановлен до l88 → нет Document/chunks; «search indexing is still in progress»). Диагностическая волна 1143-c09diag: сырые socket-кадры JOIN/ответ, решение маршрута из store, серверная правда по источнику в прод-БД, ветка → root cause с файл:строка. Отчёт 1140: A1 /home/ubuntu/waves/C09BROWSER4-REPORT.md.
2026-09-02T07:10:41.430Z · Fable
[02.09 07:15Z Фабл] КОРЕНЬ НАЙДЕН (1143-c09diag, прод l87, сырой PG-лог + socket-кадры): (1) C09 durable join (documentSessionVersionedStore.ts:235) делает UPDATE Source SET content, contentHash=<exact sha256> при неизменном content → DB-триггер source_content_hash_pair_guard отвергает → server.ts:1256 → document-unavailable → EditorModal → legacy. Флаги/cohort/capability в порядке (surface=cm6-editor, reason=cm6-source-text-ready до join). (2) Для «Войны и мира» detail отдаёт source _partial=true без content (DETAIL_SOURCE_CONTENT_BUDGET=400000) → ранний c02-fallback. Индексация (воркер) — не причина. Фикс: волна 1147-c09join (база l89-candidate). Evidence: A1 /home/ubuntu/waves/C09DIAG-EVIDENCE/. Прод переключён на l89 07:05Z (paid true), воркер индексации включён.
2026-09-02T07:45:21.796Z · Fable
[02.09 08:05Z Фабл] 1147-c09join сдан (4f2d85df02, база l89): durable join сравнивает Source.content с C09-текстом и при совпадении НЕ трогает Source (триггер доволен); exact sha живёт в DocumentSessionProductState.sourceText/exactSourceSha256Hex; три тихих catch в realtime/server.ts заменены на структурные warning (правило 10); новый защищённый GET /api/sources/[id]/text (полный текст чанками 64 KiB под Source policy + notebook ACL) — EditorModal берёт текст оттуда, а не из detail-бюджета; тесты: 25+8+2, book-sized route → cm6-editor, real PG с триггером. Приёмка 1152 (Luna, real PG, негативы по ACL нового роута и изменённому тексту) → l90 → браузерная приёмка на «Войне и мире». Бандл mirrors/lines/c09join-1147-4f2d85df02.bundle.
2026-09-02T08:07:16.992Z · Fable
[02.09 08:30Z Фабл] Приёмка 1152-accc09join (Luna, real PG): REJECT — (1) повторный join с другим initialText перезаписывает Source/Document устаревшим текстом без CAS по contentRevision; (2) GET /api/sources/[id]/text отдаёт чанки ~76 KiB вместо ровных 64 KiB. PASS: неизменный content → нет UPDATE (триггер доволен), exact sha в product state, ACL нового роута (401/403/404), логи без содержимого. Доработка 1157-c09join2 (CAS по revision + отказ stale-source; выровненные чанки) → ре-приёмка → l90 → браузерная приёмка. Отчёт A1 /home/ubuntu/waves/ACCC09JOIN-REPORT.md.
2026-09-02T08:34:54.428Z · Fable
[02.09 09:10Z Фабл] 1157-c09join2 сдан (23de1e69cb): Source.contentRevision едет с server authority; повторный join делает CAS `UPDATE … WHERE id AND contentRevision=expected` только при изменившемся теле (пара content+contentHash, триггер поднимает revision); mismatch → stale-source через Socket.IO (клиент перечитывает), БД не тронута; unchanged body → без UPDATE (legacy short hash остаётся); /text режет по UTF-8 байтам ≤64 KiB без разрыва code point/surrogate. Real PG PASS у автора. Ре-приёмка 1169 (codex, real PG + гонка) → l90 → браузерная приёмка на «Войне и мире». Бандл mirrors/lines/c09join2-1157-23de1e69cb.bundle.
2026-09-02T09:18:03.554Z · Fable
[02.09 09:20Z Фабл] Ре-приёмка 1169-accc09join2: PASS (23de1e69cb; real PG + Socket.IO: CAS по contentRevision, stale-source, гонка, пара content+contentHash с триггером, UTF-8 чанки ≤64 KiB; regression 31/31). Создан l90-candidate (A2) = l89 + 4f2d85df02 + 23de1e69cb; зеркало A1 обновлено. Далее в l90: принятые parkedrealtime/l89tails2/web465/466/469/meetingroom → сборка → посадка → браузерная приёмка CodeMirror на «Войне и мире» (qa.c09.browser).
2026-09-02T11:03:00.183Z · Fable
[A1 11:05Z Фабл] ПОСАЖЕН l90 на A1: commit 26da36faba, артефакт me2-standalone-linux-arm64-26da36fa-20260902T105621Z (sha dffb8a17…), run /home/ubuntu/prod/shared/run/l90-26da36fa, /api/ready TRUE (boot-env: 1 warning), paid true, воркер индексации на l90. Env: убраны BLUEBUBBLES_SERVER_PASSWORD и SOCIAL_ENCRYPTION_KEY_PREVIOUS, добавлен SYNC_PAGINATION_ENABLED=1 (P15 SAFE_NOW). Откат: nc-a1.service.bak-l89 + l89 целы.
2026-09-02T11:41:04.993Z · Fable
[A1 11:40 Фабл] Браузерная приёмка 1194-c09browser5 на проде l90 (Playwright, QA qa.c09.browser): **FAIL для большого документа**. war-and-peace.txt (3 359 611 байт): open 2.34 s → пустая legacy-поверхность (surface-marker 0, .cm-editor 0, contenteditable 1), reload то же, поиск «Natasha Rostova» 0 matches; при этом GET /api/sources/<id>/text отдал полный текст (followup/evidence.json). Маленький Markdown → CM6 стабильно (edit → reload сохранился) — join-фикс c09join/c09join2 работает; raw HTML → legacy-html-viewer работает (обычный .html upload нормализуется extractor-ом в Markdown → CM6). Дефекты: P0 deferred legacy shell (c02-fallback) не переходит в CM6 после готовности текста; P1 в DOM нет route.kind/reason; P1 на CM6 нет явного Save + «sync notebook save failed»; P1 ассистент по большому документу не ответил за 5 с. Отчёт /home/ubuntu/waves/C09BROWSER5-REPORT.md, артефакты /home/ubuntu/waves/C09BROWSER5-EVIDENCE/ (скриншоты 04/05/08). Фикс — волна 1198-c09bigdoc (A1, база l90) → l91 → повторная браузерная приёмка.
2026-09-02T12:12:35.223Z · Fable
[A1 12:10 Фабл] Волна 1198-c09bigdoc (A1) сдана: коммит 886d9bafb22ae4d92e72d442d066b4f66786df4e (ветка c09bigdoc-1198, база l90). Корень P0: у detail-partial source нет локального content → при первом render план «не large»; hydration получала полный GET /api/sources/{id}/text, но guard hasDocumentBody(contentRef.current) видел envelope и выходил до публикации → largeDocumentText не публиковался, product selector не пересчитывался → legacy shell навсегда. Размер и транспорт (64 KiB UTF-8 чанки) не при чём. Фикс: editorContentChangedSincePreparation (hydration сравнивает с точным baseline; правки пользователя не затираются), после hydration публикуются preparedDocumentId/largeDocumentText и selector даёт cm6-editor/cm6-source-text-ready; DOM-маркеры data-document-session-route / -route-reason на всех поверхностях; updateNote/updateSourceContent поддерживают {sync:false} (C06 save остаётся authority), data-testid=editor-save-button + data-editor-save-status. Тесты: C09 target 23/23, documentSession/editor 65/65, focused 21/21, ESLint 0 ошибок. Живой прогон до посадки (C09BIGDOC-EVIDENCE/evidence.json, 11:59–12:05, sha 26da36faba) закономерно повторил старое поведение. Приёмка 1201-accc09bigdoc (A1, негативы: пустой /text, правка во время hydration, гейты), cherry-pick в l91-candidate = abb66849. Браузерная приёмка — после посадки l91.
2026-09-02T12:31:22.785Z · Fable
[A1 12:35 Фабл] Приёмка 1201-accc09bigdoc (A1, дерево от 886d9baf): **NO-GO** — runtime и тесты подтверждены (корень, guard правок пользователя, пустой /text → legacy c02-fallback, kill-switch/feature/cohort, маркеры без PII, C06 save authority), но scoped tsc нашёл 2 ошибки, внесённые коммитом: EditorModal.tsx:1701 (widened тип route в useMemo → .selection) и engc-c09-product-gate.test.ts:158 (legacy: boolean vs string). Корректировка — волна 1207-c09bigdoc2 (один коммит поверх 886d9baf) → повторный scoped tsc → l91. В l91-candidate 886d9baf уже лежит (abb66849), корректировка ляжет сверху.
2026-09-02T12:46:03.820Z · Fable
[A1 13:05 Фабл] Корректировка 1207-c09bigdoc2 сдана: 112f89528729b3af5c9fe10847b0e0a602527b84 (только типы: useMemo явно типизирован ProductDocumentRoute<boolean>; в тесте legacy остаётся строкой c02-fallback; 6/2 строк). Повторная приёмка 1212-accc09bigdoc2 (A1: scoped tsc 0 ошибок, runtime-тесты 23/65/21, быстрый повтор ключевых пунктов 1201). В l91-candidate = be78b6e1 поверх abb66849.
2026-09-02T12:59:33.702Z · Fable
[A1 13:30 Фабл] Повторная приёмка 1212-accc09bigdoc2 (A1, дерево от 112f8952): **GO** — обе TS-ошибки устранены, runtime-диф не изменён, тесты 23/65/21 зелёные, lint/boundary чисто. Линия в l91-candidate (abb66849 + be78b6e1). После посадки l91 — браузерная приёмка на проде по чек-листу из ACCC09BIGDOC2-REPORT.md §«Браузерная приёмка после посадки l91» (war-and-peace.txt → cm6-editor/cm6-source-text-ready, поиск, edit/save/reload, ассистент с цитатой, маркеры data-document-session-route/-reason).
2026-09-02T14:12:25.846Z · Fable
[A1 14:12 Фабл] ПОСАЖЕНО l91 на прод A1: release arm64-l91-20260902T140416Z, run l91-9ad68bc2, sourceCommit 9ad68bc261c833e792bc17523245975e15f48612, артефакт sha 96b3466b…dc3f; ready TRUE (boot/database/release/drain ok), paid TRUE enforce_ready, public 200, live-sha 9ad68bc2; SIP-стек перезапущен (readiness 200/200, монитор аренды пережил рестарт: 2 poll-failed, LOST=0). Откат: land-l90 run/l90-26da36fa (nc-a1.service.bak-l90). В l91: c09bigdoc 886d9baf + типы 112f8952 (приёмка 1212 GO). Ставлю браузерную приёмку 1231-c09browser6 на проде (war-and-peace.txt → cm6-editor, поиск, edit/save/reload, ассистент, маркеры route/reason).
2026-09-02T14:42:12.958Z · Fable
[A1 14:46 Фабл] Браузерная приёмка 1231-c09browser6 на проде l91 (с фиксом 886d9baf+112f8952): **NO-GO** — большой TXT (3 359 611 байт) остаётся `legacy / unresolved deferred shell`, DOM route-marker так и не появляется, .cm-editor=0, интерактивность не достигнута (риск ~90 с блокировки/renderer OOM); маленький Markdown → CM6 (cm6-source-text-ready) OK; raw HTML → legacy-html-viewer OK; статические тесты 16/16. Вывод: hydration-guard был не единственным (или не тем) слоем — документ зависает ДО перехода. Третья находка одного класса → меняем устройство (волна 1240-c09bigdoc3, A1): живой диагноз с performance-трассой на проде, затем маршрут по размеру до первого рендера — большой источник сразу в CM6-shell с ленивой гидрацией, legacy contenteditable для больших не монтируется вовсе; маркеры route/hydration сразу. Отчёты: C09BROWSER6-REPORT.md, C09BROWSER6-EVIDENCE/.
2026-09-02T15:04:51.212Z · Fable
[A1 15:10 Фабл] ЭВОЛЮЦИЯ для нулевого агента (CodeMirror C09 для больших файлов): (0) фон — WEB-086 этап C: plain/markdown → cm6-editor всегда (C02 policy 88c1c01a), большие файлы через deferred open; (1) l86–l87: серверные флаги DOCUMENT_SESSION_PRODUCT_WIRING_* не были в env службы → join молча игнорировался (память landing-must-inventory-server-env, рецидив C09); (2) l88–l89: DB-триггер source_content_hash_pair_guard ронял durable join → фиксы c09join d3d61e24 + c09join2 0d25e824 (CAS по contentRevision, /api/sources/[id]/text ≤64 KiB) — в l90; (3) l90 браузер 1194: маленький Markdown → CM6 OK, большой TXT → пустой legacy shell → диагноз 1198 «hydration guard видел envelope» → фикс 886d9baf + типы 112f8952 (приёмка 1212 GO) — в l91; (4) l91 браузер 1231: большой TXT по-прежнему `legacy / unresolved deferred shell`, route-marker не появляется → третий круг класса → волна 1240 (живой performance-trace на проде + смена устройства: маршрут по размеру ДО первого рендера, большой источник сразу в CM6-shell с ленивой гидрацией, legacy contenteditable не монтируется). Проверка на проде — только Playwright под QA qa.c09.browser (пароль ops-backups/c09/…); отчёты /home/ubuntu/waves/C09BROWSER5/6-REPORT.md, C09BIGDOC-REPORT.md, C09BIGDOC2-REPORT.md, ACCC09BIGDOC*-REPORT.md; evidence-каталоги рядом. Текущий билд: l91 9ad68bc2 (фикс (3) внутри, поведение большого файла не изменилось).
2026-09-02T15:49:32.787Z · Fable
[A1 15:50 Фабл] C09, третий круг (смена устройства): волна 1240-c09bigdoc3 сдана, коммит cea6df4296 (ветка c09bigdoc3-1240, база l91-candidate). Суть: решение о маршруте больших источников (порог 256 KiB, src/lib/editor/editorOpenPreparation.ts) принимается ДО legacy WYSIWYG mirror / contenteditable — metadata-only ProductDocumentSource, route-маркер публикуется сразу, затем protected text → hydration; kill-switch/disabled/cohort-excluded по-прежнему legacy. Отчёт автора: A1 /home/ubuntu/waves/C09BIGDOC3-REPORT.md, трассы с прода l91: /home/ubuntu/waves/C09BIGDOC3-EVIDENCE/. История класса: l90 C09BROWSER5 FAIL → диагноз 1198 → фикс 886d9baf (приёмки 1201/1212 GO на моках) → на l91 C09BROWSER6 NO-GO (legacy shell висит) → третий круг = менять устройство. Дальше: приёмка 1263-accc09bigdoc3 (A1, свой harness + негативы) → cherry-pick в l92-candidate (A2 nc-build, ref c09bigdoc3-1240/head) → посадка l92 → браузерная приёмка на проде (1264). Бандл: A1 /home/ubuntu/mirrors/lines/c09bigdoc3-1240.bundle.
2026-09-02T16:22:30.487Z · Fable
[A1 16:30 Фабл] Приёмка 1263-accc09bigdoc3 = NO-GO (A1 /home/ubuntu/waves/ACCC09BIGDOC3-REPORT.md, harness приёмщика ACCC09BIGDOC3-open-harness.test.ts 8/11). Здоровый large-open seam подтверждён (metadata-only source, граница 256 KiB ±1, kill-switch/disabled/cohort → legacy, без contenteditable). Два блокера: (1) при ошибке/пустом /text surface публикует hydration=failed, но root-маркеры (EditorModal.tsx ~1772, второй источник — старый hydration effect ~3482) остаются route=document-session/cm6-source-text-ready вместо контракта route=legacy/c02-fallback; (2) editorOpenPreparation.ts:42 принимает contentLength >= 0 → нулевая/stale мета подавляет large-detection при наличии envelope. → волна 1268-c09bigdoc4 (A1): единая функция состояния маршрута (decision × hydration outcome → атрибуты), contentLength только > 0, harness приёмщика в регресс + свои негативы (/text 500/пусто/таймаут; contentLength undefined/0/-1). Дальше: приёмка → l92 → браузерная приёмка на проде 1264 (бриф в разделе отчёта 1263).
2026-09-02T17:02:49.907Z · Fable
[A1 17:12 Фабл] Корректировка после NO-GO 1263 сдана: волна 1268-c09bigdoc4, коммит ad9e828e2e (ветка c09bigdoc4-1268 = 1240 + ad9e828e, база l91-candidate). Закрыто: (1) единый resolver состояния маршрута src/lib/document-session/product-wiring/route-state.ts — при failed/fallback текущего documentId root переходит в route=legacy / c02-fallback / hydration=failed, ownership выключен; старый hydration effect в EditorModal убран (−102/+164); (2) contentLength используется только > 0 (0/отрицательный/строка/unknown при envelope → large-detection по телу) — product-wiring/source-text.ts. Harness приёмки 1263 перенесён в src/lib/document-session/__tests__/ (10 тестов PASS), таблица observable route state в отчёте A1 /home/ubuntu/waves/C09BIGDOC4-REPORT.md. Дальше: приёмка 1278-accc09bigdoc4 (A1, другой verifier: единый источник правды, fallback 500/пусто/таймаут/чужой id, contentLength-матрица, «незалипание» состояния) → GO → cherry-pick в l92-candidate → посадка l92 → браузерная приёмка на проде 1264. Эволюция: 1147 → 1194 FAIL → 1198 диагноз → 886d9baf (1201/1212 GO) → 1231 NO-GO → 1240 (смена устройства) → 1263 NO-GO → 1268. Бандл: A1 /home/ubuntu/mirrors/lines/c09bigdoc4-1268.bundle; A2 ref c09bigdoc4-1268/head.
2026-09-02T17:38:23.858Z · Fable
[A1 18:15 Фабл] Приёмка 1278-accc09bigdoc4 = NO-GO с одним НОВЫМ блокером (A1 /home/ubuntu/waves/ACCC09BIGDOC4-REPORT.md): оба блокера 1263 подтверждены закрытыми (единый resolver route-state, source-text с таймаутом 15 с, contentLength только > 0, bounded/read-only fallback, harness 10/10 не ослаблен); но kill-switch/гейт C09 читаются только из NEXT_PUBLIC_DOCUMENT_SESSION_PRODUCT_WIRING_* на сборке — в /admin/defaults namespace для C09 нет, т.е. выключить C09 на проде без пересборки нельзя. Решение (по принципу WEB-452: тумблеры = admin-defaults): волна 1286-c09bigdoc5 (A1) — namespace C09 в admin-defaults (enabled/killSwitch/cohort), effective gate с сервера в клиент через существующий механизм раздачи, env — fallback; тумблеры в /admin рядом с WEB-453; тесты матрицы admin-default × env × cohort. В отчёте 1278 уже есть бриф браузерной приёмки 1264. Эволюция: … → 1240 → 1263 NO-GO(2) → 1268 → 1278 NO-GO(1 новый: admin-defaults) → 1286.
2026-09-02T18:36:15.861Z · Fable
[A1 18:55 Фабл] Корректировка после NO-GO 1278 сдана: волна 1286-c09bigdoc5, коммит 2e7fdceaad (ветка c09bigdoc5-1286 = 1268 + admin-defaults). Заявлено: namespace C09 в admin-defaults (enabled/killSwitch/cohort), effective gate с сервера в клиент, env — fallback, тумблеры в /admin рядом с WEB-453. Отчёт: A1 /home/ubuntu/waves/C09BIGDOC5-REPORT.md. Дальше: приёмка 1312-accc09bigdoc5 (A1) → GO → l93-candidate → посадка → браузерная приёмка 1264 на проде (сценарий kill-switch через /admin). Бандл: A1 /home/ubuntu/mirrors/lines/c09bigdoc5-1286.bundle; A2 ref c09bigdoc5-1286/head. (l92 уже собран без этой линии и сажается сейчас.)
2026-09-02T19:25:20.590Z · Fable
[A1 20:00 Фабл] Приёмка 1312-accc09bigdoc5 = GO (A1 /home/ubuntu/waves/ACCC09BIGDOC5-REPORT.md): namespace C09 в admin-defaults, effective gate с сервера в клиент (другой процесс видит старое значение ≤30 с до refresh; при сбое RuntimeConfig last-known-good ≤300 с), kill-switch без пересборки, регресс 1263/1278 (resolver, fallback c02-fallback, contentLength>0) подтверждён. Линия c09bigdoc3-1240 + 1268 + 1286 → **l93-candidate** (A2, создан от l92-candidate). Дальше: сборка l93 после следующих GO (или по таймеру, чтобы не копить) → посадка → браузерная приёмка 1264 на проде (большой файл: клик → CM6 shell < 1 с, fallback, kill-switch через /admin). Эволюция: 1147 → 1194 FAIL → 1198 → 886d9baf (1201/1212 GO) → 1231 NO-GO → 1240 → 1263 NO-GO → 1268 → 1278 NO-GO → 1286 → 1312 GO.
2026-09-02T19:34:28.278Z · Fable
[A1 20:15 Фабл — сводка] C09 принят (1312 GO) и уже в l93-candidate (6acd0727). После посадки l93 — браузерная приёмка 1264 на проде (большой файл, fallback, kill-switch через /admin).
2026-09-02T22:09:45.131Z · Fable
[A1 22:55 Фабл] МАТРИЦА ДВИЖКА НА ПРОДЕ l93 (волна 1350, отчёт A1 /home/ubuntu/waves/ENGINEPRODMATRIX-REPORT.md, 73 улики в /home/ubuntu/waves/evidence/engineprod/): ответ owner-у — НЕТ, всё из эпика не работает. PASS: legacy-редакторы, малый wiki-пайплайн, C08 legacy-HTML viewer (с ограничением). FAIL/BLOCKED: A маршрутизация (все доки → legacy/c02-fallback hydration=failed, большие → cm6 pending без текста); B тулбар (нет H/ссылок/кода, C09 прячет) → WEB-491 волна 1387; C C06 save ack раньше записи → WEB-495 волна 1386; D realtime C07 — 500 /api/realtime/socket (нет res.socket.server в standalone) → WEB-492 P0 волна 1383; E большие документы (PDF extraction застряла, HTML/TXT partial после 504) → P0 волна 1384; G gated writer/mutating AI выключены в бандле (build-time флаги, сборка без них) → WEB-494 волна 1385 + флаги в build-env l94; H обзоры/wiki/NER на большом источнике BLOCKED из-за E; I 20×500 + 504. Следующая матрица — после посадки фиксов (l94/l95).
2026-09-04T15:08:17.177Z · coordinator
04.09 координатор: в body добавлен блок «ЭВОЛЮЦИЯ 04.09.2026» — состояние, причина с доказательством, что село, что осталось, ловушки.
2026-09-08T13:30:28.938Z · coordinator
[08.09 13:30Z координатор] Статус → **review**. Принято независимой приёмкой ACCEDITORPROD = GO. Продуктовая проводка headless-адаптера CodeMirror: подтверждено, что адаптер импортируется ПРОДУКТОВЫМ кодом, а не только своим тестом — именно за это был отклонён круг 1. В линию ещё не собрано.
2026-09-08T15:51:06.392Z · coordinator
[08.09 15:51Z координатор] Статус → **done**. подключение headless-адаптера CodeMirror к ПРОДУКТОВОМУ пути — независимая приёмка подтвердила, что адаптер импортируется продуктовым кодом, а не только своим тестом (за это был отклонён круг 1)

Посажено на прод линией **l113u** `4e0e5406db8b3844bfc7bc43148c37ddd4cdbf99` (артефакт `me2-standalone-linux-arm64-4e0e5406-20260908T151242Z`, sha256 `43a6d010…`), флип 08.09 15:34Z.

Проверено ПОСЛЕ флипа, не по факту деплоя: оба бэкенда `ready=true` и `paidReady=true` с новым releaseId; корень `https://app.sixbyy.com/` = 200; вебхук Telegram = 401; готовность SIP 4080 = 200; строк `LEASE_LOST` — 0.
Откат: l113t `a45e820c7ec1043fe601974fe24fe5026eaaf118`, релиз `arm64-l113t-20260908T131657Z`.
Воркер
не привязан — привязать: curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \ -d '{"issueId":"WEB-333","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-08T15:51:06.389Z