WEB-651 · Дефект · Редактор · web
P1 [редактор]: документы выше потолка 16M UTF-16 открываются и правятся, но НЕ сохраняются — правки теряются
В работе
P1 · важно
ведёт: —
эпик: WEB-221
Суть
## Суть
Документ больше потолка 16 000 000 единиц UTF-16 ОТКРЫВАЕТСЯ и РЕДАКТИРУЕТСЯ, но НЕ СОХРАНЯЕТСЯ. Пользователь может внести правки в очень большой документ и молча их потерять.
## Где мы сейчас (13.09.2026)
Прод = l115j (133fe00c). Карточка заведена координатором 13.09 по находке волны 3638 (DeepSeek, M1); работы по ней ещё нет. Потолок задан в src/lib/documents/documentLimits.ts:10-11 (DOCUMENT_MAX_UTF16_UNITS, по умолчанию 16 000 000). Замер на документе 20 млн единиц: первый текст 44.61 мс, готовность к правке 425.17 мс, 306 кусков по 64 КиБ — чтение и правка работают. Сохранение отказывает примерно за 70 мс: запись идёт одной цельной версией документа, а не кусками.
## Хронология
- 08.09: волна 2698 — находка URGENT_FINDING=RESCUE_DOWNLOAD_CAN_EXPORT_STALE_OR_EMPTY_TEXT; замер 20M (чтение работает, запись нет).
- 08.09 06:24Z: решение владельца — чанковое точное сохранение, а не запрет редактирования; проект разбит волной 2749 (CHUNKED-SAVE-DESIGN).
- 13.09: координатор завёл WEB-651 (P1, дочерняя к WEB-221) по находке волны 3638.
## Карта документов и кода
- src/lib/documents/documentLimits.ts:10-11,34,40-41,52-63,65-88 — потолок и производные лимиты.
- src/components/modals/EditorModal.tsx:4387-4399 (Hybrid меняет только dirty/version), 8247-8260 (Download берёт content) — смежные места потери текста.
- Проект чанкового сохранения: волна 2749 (CHUNKED-SAVE-DESIGN): протокол манифеста чанков, resumable запись, атомарная публикация на существующем CAS, совместимость с документами до 16M.
- Копия отчёта источника: nc-ops-scripts/shift-20260912-resume/colN/3638-gate-e-and-ai-act-out/RESULT.md.
## Остаток
1. Чанковое точное сохранение для документов >16M UTF-16 (весь объём). До него честный промежуточный вариант — выше потолка открывать документ только для чтения, иначе правки теряются молча.
2. Смежное: скачивание/экспорт в гибридном режиме могло отдавать пустой или устаревший текст (EditorModal.tsx около 4387-4399, 8247-8260) — сверить, закрыто ли это отдельными коммитами 07257c3e/b5526fb8 (посажены l113r).
## Критерий закрытия
Документ >16M UTF-16 редактируется И сохраняется без потери правок (чанковый save с манифестом/CAS/атомарной публикацией), либо до внедрения чанкового save документ выше потолка честно открывается только для чтения. Прогон с числами и линией посадки записан в карточке.
---
## История (старое тело)
Правила обогащения: WEB-449. Parent WEB-221. Заведено координатором 13.09 по находке волны 3638.
## Суть
Документ больше потолка 16 000 000 единиц UTF-16 ОТКРЫВАЕТСЯ и РЕДАКТИРУЕТСЯ, но НЕ СОХРАНЯЕТСЯ. Пользователь может внести правки в очень большой документ и молча их потерять.
## Механика
Потолок задан в src/lib/documents/documentLimits.ts, строки 10-11 (константа DOCUMENT_MAX_UTF16_UNITS, по умолчанию 16 000 000). Замер на документе 20 млн единиц: первый текст 44.61 мс, готовность к правке 425.17 мс, 306 кусков по 64 КиБ — чтение и правка работают. Сохранение отказывает примерно за 70 мс. Причина: запись идёт одной цельной версией документа, а не кусками.
## Что предлагается
Чанковое точное сохранение — проект описан волной 2749 (CHUNKED-SAVE-DESIGN). До него честный вариант: выше потолка открывать документ только для чтения, иначе правки теряются молча.
## Смежное (из того же разбора)
Скачивание и экспорт могли отдавать пустой или устаревший текст: в гибридном режиме на правке обновлялись только флаг изменения и версия, полный текст — нет (EditorModal.tsx около строк 4387-4399), а скачивание брало именно полный текст (около 8247-8260).
## Как воспроизвести
Открыть документ на 20 млн единиц UTF-16, внести правку, попытаться сохранить — отказ.
## Источник
Волна 3638 (DeepSeek, M1), RESULT.md пункт 1; сведено из истории комментариев 3302 и 3314. Копия отчёта: nc-ops-scripts/shift-20260912-resume/colN/3638-gate-e-and-ai-act-out/RESULT.md. Прод на момент заведения: l115j (133fe00c, посажен 13.09 08:50Z).
---
## история (тело до 13.09.2026)
Правила обогащения: WEB-449. Parent WEB-221. Заведено координатором 13.09 по находке волны 3638.
## Суть
Документ больше потолка 16 000 000 единиц UTF-16 ОТКРЫВАЕТСЯ и РЕДАКТИРУЕТСЯ, но НЕ СОХРАНЯЕТСЯ. Пользователь может внести правки в очень большой документ и молча их потерять.
## Механика
Потолок задан в src/lib/documents/documentLimits.ts, строки 10-11 (константа DOCUMENT_MAX_UTF16_UNITS, по умолчанию 16 000 000). Замер на документе 20 млн единиц: первый текст 44.61 мс, готовность к правке 425.17 мс, 306 кусков по 64 КиБ — чтение и правка работают. Сохранение отказывает примерно за 70 мс. Причина: запись идёт одной цельной версией документа, а не кусками.
## Что предлагается
Чанковое точное сохранение — проект описан волной 2749 (CHUNKED-SAVE-DESIGN). До него честный вариант: выше потолка открывать документ только для чтения, иначе правки теряются молча.
## Смежное (из того же разбора)
Скачивание и экспорт могли отдавать пустой или устаревший текст: в гибридном режиме на правке обновлялись только флаг изменения и версия, полный текст — нет (EditorModal.tsx около строк 4387-4399), а скачивание брало именно полный текст (около 8247-8260).
## Как воспроизвести
Открыть документ на 20 млн единиц UTF-16, внести правку, попытаться сохранить — отказ.
## Источник
Волна 3638 (DeepSeek, M1), RESULT.md пункт 1; сведено из истории комментариев 3302 и 3314. Копия отчёта: nc-ops-scripts/shift-20260912-resume/colN/3638-gate-e-and-ai-act-out/RESULT.md. Прод на момент заведения: l115j (133fe00c, посажен 13.09 08:50Z).
## Актуализация координатора 2026-09-26 12:01Z [refresh-20260926-roles-capacity]
Правила обогащения: WEB-449.
Разделены source acceptance и доставка: историческая независимая5045 GO для общего563db146 сохраняется в своём объёме (PG17/17+generic1, targeted291/291). Новая интеграция5058 со связанной CPU/worker веткой закончилась NO-GO без артефакта/bundle. Новые Linux fixes не приняты; успешные source tests не означают новую посадку. Общий оставшийся шаг — восстановление сборки координатором, затем полная проверка пакета и отдельная посадочная приёмка. Этот тикет не объявляется заново завершённым на основании5058.
КАРТА ДОКУМЕНТОВ / доказательства: M1:/Users/poolpooly/waves/5045MERGEDCANDIDATEINDEPENDENT-REPORT.md; A2:/home/ubuntu/waves/5058INTEGRATEDLINUXSTANDBUILD-REPORT.md; A2:/home/ubuntu/waves/5058INTEGRATEDLINUXSTANDBUILD-evidence/SHA256SUMS; ноутбук:/Users/annakorin/nc-ops-scripts/material-5058/5056NEXTBOOTSTRAPCOMPATIBILITYCOMPLETION.bundle
Лента
2026-09-13T10:34:59.381Z · coordinator[13.09 10:34Z координатор] Волна 3646 нашла весь путь сохранения и объяснила молчаливую потерю: тело документа лежит одной строкой и пишется одним обновлением, а при превышении потолка в 16 миллионов символов запись отклоняется — редактор об этом не знает. Написаны два документа: задание на чанковое сохранение (большое решение) и точный быстрый фикс. Быстрый фикс уже отправлен в работу волной 3656: такие документы будут открываться только для чтения, с понятным текстом пользователю, вместо тихой потери правок.
2026-09-13T10:37:39.818Z · coordinator[13.09 10:37Z координатор] Мойка доски, волна 3651. OPEN. Карточка заведена 13.09 по находке волны 3638, работы нет. Документ >16M UTF-16 правок не сохраняет (запись одной цельной версией). Нужна волна чанкового точного сохранения (проект 2749) — готовый бриф B. Честный промежуточный вариант — выше потолка открывать только для чтения. Координатор: быстрый фикс (режим только чтения выше потолка) уже в работе волной 3656, поэтому карточка остаётся в работе, а не в очереди.
2026-09-13T10:59:14.796Z · coordinator[13.09 10:59Z координатор] Волна 3656 (GO, refs/waves/3656 = e18076e8): быстрый фикс сделан. Документ выше потолка в 16 миллионов символов теперь приходит с сервера с признаком «только чтение» и причиной, редактор объединяет этот признак с уже существующим и показывает человеку понятный текст: слишком большой для сохранения, открыт только для чтения. Молчаливая потеря правок на этом пути закрыта.
Попутно найдено и исправлено второе, независимое место: у входа в сессию документа была СВОЯ проверка размера, отдельная от той, что мы чинили — то есть дыра была не одна.
Что этот фикс НЕ решает: сохранять такие документы по-прежнему нельзя. Настоящее решение — чанковое хранение, задание на него написано волной 3646 и лежит отдельно.
2026-09-13T12:50:57.281Z · coordinator[13.09 12:50Z координатор] Настоящее решение сделано (волна 3693, refs/waves/3693 = c78aa02f).
Тело документа больше не лежит одной гигантской строкой: оно раскладывается на пронумерованные кусочки примерно по миллиону знаков и собирается обратно в ровно тот же текст. Ни один символ не теряется и не портится на границе кусочка, включая невидимые — переносы строк, неразрывные пробелы, эмодзи. Потолок сохранения поднялся с 16 миллионов знаков до примерно 268 миллионов.
Три гарантии, которые волна обязана была доказать и доказала тестами: обрыв посреди записи оставляет документ в прежнем исправном состоянии, полусохранённого не бывает; одновременная правка двумя людьми даёт одному явный отказ «документ изменился», а не тихую потерю; документы ниже прежнего потолка ведут себя ровно как раньше.
Честный нюанс из отчёта: живой совместный редактор — отдельный механизм с отдельным хранилищем, его в этой волне не трогали намеренно. Такой документ выше потолка по-прежнему открывается только для чтения, но теперь открывается с полным правильным текстом, а раньше мог открыться пустым или неполным — это тоже починено.
2026-09-13T17:37:08.513Z · coordinator[13.09 17:37Z координатор] ПОСАЖЕНО В ПРОД. Линия l115k, источник `ac4eb8c68d70de829608bcae5a7acef693ab85fb`, артефакт `me2-standalone-linux-arm64-ac4eb8c68-20260913T165733Z` sha256 `eafbeb5146ddf0b498f82d608ddd30d15053d23156b43603dfb88dfe71aaebed`, релиз `arm64-l115k-20260913T165733Z`, переключение 13.09 17:27:44Z.
Проверено после переключения: публичный `https://app.sixbyy.com/` 200, `/api/ready` `ready:true` с коммитом линии, проба базы пройдена, `paidReady:true`, поза `enforce_ready`, обе копии приложения (3010 и 3012) и рабочие таймеры на новом релизе, упавших юнитов нет. Артефакт опубликован на Hetzner: `release_id=l115k-ac4eb8c6`, 244545299 байт, удержание 5.
Откат: `sudo python3 /home/ubuntu/transition-l115k.py rollback` → l115j (`133fe00c`).
Особенность этой посадки: впервые с 12.09 поехали настоящие миграции, 206 → 209 (`web651_source_text_chunk`, `web575_erasure_tombstone`, `web575_embed_share_audience`), расписка `prod/shared/l115k-migration/apply-receipt.json`, личность применения `web_migrator`.
2026-09-13T20:18:52.550Z · coordinator[13.09 20:18Z координатор] ПОСТ-QA РАУНД 2 — ДОКАЗАНО. Инструмент: `scripts/postqa/l115k-postqa-dom.mjs` (волна 3742), прогон координатора против исходника КОММИТА, КОТОРЫЙ СЕЙЧАС В ПРОДЕ (`ac4eb8c68d70de829608bcae5a7acef693ab85fb`, отдельный worktree `wt-postqa-release`), результат `/tmp/l115k-postqa-dom.json` на A1.
Итог: **PROVEN 4, не проверяется этим способом 1.**
- WEB-576 — маркер происхождения ИИ переживает выгрузку EPUB/FB2/MOBI — **PROVEN**
- WEB-571 — видимая обратная связь кнопки «Поделиться» (фоллбэк буфера + тост) — **PROVEN**
- WEB-583 — редактор: разделение сохранения и переиндексации, сохранение прокрутки на больших документах — **PROVEN**
- WEB-325 — рубильник Gate E действительно блокирует правки ИИ (очистка localStorage сохраняет оба рубильника) — **PROVEN**
- WEB-651 — клиентская половина (баннер «только для чтения») — не проверяется в jsdom: она вшита в эффект живого socket.io-присоединения к сессии; серверная половина проверяема живым пробником.
ПОЧЕМУ ЭТОМУ МОЖНО ВЕРИТЬ, А НЕ ПРОСТО «ТЕСТЫ ЗЕЛЁНЫЕ». У каждой проверки есть пара «краснеет/зеленеет», и краснеет она НА НАСТОЯЩЕМ КОДЕ ДО ФИКСА, а не на синтетической заглушке:
- WEB-576 → красный на `66dbb8882~1`
- WEB-571 → красный на `db5b414cc~1`
- WEB-325 → красный на `a4353bcda~1`
- WEB-583 → красный на мутанте (`shouldShowIndexingDeferredNotice` всегда `false`), это единственная синтетическая пара из четырёх, и волна это честно пометила.
ЧТО ЭТО ДОКАЗЫВАЕТ И ЧЕГО НЕ ДОКАЗЫВАЕТ. Доказывает: поведение кода, который сейчас работает в проде, в среде DOM, с отрицательным контролем на настоящем до-фиксном коде. НЕ доказывает: клик живого человека в настоящем браузере на настоящем проде — для этого нужна ручная проба, и для WEB-651 волна расписала её по шагам (открыть документ сверх 16 000 000 единиц UTF-16, убедиться, что редактор открылся только для чтения с баннером и БЕЗ сообщения «не удалось сохранить»).
СТАТУСЫ: WEB-576, WEB-571, WEB-583, WEB-325 → done. WEB-651 остаётся открытым до ручной браузерной пробы.
Отдельно закрыт долг инструмента: проверка WEB-467 переписана под настоящую форму ответа кошелька (`mode='real_spend_ledger'`, `days[].groups[].details[]`) и смотрит на статусы урегулирования и подвисшие кредиты, а не на факт ответа 200. Ложных тревог по ней больше не будет.
2026-09-14T11:13:00.068Z · coordinator[14.09 11:12Z координатор] ПОЧЕМУ ЭТА КАРТОЧКА В REVIEW (для того, кто откроет её без контекста).
Продуктовая часть сделана и посажена. Осталось одно, чего НЕЛЬЗЯ доказать программой: клик живого человека в браузере.
Что сделано: волна 3693 (GO) — чанковое сохранение. Тело документа раскладывается на пронумерованные кусочки ~1 млн знаков и собирается обратно байт в байт, включая невидимые символы на границах. Потолок сохранения 16 млн знаков → около 268 млн. Доказано тестами: обрыв посреди записи не оставляет полусохранённого документа; одновременная правка даёт явный отказ, а не тихую потерю; документы ниже потолка ведут себя как раньше.
Честная оговорка самой волны: живой совместный редактор — отдельный механизм, его не трогали. Документ выше потолка по-прежнему только для чтения, но теперь открывается с ПОЛНЫМ текстом (раньше мог открыться пустым).
ПОЧЕМУ НЕ ЗАКРЫТ. Пост-QA линии l115k (волна 3742) доказала четыре тикета из пяти прогоном против исходника прод-коммита. Этот — единственный, помеченный NOT-PROBEABLE-VIA-JSDOM-BUNDLE: клиентский баннер «только для чтения» вшит в эффект живого присоединения socket.io, и в собранном бандле под jsdom этот путь не исполняется. То есть проверка не «не нашла дефект», а физически не может его достичь.
ГРАНИЦА ЗАЯВЛЕНИЯ: доказано поведение прод-кода при сохранении и открытии больших документов. НЕ доказано, что человек видит правильный баннер в живом браузере.
ЧТО ЗАКРОЕТ КАРТОЧКУ: ручной сценарий в браузере — открыть документ выше потолка 16M UTF-16, убедиться, что текст виден полностью и что показан признак «только чтение» с объяснением причины. Сценарий расписан по шагам в пост-QA 3742.
TROUBLESHOOTER: если документ выше потолка открывается ПУСТЫМ — это регрессия чанкового сохранения, смотреть refs/waves/3693 = c78aa02f. Если открывается с текстом, но без баннера — это ровно остаток данной карточки, а не новый дефект.
2026-09-14T12:07:46.281Z · coordinator[14.09 12:07Z координатор] WEB-651 — очень большой документ не сохраняется, а иногда открывается пустым
Обновление от 2026-09-14. Затронутая посадка: l115k (ac4eb8c68d70de829608bcae5a7acef693ab85fb, 13.09 17:27:44Z). Эта посадка принесла первую в истории линии `contract`-миграцию, которая НЕ безопасна для отката, — она относится именно к этому тикету.
Карточка написана для человека, который открывает её впервые и не имеет ни журнала смены, ни переписки.
1. ЧТО БЫЛО СЛОМАНО
Очень большой документ либо не сохраняется вовсе, либо — что хуже — ОТКРЫВАЕТСЯ ПУСТЫМ. Человек видит пустую страницу вместо своего текста и не понимает, потерян ли он.
Отдельно: продукт не объяснял причину. Документ просто вёл себя странно, без сообщения.
2. КАК НАШЛИ И ПОЧЕМУ НЕ ПОЙМАЛИ РАНЬШЕ
Находка пришла побочно: волна 3638 обнаружила, что документы свыше 16 миллионов знаков не сохраняются, и это было заведено отдельной карточкой.
Почему не поймали раньше: ограничение не сообщалось пользователю никак. Волна 3656 (`refs/waves/3656` = `e18076e8`) сделала так, чтобы признак «только чтение» приходил С СЕРВЕРА и редактор показывал человеку причину; ПОПУТНО она нашла ВТОРУЮ, НЕЗАВИСИМУЮ проверку размера у входа в сессию — дыра была не одна.
3. ЭВОЛЮЦИЯ, ВКЛЮЧАЯ ТУПИКИ
3.1. РЕШЕНИЕ ПО СУЩЕСТВУ — чанковое сохранение (волна 3693, `refs/waves/3693` = `c78aa02f`). Тело документа раскладывается на пронумерованные кусочки примерно по миллиону знаков и собирается обратно БАЙТ В БАЙТ, включая невидимые символы на границах. Потолок сохранения 16 миллионов знаков поднимается примерно до 268 миллионов.
3.2. ГЛАВНЫЙ СЮЖЕТ ЭТОЙ КАРТОЧКИ — МИГРАЦИЯ, КОТОРАЯ ЧУТЬ НЕ ОСТАНОВИЛА ПОСАДКУ, И ПОЧЕМУ ОНА ЕЁ НЕ ОСТАНОВИЛА.
Кандидат линии l115k принёс ТРИ новые миграции, не объявленные в манифесте совместимости, и сборка ПРАВИЛЬНО встала на гейте. Волна 3729 объявила их в манифесте с классификацией, выведенной РЕАЛЬНЫМ запуском инспектора SQL:
`20260911100000_web651_source_text_chunk` → `contract` (пара DROP TRIGGER / CREATE CONSTRAINT TRIGGER на таблице `Source`, по прецеденту десяти других миграций манифеста);
`20260913100000_web575_erasure_tombstone` и `20260913110000_web575_embed_share_audience` → `expand` (чистые CREATE TABLE/INDEX).
Негатив показан ДВАЖДЫ: ложное объявление первой миграции как `expand` роняет гейт на конкретном месте с триггером; порча контрольной суммы набора роняет гейт с ошибкой устаревшего базиса.
3.3. ВТОРОЙ ГЕЙТ, НА КОТОРОМ ВСЁ ЧУТЬ НЕ ВСТАЛО НАСОВСЕМ.
Скрипт посадки требовал `phase == 'expand' и rollbackSafe` для КАЖДОЙ новой миграции, а `web651_source_text_chunk` объявлена как `contract` с `backwardCompatible=false, forwardCompatible=false, rollbackSafe=false`. Скрипт ПРАВИЛЬНО отказывался её пропускать.
Координатор прочитал SQL сам. По существу миграция аддитивная: новая таблица `SourceTextChunk`, три новые колонки в `Source`, пересоздание того же охранного триггера. НО в ней есть `ALTER TABLE "Document" ALTER COLUMN "content" DROP NOT NULL` — ослабление ограничения, которое при откате автоматически НЕ возвращается, если успели появиться строки со значением NULL.
ТУПИК, В КОТОРЫЙ СОЗНАТЕЛЬНО НЕ ПОШЛИ: ослабить проверку до «любая `contract` сойдёт». Это и есть защита цели отката, и снимать её ради зелёного нельзя.
ПРИНЯТОЕ РЕШЕНИЕ — узкое и проверяемое послабление: `contract`-миграция принимается ТОЛЬКО если её запись объявляет флаг возможности со значением по умолчанию `off` И этот флаг фактически ВЫКЛЮЧЕН в окружении. У `web651` такой флаг есть: `WEB651_SOURCE_TEXT_CHUNK_CONTRACT_ATTESTED`, умолчание `off` (см. `prisma/migration-compatibility-manifest.json`). При выключенном флаге новый путь записи МЁРТВ, `Document.content` не получает NULL ни в одной строке, и откат остаётся безопасным ПО СУЩЕСТВУ, а не по декларации. Флаг, оказавшийся включённым, ОСТАНАВЛИВАЕТ ПОСАДКУ ДО НЕЁ, а не после. В расписку применения миграций добавлено поле `contractMigrations`.
Решение принято одним человеком и записано открыто — именно для того, чтобы следующий агент видел цену и мог его оспорить.
3.4. НАХОДКА ПРИЁМКИ, КОТОРАЯ К ЭТОЙ МИГРАЦИИ НЕ ОТНОСИТСЯ, НО ВАЖНА.
Приёмка 3734 подтвердила классификацию (правило «одна фаза совместимости на релиз» этими тремя записями не нарушено — у каждой свой ярлык релиза и это действительно независимые изменения), НО доказала СВОИМИ ТРЕМЯ ТЕСТАМИ (`scripts/__tests__/acceptance3734-p19-gate-gaps.test.mjs`), что САМ МЕХАНИЗМ ГЕЙТА ДЫРЯВЫЙ: пара «`contract` + `expand` с разными ярлыками релиза в одном наборе миграций» проходит, и `DROP DEFAULT` на колонке NOT NULL, объявленный как `expand/rollbackSafe:true`, тоже проходит. Это находка на ОТДЕЛЬНЫЙ тикет, а не вина волны 3729.
3.5. ТУПИК — тикет НЕ был закрыт вместе с соседями, и это оказалось правильно.
Когда координатор закрывал четыре тикета по вердикту DOM-пробника, этот был ОСТАВЛЕН ОТКРЫТЫМ с прямой причиной: клиентский баннер вшит в эффект живого присоединения по сокету, и программой его не доказать; ручной сценарий расписан по шагам. Независимая приёмка 3743 вернула три из четырёх закрытых — этот тикет в возврат не попал, потому что и не закрывался.
4. ЧТО СДЕЛАЛИ В ИТОГЕ
Волна 3656 (`e18076e8`) — признак «только чтение» приходит с сервера, редактор показывает причину; найдена вторая независимая проверка размера у входа в сессию.
Волна 3693 (`c78aa02f`) — чанковое сохранение.
Волна 3729 — объявление трёх миграций в манифесте совместимости с проверяемой классификацией; контрольная сумма набора миграций пересчитана КОДОМ ПРОЕКТА, а не вручную.
Линия l115k = `ac4eb8c68d70de829608bcae5a7acef693ab85fb`, посажена 13.09 17:27:44Z. МИГРАЦИИ НА ПРОДЕ: 206 → 209, личность применения `web_migrator`, расписка `prod/shared/l115k-migration/apply-receipt.json` со списком `contractMigrations`. (Число 204 в манифесте — это размер набора миграций в репозитории, другой счёт; не путать.)
Комментарий о посадке разослан в этот тикет в числе прочих.
5. ЧЕМ ДОКАЗАНО И ГРАНИЦЫ ЗАЯВЛЕНИЯ
ДОКАЗАНО:
Чанковое сохранение доказано тестами: обрыв посреди записи НЕ оставляет полусохранённого документа; одновременная правка даёт ЯВНЫЙ ОТКАЗ, а не тихую потерю; документы ниже потолка ведут себя как раньше; сборка обратно побайтовая, включая невидимые символы на границах.
Пост-QA линии l115k (волна 3777) доказал НА НАСТОЯЩЕЙ PostgreSQL ровно то, ради чего ставился гейт: `contract`-миграция `web651` НЕ МОЖЕТ ОПУСТОШИТЬ `Document.content`, пока её флаг выключен. Обе `expand`-миграции обратимы без следа. Это прямая защита цели отката.
Гейт совместимости показал негатив дважды (ложная классификация и порченый базис роняют сборку).
ГРАНИЦЫ — читать обязательно:
ЖИВОЙ СОВМЕСТНЫЙ РЕДАКТОР — ОТДЕЛЬНЫЙ МЕХАНИЗМ, ЕГО НЕ ТРОГАЛИ. Документ выше потолка по-прежнему ТОЛЬКО ДЛЯ ЧТЕНИЯ; изменилось то, что теперь он ОТКРЫВАЕТСЯ С ПОЛНЫМ ТЕКСТОМ, тогда как раньше мог открыться пустым.
КЛИЕНТСКИЙ БАННЕР «ТОЛЬКО ЧТЕНИЕ» ЧЕЛОВЕКОМ В БРАУЗЕРЕ НЕ ПОДТВЕРЖДЁН. Он вшит в эффект живого присоединения по сокету, и серверная проба его не видит.
Безопасность отката держится НА ВЫКЛЮЧЕННОМ ФЛАГЕ, а не на свойстве миграции. Включённый флаг делает откат линии небезопасным по существу.
6. ЧТО ОСТАЛОСЬ ОТКРЫТЫМ
Браузерная проверка баннера «только чтение» человеком. Ручной сценарий расписан по шагам.
Дырявость самого механизма гейта миграций (находка приёмки 3734) — отдельный тикет.
7. TROUBLESHOOTER — ЕСЛИ БОЛЬШОЙ ДОКУМЕНТ СНОВА ВЕДЁТ СЕБЯ СТРАННО
Шаг 1. ПЕРВЫМ ДЕЛОМ проверить флаг `WEB651_SOURCE_TEXT_CHUNK_CONTRACT_ATTESTED` в окружении прода.
Выключен (умолчание) — новый путь записи мёртв, откат линии безопасен.
ВКЛЮЧЁН — новый путь живой, в `Document.content` могли появиться NULL, и ОТКАТ ЛИНИИ БОЛЬШЕ НЕ БЕЗОПАСЕН ПО СУЩЕСТВУ, что бы ни было объявлено в манифесте. Это надо знать ДО, а не после.
Шаг 2. Если документ открывается пустым — проверять ОБЕ проверки размера. Их две и они независимы: серверный признак «только чтение» и отдельная проверка у входа в сессию. Починка одной ничего не даёт.
Шаг 3. Если баннер «только чтение» не показывается — это КЛИЕНТСКИЙ путь, вшитый в эффект живого присоединения по сокету. Серверная проба его не увидит НИКОГДА; нужен человек в браузере.
Шаг 4. Если посадка встала на гейте миграций с отказом по `contract` — НЕ ослаблять проверку до «любая contract сойдёт». Правильный путь: у миграции должен быть объявленный флаг возможности с умолчанием `off`, и этот флаг должен быть фактически выключен в окружении. Иначе посадку надо остановить, а не пропустить.
2026-09-15T01:25:26.432Z · coordinator[15.09 01:25Z координатор] ## 15.09 01:40Z — ВОШЁЛ В ПОСАДКУ l115o. Требуется пост-QA на проде.
Прод работает на `l115o-68e25d8d` (коммит `68e25d8df5ae8263c5ac5466353631f57a17cfcc`, артефакт `cd2773f65d66b09ec03d39b553041d2814ce09413e72d72b07bc9de89df536c8`) с 00:56Z 15.09. Посадка проверена: `ready=true`, коммит совпал, браузерная проба открыла документ, 0 новых ошибок.
**Работу по этому тикету принесли волны:** 3742.
**Что это значит для этого тикета.** Работа по нему пролежала принятой, но НЕ посаженной — в некоторых случаях неделями. Теперь она на проде. Приёмка волной доказывала, что код правильный в дереве волны; она НЕ доказывала, что фича работает на живом проде. Это разные вещи, и мы на этом уже обжигались.
**Поэтому статус — `review`, а не `done`.** Закрыть тикет имеет право только пост-QA, который проверит поведение на работающем проде и приложит доказательство. До тех пор «сделано» — это заявка.
### Для нулевого агента (тот, кто будет делать пост-QA)
Ты приходишь на этот тикет без нашей истории. Что надо знать:
1. **Проверяй на проде, не на стенде.** Стенд сейчас вообще не поднят — у него не было своего артефакта, он запускался из каталога боевого релиза и заблокировал проверку посадки; пересобирается волной 3948 (WEB-662).
2. **`/api/health` ничего не доказывает** — он проходит и на пустом приложении. Нужно деловое действие: аутентифицированная сессия делает то, про что этот тикет.
3. **Отсутствие ошибок в логе — не доказательство жизни.** Нужен положительный результат, а не тишина.
4. **Числа в обосновании закрытия получай командой в момент закрытия.** Я однажды закрыла тикет числом `4255`, взятым из `pg_stat_user_tables.n_live_tup` — это ОЦЕНКА. Настоящее `count(*)` дало `107 817`. Разница в 25 раз.
5. **Не верь имени волны в теме коммита** — проверяй наличие содержимого (`git cherry`), а не упоминание номера.
6. Запускатель тестов в проекте — `node --test`. Vitest нет.
2026-09-15T13:32:04.003Z · coordinator[15.09 13:32Z координатор] [15.09 13:27Z координатор] M1/4016 на exact l115o статически подтвердил конкретный остаток: основной C09 editor path всё ещё ограничивает hydration/persistExact/authority 16M UTF-16, хотя chunked storage рассчитан выше. WEB-651 переведён в in_progress; Neo/4020 исправляет механизм и обязан дать RED→GREEN на disposable fixture ровно 16,000,001 UTF-16 с save/reopen hash equality. Production и живые документы не трогать.
2026-09-15T13:39:33.474Z · coordinator[15.09 13:39Z координатор] [15.09 13:40Z координатор] Reconciliation 4016 на exact l115o нашла точный source-дефект: chunked storage/streaming route поддерживают 268,435,456 UTF-16, но основной C09 editor path всё ещё ставит legacy 16,000,000 в hydration, persistExact и authority/read-only guard. Поэтому тикет переведён review→in_progress. Neo/4020 чинит только эту границу и обязана показать RED→GREEN open/edit/save/reopen на synthetic fixture ровно 16,000,001 UTF-16 без печати содержимого.
2026-09-15T14:05:07.395Z · coordinator[15.09 14:05Z координатор] [15.09 14:02Z координатор] Neo/4020 сдала corrective candidate 6d49005e: VERDICT=INCOMPLETE, bundle verified against exact l115o, evidence 10/10 SHA256. Candidate снимает legacy 16M authority/read-only ceiling только с основного C09 path и использует существующий chunked ceiling 268,435,456; BASE RED на 16,000,001 UTF-16 подтверждён, focused 59 pass/0 fail, scoped typecheck и diff-check зелёные. Закрывать и принимать код пока нельзя: обязательный PostgreSQL persistExact end-to-end (реальные SourceTextChunk writes, canonical read, revision и reopen hash equality) не запускался из-за отсутствующего disposable DB URL; 8 PG-tests skipped. Статус остаётся in_progress, остаток нужно выполнить на машине с disposable PostgreSQL, без live DB.
2026-09-15T14:46:44.052Z · coordinator[15.09 14:46Z координатор] Независимая PostgreSQL-приёмка 4039: VERDICT=GO. Exact candidate `6d49005e065146a668aef12d9168575f25f9cbcb`, prerequisite l115o; dispatcher закрыл волну по marker, report и 18/18 SHA256 проверены. На свежем PostgreSQL 16.15 + pgvector с 204 миграциями BASE сделал 16M+1 read-only, candidate реальным `persistExact` выполнил open→marker→два exact save→revision switch→close/reopen. Итог: 16,000,051 UTF-16, exact SHA, editable=true, 16 ordered chunks, one generation, stale=0, Source.content/Document.content NULL. Small path, 268,435,456 ceiling, stale writer, rollback, gap/order и route guards зелёные; disposable DB и процессы удалены. TypeScript diagnostics только в untouched generated/dependency types и честно записаны. Candidate принят для следующей линии; статус in_progress→review до интеграции, build, посадки и production post-QA.
2026-09-15T22:04:50.082Z · coordinatorДЛЯ ТИКЕТА WEB-651 - сводка под нулевого агента (составлено 2026-09-15, read-only)
Симптом. Документ больше потолка 16 000 000 единиц UTF-16 открывается и редактируется, но НЕ сохраняется. Человек вносит правки в очень большой документ и молча их теряет.
Тело устарело в первой же строке состояния. "Где мы сейчас (13.09.2026)" говорит: "работы по ней ещё нет". Это неверно с 15.09 - кандидат есть и принят. Читать тело как руководство нельзя.
Механика (тело, не отменено). Потолок задан в src/lib/documents/documentLimits.ts:10-11 (DOCUMENT_MAX_UTF16_UNITS, по умолчанию 16 000 000). Замер на документе 20 млн единиц: первый текст 44.61 мс, готовность к правке 425.17 мс, 306 кусков по 64 КиБ - чтение и правка работают. Сохранение отказывает примерно за 70 мс: запись идёт одной цельной версией документа, а не кусками.
Путь к закрытию - четыре шага, все с фактом:
1. 2026-09-15T13:32:04.003Z - M1/4016 на exact l115o статически подтвердил конкретный остаток: основной C09 editor path всё ещё ограничивает hydration/persistExact/authority 16M UTF-16, хотя chunked storage рассчитан выше. WEB-651 переведён в in_progress.
2. 2026-09-15T13:39:33.474Z - reconciliation 4016 нашла точный source-дефект: chunked storage/streaming route поддерживают 268 435 456 UTF-16, но основной C09 editor path всё ещё ставит legacy 16 000 000 в hydration, persistExact и authority/read-only guard. Neo/4020 чинит только эту границу и обязана показать RED->GREEN open/edit/save/reopen на синтетической фикстуре ровно 16 000 001 UTF-16, без печати содержимого.
3. 2026-09-15T14:05:07.395Z - Neo/4020 сдала corrective candidate 6d49005e, VERDICT=INCOMPLETE, бандл сверен с exact l115o, evidence 10/10 SHA256. Кандидат снимает legacy 16M authority/read-only ceiling только с основного C09 path и использует существующий chunked ceiling 268 435 456; BASE RED на 16 000 001 UTF-16 подтверждён; focused 59 pass / 0 fail; scoped typecheck и diff-check зелёные. Принять было нельзя: обязательный PostgreSQL persistExact end-to-end ещё не был выполнен.
4. 2026-09-15T14:46:44.052Z - независимая PostgreSQL-приёмка 4039: VERDICT=GO. Exact candidate 6d49005e065146a668aef12d9168575f25f9cbcb, prerequisite l115o; marker, report и 18/18 SHA256 проверены. На свежем PostgreSQL 16.15 + pgvector с 204 миграциями BASE сделал 16M+1 read-only; кандидат реальным persistExact выполнил open->marker->два exact save->revision switch->close/reopen. Итог: 16 000 051 UTF-16, exact SHA, editable=true, 16 упорядоченных кусков, одна генерация, stale=0.
Текущее состояние. Кандидат 6d49005e... принят как вход следующей линии и на прод не посажен; статус review. Прод по телу - l115j (133fe00c), то есть на проде потолок 16M жив, и правки выше потолка по-прежнему теряются молча.
Первый шаг нулевого агента (2 минуты). Проверить, вошёл ли 6d49005e... в текущую обслуживаемую линию (прогонщик: git cherry / merge-base, не по имени волны в теме коммита). Если не вошёл - посадить и снять живую расписку на синтетическом документе ровно 16 000 001 UTF-16 (open->правка->два save->revision switch->close/reopen с точным SHA). Если вошёл - снять ту же расписку на обслуживаемой границе.
Чего в карточке НЕТ - и это пробел. Поле доказательств пусто; отчёты волн 4020/4039 и их evidence-каталоги в карточке не приложены полными путями. Дописать при посадке.
2026-09-15T23:42:37.989Z · coordinatorL115Q-LANDING-20260915-WEB-651
[15.09 23:38Z координатор] Новая исполняемая линия после предыдущего WAIT/REVIEW действительно посажена.
- Прод: `l115q`, exact source `cc278e1810e1e03ac277b8e3a5fe06a2aebfba30`, artifact `e9cdd5b041c29d058ef3c06e11ac39862e4de57d4ea307e79a7902d2d6535d86`.
- Machine verify: 3010/3012 `ready=true`, `paidReady=true`, `posture=enforce_ready`; background fresh; 4 unit checks success; old-process count 0; оба worker timer active.
- Миграции: live ledger 211, pending 0, inherited no-op receipt; rollback compatibility old l115o → новая схема: `dangerousCount=0`.
- Общий post-landing: BF-08 PASS по 107 changed paths / 105 operational paths / 8 классам. Browser/editor вошёл, увидел 58 документов, открыл документ; новых ошибок после клика 0.
- Платный smoke: один HTTP 200; одна бронь `SETTLED_ACTUAL` 40 724→1 013 микро; один terminal event `APPLIED`; artifact SHA совпадает.
- Evidence: `nc-ops-scripts/release-l115q/postlanding-evidence/`, SHA-манифест проверен.
Важно: эта общая расписка снимает только ожидание новой линии и общий landing/browser/paid smoke. Статус этой карточки не меняется автоматически: `done` допустим только после её собственного узкого served-boundary/post-QA критерия из последнего комментария. Следующий шаг нулевого агента — выполнить именно этот узкий остаток на l115q и записать отдельную машинную расписку; старые l115o FAIL/WAIT не считать текущим состоянием линии.
2026-09-22T18:07:03.006Z · triage-neoРЕШЕНИЕ=in_progress
ОСНОВАНИЕ=Независимая PostgreSQL-приёмка 4039: VERDICT=GO для 6d49005e; посадка L115Q-LANDING-20260915-WEB-651 на l115q зафиксирована, но общая расписка прямо оставляет собственный served-boundary/post-QA тикета незакрытым.
ЧТО НУЖНО=На l115q дать отдельную машинную расписку WEB-651: 16,000,001 UTF-16 open/edit/save/reopen, revision switch и точное совпадение SHA.
triage-neo 4604
2026-09-23T09:53:46.005Z · coordinator[23.09 09:53Z координатор] ## 4693 (M1, Luna) — в работе: сверх потолка 16M — read-only с честным баннером + серверный отказ `document_over_ceiling`; экспорт/скачивание берут актуальный текст (дефект EditorModal ~4387/8247); ниже потолка байт-в-байт как было. Чанковое сохранение (2749) — отдельно.
2026-09-23T10:16:33.777Z · coordinator[23.09 10:16Z координатор] ## 4693 (M1, GO, 5/5) — принято: сервер (save/upload/realtime) отвергает текст выше `DOCUMENT_MAX_UTF16_UNITS` кодом `document_over_ceiling` с лимитом и фактическим размером; документ сверх потолка открывается read-only с полным текстом и русским баннером («правка недоступна, экспорт доступен»), органы правки отключены до начала правки; экспорт Hybrid/C09 читает живой источник редактора (тот же, что сохранение) — тест на несохранённую правку. Ниже потолка — без изменений. 2 коммита; ветка A2 `l115s-web651-over-ceiling` (c0252165). Чанковое сохранение (проект 2749) остаётся отдельной задачей. Статус ← review.
2026-09-23T10:34:49.389Z · coordinator[23.09 10:34Z координатор] ## 4695 (M1, независимая приёмка) — **WEB-651 = NO-GO, 2 critical**: серверные пути записи, обходящие отказ `document_over_ceiling`: (1) `persistUpdatedSource` пишет `newContent` напрямую (`src/lib/sources/updateSource.ts:77-80`, вход через `src/app/actions.ts:7704-7705`); (2) `/api/sync` принимает `SourcePayload.content` без проверки (`sync/route.ts:1129-1175` → `buildSourceSyncRows` → транзакция wipe/recreate) — импорт/восстановление. Read-only UI, realtime, upload, product save, граница UTF-16, экспорт — PASS. Починка — 4697 (M1): один центральный guard на ВСЕ пути записи текста + репродуктор 4695 зелёный. Статус ← in_progress.
2026-09-23T11:01:10.090Z · coordinator[23.09 11:01Z координатор] ## 4697 (M1, GO, 7/7) — принято: один центральный guard `assertDocumentWithinCeiling` (`src/lib/documents/documentLimits.ts`, тот же inclusive UTF-16 потолок, отказ `document_over_ceiling` через `DocumentLimitError`) на 26 точках записи Source/Document/SourceTextChunk, включая legacy `persistUpdatedSource`, sync wipe/recreate, import/restore; репродукторы 4695 зелёные; сторожевой тест точек записи. Ветка A2 `l115s-web651-over-ceiling` = 4 коммита. Повторная независимая приёмка — 4699. Статус ← review.
2026-09-23T11:20:18.851Z · coordinator[23.09 11:20Z координатор] ## 4699 (M1, повторная приёмка) — **WEB-651 = NO-GO**: (1, critical) незащищённая точка записи `src/lib/videoContext/reportSnapshot.ts:210-231` — `prisma.source.upsert` с `content` в create/update без guard (`coverMeta.title` из входа видео-отчёта без ограничения) — репродуктор в `patches/0001`; (2, medium) инвентарь автора неполон как инвентарь: независимый grep нашёл 28 точек (две в `documentSessionVersionedStore.ts:305,376` — защищены), в таблице и массиве `WRITE_POINTS` 25; регекс сторожа пропускает сокращённое `content,` — потому и не поймал видео-отчёт. Чек-лист 13/17 (4 — pg без БД). Починка — 4700 (M1): guard в reportSnapshot, сторож с честным регексом/AST, инвентарь 28. Статус ← in_progress.
2026-09-23T11:37:04.699Z · coordinator[23.09 11:37Z координатор] ## 4700 (M1, GO, 10/10) — принято: `reportSnapshot.ts` защищён guard-ом; сторож точек записи переписан на AST-скан (`typescript` API): найдено 28 точек, незащищённых 0, красный на подсадной точке; инвентарь совпал с независимым (4699); репродуктор 4699 зелёный; области 58/58, typecheck 0. Ветка A2 `l115s-web651-over-ceiling` = 7 коммитов. Третья независимая приёмка — 4701. Статус ← review.
2026-09-23T11:50:47.600Z · coordinator[23.09 11:50Z координатор] ## 4701 (M1, третья приёмка) — ПРОДУКТ чист: независимый инвентарь 28 точек записи, незащищённых 0, чек-лист по продукту PASS (16/21; 5 незачтённых = pg без БД + сторож). **NO-GO по инструменту приёмки**: AST-сторож (`scripts/web651-write-point-sentinel.ts:255-268`) считает точку защищённой, если в той же функции есть вызов `assertDocumentWithinCeiling`, не проверяя (1) что аргумент guard — то же значение, что пишется, (2) что guard на достижимом пути, (3) что guard выполняется ДО записи; репродуктор показывает все три ложных PASS. Решение координатора: продуктовые патчи WEB-651 (7 коммитов) считать готовыми к кандидату l115s; сторож дорабатывается отдельно — 4702 (M1): проверка потока значения, порядка и достижимости. Статус остаётся review.
2026-09-23T12:23:34.708Z · coordinator[23.09 12:23Z координатор] ## 4702 (M1, GO, 7/7) — принято: сторож точек записи доказывает guard по трём признакам (`same-binding` — тот же биндинг/выражение, что пишется; `stmt-order` — guard раньше записи по потоку; `reachable` — не мёртвая ветка), три подсадки 4701 красные, реальные 28/28 зелёные, 3 helper-случая доказаны структурно, новых незащищённых 0. Ветка A2 `l115s-web651-over-ceiling` — продукт + сторож; WEB-651 готов в кандидат l115s (включается в сводку all4). Статус остаётся review до посадки.
2026-09-23T12:40:47.606Z · coordinator[23.09 12:40Z координатор] ## 4711 (M1, GO, 14/14) — WEB-651 перебазирован на сводку all4: 41 патч all4 лёг без конфликтов, 11 коммитов WEB-651 — 2 файла конфликтов (list-маршрут после 4655; `sourceBodyChunkStore` после изменения батча) решены с сохранением guard/read-only и правок 4652/4655; сторож AST зелёный на объединённом дереве. A2: ветка `l115s-all5` = 2dc0ee1d (52 коммита) → стендовая сборка 4717 после лестницы 2 МиБ.
2026-09-25T08:42:12.192Z · coordinator[25.09 08:42Z координатор] # Ready board comment — WEB-651
2026-09-25 — POST-QA all9 `879094713e`: **KEEP-REVIEW**.
Код реализует честный interim: документ выше 16M получает read-only authority (`src/lib/realtime/documentSessionVersionedHub.ts:362`), а exact persist отказывает по limit до записи (`src/lib/realtime/documentSessionVersionedState.ts:235-282`). CAS/revision остаются защищены. Коммиты: `23a9b1db4`, `e02d2d509`, `3aa30b569`, `929eb18d9`, `2dc0ee1d3`, плюс `25800dd4c`, `c59ee6d0f`.
Открытый конкретный критерий: чистый sentinel/adversarial proof. Targeted report дал 14 pass / 3 fail: `scripts/web651-write-point-sentinel.ts` классифицирует `src/lib/rag/documentStore.ts:111` как `UNINVENTORIED`; два reproducers падают раньше на `src/lib/ai/toolContext.ts:120` из-за auth fixture. Вернуть в работу: исправить inventory mapping и authenticated fixture, rerun `web651OverCeilingReadOnly`, `web651AdversarialPaths`, `web651-4701-sentinel-bypass`.
Траблшут/live: JSDOM banner не probeable (`scripts/postqa/dom/webChecks.mjs:720`), браузерный runbook — `scripts/postqa/l115k-postqa.mjs:596`; это отдельный staging residue и здесь не запускался. Новый агент начинает с WEB-449 → этот файл → sentinel → failing fixture; бой и секреты не трогать.
Проверка координатора (09:5xZ, all9 879094713e, M1): Подтверждаю KEEP-REVIEW: на all9 web651OverCeilingReadOnly 6/7; красный тест 3 «streamed save refuses over-ceiling text before opening a transaction» падает с 'effectful operation requires a registry-authenticated tool context' — вероятно, тест не обновлён под контекст инструментов WEB-685.
2026-09-25T09:03:58.764Z · coordinator[25.09 09:03Z координатор] 2026-09-25 — 4984 GO
Исправлено: фикстура теста сохранения сверх лимита теперь создаёт зарегистрированный контекст инструмента (buildAuthenticatedToolContext) — защита WEB-685 не ослаблена, toolContext.ts не менялся; sentinel инвентаризировал client.document.upsert в rag/documentStore.ts с обоснованием. web651OverCeilingReadOnly 7/7, sentinel 3/3, WRITE_POINTS_FOUND=28.
Волна 4984 (M1, Node 22.23.2, all9 879094713e): VERDICT=GO. Регресс WEB-685 263/263, check:web685-runtime и tool-worker-boundary зелёные. Коммиты на A2: ветка nc-build l115s-all9-green-4984 (318ab2309b WEB-681, 74b11db126 WEB-651, 3b75298e0a WEB-439), патчи /home/ubuntu/patches-4984/. Доказательства M1 ~/waves/4984ALL9GREENTESTS-evidence/ (SHA256SUMS 27 OK). Войдёт в следующую сборку (all10).
2026-09-26T12:12:21.971Z · coordinator[26.09 12:12Z координатор] 26.09 12:15Z координатор: сборка 5058 (NO-GO) сорвана дворником диска A2, он удалил рабочий каталог. Дворник исправлен: защита по метке KEEP. Интеграция перезапущена как 5061 (A2, старт 12:11:31Z) с тем же составом: e7e0cd9b + 618583ff и Linux-исправления из журнала 5058. Тикет остаётся в работе до GO сборки и деплоя на стенд.
2026-09-26T12:57:50.311Z · coordinator[26.09 12:57Z координатор] 5061 (сборка r2, 26.09 12:53Z) NO-GO. Интеграция и все Linux-исправления восстановлены, merge tree совпал с ожидаемым. Все тесты Linux прошли, checker5057 17/17. Прежний блокер (инициализация pinned Next send) устранён узким допуском по точному пути и хешу, отрицательные тесты прошли. Compile упал на новом месте: нативный модуль lightningcss linux-arm64 не загрузился. Повторить не дал порог диска 12 GiB. Координатор удалил 25 чистых worktree на A2, ветки сохранены, стало 16 GiB. Запущена 5062 (r3) с вершины 5061: узкий допуск для lightningcss, затем полная штатная цепочка. Тикет ждёт общий пакет стенда.
2026-09-26T13:38:35.175Z · coordinator[26.09 13:38Z координатор] 26.09 13:38Z: сборка интеграции 5062 NO-GO. Допуск lightningcss принят, тесты PASS. Compile упал на нативном модуле @tailwindcss/oxide. Запущена 5064: инвентарь всех нативных linux-arm64 модулей и узкие допуски разом, затем штатная цепочка. Этот тикет входит в пакет. После GO: деплой на стенд, checker5057, ступени 300/400/500, живые роли.
2026-09-26T20:36:04.491Z · coordinator[26.09 20:36Z координатор] Координатор, пост-QA 5073 на стенде 5069 (26.09 ~21:40 Дублин). Отчёт A2 /home/ubuntu/waves/5073POSTQASIXTICKETSSTAND-REPORT.md. FAIL: сверхлимитная загрузка 16 000 001 принята в очередь, но extraction даёт общий extraction_failed, текст не открыть и не экспортировать (422). Save корректно 413 document_over_ceiling. Статус review → in_progress.
2026-09-26T21:35:54.489Z · coordinator[26.09 21:35Z координатор] Волна 5077 (Astra), 26.09 21:32Z, VERDICT=NO-GO (диагноз готов, фиксы подготовлены, НЕ применены), манифест 62/62 OK.
- Индексация стенда стоит из-за конфигурации: SPEND_CONTAINMENT_MODE=enforce, а у worker нет ~20 обязательных входов (caps, attestation, egress proxy, reconcile, alert). Guard fail-closed отработал правильно.
- Старый source в readiness: устаревшие NC_RELEASE_ID/RELEASE_SOURCE_COMMIT в app-a..d.env и worker.env. Скрипт fix-stand.sh (overlay, откат rollback-stand.sh) подготовлен.
- Патчи на 5069: WEB-677 service wallet floor=0 + нулевые receipts при долге; WEB-651 отказ 413 document_over_ceiling до создания Source для TXT/MD; WEB-676/681 timeout записи документа 5s→15s (claim+upsert атомарны); egress proof интервал 61s. Тесты 179/179 → 188/188, tsc PASS, новых lint нет.
- Checker 5057: 59.999 с — порядок setInterval до startup proof; patch 0006 (stdin для jq, CLD_EXITED numeric); на живой сессии PASS span 1523 с.
- Оговорки: денежный патч WEB-677 требует живой проверки конкурентности на изолированном Postgres; критерий WEB-651 Astra искала не на этой доске — сверить; прогресс индексации (heartbeat замер 21:01Z) не исправлен.
Следующее: readiness-fix + checker → 5074-r2 → ступени; патчи → сборка + пост-QA.
2026-09-27T08:26:46.073Z · coordinator[27.09 08:26Z координатор] Пост-QA 5094 на стенде r12: FAIL. DOCX >16M UTF-16 принят, но extraction отказывает document_over_ceiling до публикации — полного текста для read-only/export нет (save-потолок 413 работает). Нужен отдельный bounded read-only import/storage путь при сохранении потолка save. Репродьюсер-тест: A2 /home/ubuntu/waves/5094POSTQAFOURR12-evidence/patches/0001 (против c0439ed2, RED на r12). Статус → in_progress, фикс-волна следующей.
2026-09-27T08:51:56.377Z · coordinator[27.09 08:51Z координатор] Фикс 5095 GO (A2 fix/5095 @ fc40dbf4, поверх r12 c0439ed2): импорт до 32M UTF-16; выше редактируемого потолка 16M — read-only, индексация явно skipped, чтение и TXT-экспорт полного текста; save-потолок не повышен. Репродьюсер 5094 GREEN, acceptance 20/20, новых падений 0, tsc/eslint чисто, миграций нет. Следом: сборка r13 (5097) → деплой на стенд → пост-QA. Статус остаётся in_progress до пост-QA.
2026-09-27T09:26:50.829Z · coordinator[27.09 09:26Z координатор] Сборка r13 (5097) NO-GO по диску A2 (STOP на пороге 7 GiB, tarball не создан); код не при чём: тесты области 0 новых падений, репродьюсеры и acceptance 20/20 зелёные. Повтор 5099 с разрешённой чисткой старых точек отката стоит в очереди за 5098.
2026-09-27T10:17:23.837Z · coordinator[27.09 10:17Z координатор] Сборка r13 (5099) GO: фикс вошёл в артефакт fc40dbf4 (sha 69bff833…), contract/fence, тесты области (0 новых падений), acceptance 20/20, runtime из tarball и boot smoke зелёные. Деплой будет один раз — r14 (r13 + прокси ролей, 5100 собирается), затем повторный пост-QA этого тикета на стенде.
2026-09-27T11:35:19.589Z · coordinator[27.09 11:35Z координатор] Волна 5102 (деплой r14 1bf2f869 на стенд 4400-r2), 27.09 11:33Z: VERDICT=NO-GO только из-за WEB-651. Стенд оставлен на r14: ready 5/5, ready/paid 5/5, реальный логин, realtime 401, checker PASS, egress нет.
WEB-651 на стенде: открытие, сохранение, повторное открытие и экспорт прошли. Но POST /api/sync тетради с _partial-ссылкой на импорт выше потолка вернул HTTP 500: mapExistingSourceRow повторно применяет потолок к неизменённому телу.
Патч: fix/5102-web651-sync @ 5046ebed (правки только в src/app/api/sync/route.ts и новом тесте). Тест red 1/4 → green 5/5, acceptance импорта 9/9, sync regression без новых падений.
WEB-676 на стенде PASS: пользовательский документ готов за 6.9 с, позиция 2/8, 6 отложенных источников.
Дальше: сборка r15 (5103) = r14 + патч с adversarial review, потом деплой и повторный пост-QA.
2026-09-27T14:00:19.385Z · coordinator[27.09 14:00Z координатор] 5109 (27.09 13:20Z, стенд r15 a095828e): синхронизация тетради исправлена (sync HTTP 200, было 500 в 5102), документ 16000029 UTF-16 открывается, сохранение отказывает 413 без потери содержимого. Пост-QA всё же NO-GO: экспорт TXT обрывается на стендовом nginx (Permission denied на /var/lib/nginx/proxy при временном файле ответа). Это настройка стенда, не код приложения: прод не затронут (там proxy_buffering off, ошибок нет). Патч proxy_max_temp_file_size 0 с регрессией RED/GREEN на настоящем nginx готов и ставится вместе с деплоем r16. Далее: 5110 сборка r16 (r15 + WEB-580 + WEB-057), затем деплой с nginx-патчем и повтор пост-QA.
2026-09-27T16:11:38.616Z · coordinator[27.09 16:11Z координатор] [27.09 16:15Z координатор] Волна 5115: r16 79bbf331 выкачен на стенд 4400-r2, VERDICT=GO (evidence SHA256SUMS OK; ready 5/5, ready/paid 5/5, реальный логин, realtime 401 без сессии, воркер стартует, миграция WEB-057 применена к стендовой БД после проверенного pg_dump, nginx-патч proxy_max_temp_file_size 0). Откат: sudo timeout 480s python3 /home/ubuntu/waves/5115-work/rollback-release.py. Пост-QA:
WEB-651 PASS: документ 16 000 029 байт, экспорт TXT 16 039 396 байт, SHA256 совпал, Permission denied в nginx 0 (причина обрыва в 5109 — временный файл nginx, исправлено патчем). evidence postqa-web651.json.
Воркер
не привязан — привязать:
curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \
-d '{"issueId":"WEB-651","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-27T08:26:53.551Z