WEB board

всеканоны и докиворкеры↗ iOS↗ Легаси
WEB-576 · Эпик · Вход · web

ЭПИК: Закон ЕС об ИИ, статья 50 — раскрытие ИИ и маркировка сгенерированного

Закрыт P1 · важно ведёт: —
Суть
## Суть одной фразой
EU AI Act ст.50: человек обязан узнать, что перед ним ИИ, не позже первого взаимодействия; сгенерированное ИИ обязано нести машинно-читаемую маркировку происхождения.

## Где мы сейчас (13.09.2026)
Код готов частично: transparencyRegistry v2, disclosure.ts, inboundConsent.ts, тесты aiActDisclosure.test.ts; классификация 12 команд редактора готова (волна 3010, writingActions.ts); карта поверхностей ИИ-контента и страница раскрытия RU/EN — волна 3588 (GO), посажены в l115i (13.09). НЕ сделано: runtime-включение раскрытия (флаг off, решение владельца не принято; точное имя флага подтвердить grep'ом transparencyRegistry.ts/disclosure.ts); first-contact раскрытие в рабочем веб-чате (пустой экран «No messages yet» — не раскрытие); машинно-читаемая маркировка (C2PA/XMP/ID3/PDF-метаданные) отсутствует полностью.

## Хронология
- 08.09 эпик; 3010 поправка тела (NO-GO = верный вердикт, каждая строка файл:строка).
- 09.09 l114d сухой прогон поймал барьер Article28 — это GDPR (WEB-575), отдельно от раскрытия Art.50.
- 12.09 мойка 3569; волна 3588 (карта поверхностей + страница раскрытия RU/EN, что из 3025-3027 уже в дереве).
- 13.09 разбор 3638.

## Карта документов и кода
- src/lib/editor/writingActions.ts (12 команд, 2 группы); src/lib/editor/downloadExport.ts (PDF без метаданных); src/lib/podcast/api.ts:1675-1677 (ID3 только как вход); src/lib/editor/exportFormats.ts:12-20 (DOCX не выгружается); src/lib/export/epub.ts:395-404, fb2.ts:239-251.
- transparencyRegistry.ts, disclosure.ts, inboundConsent.ts; тест tests/editor/ai-transparency-evidence.test.ts.

## Остаток (ответственный)
1. Подтвердить точное имя runtime-флага раскрытия Art.50 по дереву (grep transparencyRegistry.ts/disclosure.ts) — волна/координатор.
2. Решение владельца о включении runtime-раскрытия; включить через /api/feature-toggles (RuntimeConfig), не build-флаг — владелец + координатор.
3. First-contact раскрытие в веб-чате и на странице (волна 3026).
4. Машинно-читаемая маркировка на 4 пути выдачи (PDF/звук/обложки/соцсети) (волна 3027).
5. Негативный тест: удаление раскрытия/маркировки обязано ломать проверку (волна).

## Критерий закрытия
Runtime-раскрытие включено и видно при первом взаимодействии в чате и на странице; выгруженные артефакты несут машинно-читаемую маркировку (C2PA/XMP/ID3/PDF-метаданные); негативный тест стоит. Тогда эпик done.

---

## История (старый текст, сохранён ниже)

## ДЛЯ НУЛЕВОГО АГЕНТА (создан 2026-09-08)
- **Суть одной строкой:** человек обязан узнать, что перед ним ИИ, не позже первого взаимодействия; сгенерированное ИИ обязано нести машинно-читаемую маркировку.
- **Откуда взялось:** внешний рецензент 08.09; владелец подтвердил разделение на две линии.
- **Срок:** на переходный период НЕ рассчитывать — внешней беты ещё не было, значит готовность нужна ДО первого внешнего запуска, а не по послаблению для систем, размещённых на рынке ранее.
- **Текущее состояние:** три волны отданы 08.09 ~23:10Z, база — боевая линия l113z `30000baf9939f94d062b0e216f023a11faa4af3f`.
- **Свой отдельный вердикт:** AI ACT ARTICLE 50 READY / CONDITIONAL / NO-GO. Не смешивать с вердиктом линии GDPR (WEB-575).

## Что уже установлено по коду (координатор, 08.09)
- Телефония на SIP и обратный вызов в Telegram раскрытие ДАЮТ — считать существующими соответствующими путями.
- Веб-чат и публичная страница обмена раскрытия при первом взаимодействии НЕ дают. Слова «AI assistant» найдены только на странице ОШИБКИ `src/app/share/[slug]/not-found.tsx:6`, в настройках телефона и при создании агента — то есть там, где человек уже внутри.
- Машинно-читаемой маркировки происхождения НЕТ нигде: ни C2PA/Content Credentials, ни XMP, ни тегов в звуке. При выгрузке PDF `src/lib/editor/downloadExport.ts` не выставляет НИ ОДНОГО поля метаданных — ни заголовка, ни автора, ни производителя.
- Сильная сторона: команды редактора объявлены типизированным реестром `src/lib/editor/writingActions.ts` — двенадцать команд, две группы (`edit`/`voice`), плюс отдельный список `rewriteWriterCommands` и функция `isRewriteWriterCommand`. Система уже различает переписывание и прочее.
- Клонирования голосов реальных людей нет; распознавания эмоций нет; публикация в соцсеть идёт через показ и правку пользователем.

## Волны
| Волна | Что делает | Хост |
|---|---|---|
| 3025 | Реестр прозрачности + классификация 12 команд редактора В КОДЕ (команда без класса не собирается) | M4 |
| 3026 | Раскрытие при первом взаимодействии: веб-чат, публичная тетрадь, виджет; получатель ссылки получает СВОЁ раскрытие | A2 |
| 3027 | Единый слой машинно-читаемой маркировки + адаптеры на 4 пути выдачи (документы/PDF, звук, обложки, соцсети) | A2 |

## Классификация действий редактора (предварительно, уточняет волна 3025)
- `MARK_REQUIRED` — создаётся новый текст: «продолжить мысль», «извлечь суть».
- Кандидат в `STANDARD_EDITING_EXEMPT` — обычная правка языка: «полировка языка».
- Отдельная оценка по каждому: короче, длиннее, плотнее, проще, четыре тона, перевод — меняют ли существенно вход или смысл.

## Сдача
`AI TRANSPARENCY REGISTER`, список поверхностей, доказательства интерфейса и звука, реализация маркировки, промаркированные образцы выгрузки, классификация действий редактора, тесты, итоговый вердикт.

## KNOWN ISSUES / ТРАБЛШУТИНГ
- Симптом: раскрытие «есть», но человек его не видит → проверка: где именно и когда показывается → причина: текст в подвале или на странице ошибки → лечение: волна 3026 требует показ до или в момент первого взаимодействия.
- Симптом: маркировку завтра тихо уберут → проверка: негативный тест → лечение: в обеих волнах главный негативный тест — удаление раскрытия или маркировки обязано ломать проверку.

---

## история (тело до 13.09.2026)

## ДЛЯ НУЛЕВОГО АГЕНТА (создан 2026-09-08)
- **Суть одной строкой:** человек обязан узнать, что перед ним ИИ, не позже первого взаимодействия; сгенерированное ИИ обязано нести машинно-читаемую маркировку.
- **Откуда взялось:** внешний рецензент 08.09; владелец подтвердил разделение на две линии.
- **Срок:** на переходный период НЕ рассчитывать — внешней беты ещё не было, значит готовность нужна ДО первого внешнего запуска, а не по послаблению для систем, размещённых на рынке ранее.
- **Текущее состояние:** три волны отданы 08.09 ~23:10Z, база — боевая линия l113z `30000baf9939f94d062b0e216f023a11faa4af3f`.
- **Свой отдельный вердикт:** AI ACT ARTICLE 50 READY / CONDITIONAL / NO-GO. Не смешивать с вердиктом линии GDPR (WEB-575).

## Что уже установлено по коду (координатор, 08.09)
- Телефония на SIP и обратный вызов в Telegram раскрытие ДАЮТ — считать существующими соответствующими путями.
- Веб-чат и публичная страница обмена раскрытия при первом взаимодействии НЕ дают. Слова «AI assistant» найдены только на странице ОШИБКИ `src/app/share/[slug]/not-found.tsx:6`, в настройках телефона и при создании агента — то есть там, где человек уже внутри.
- Машинно-читаемой маркировки происхождения НЕТ нигде: ни C2PA/Content Credentials, ни XMP, ни тегов в звуке. При выгрузке PDF `src/lib/editor/downloadExport.ts` не выставляет НИ ОДНОГО поля метаданных — ни заголовка, ни автора, ни производителя.
- Сильная сторона: команды редактора объявлены типизированным реестром `src/lib/editor/writingActions.ts` — двенадцать команд, две группы (`edit`/`voice`), плюс отдельный список `rewriteWriterCommands` и функция `isRewriteWriterCommand`. Система уже различает переписывание и прочее.
- Клонирования голосов реальных людей нет; распознавания эмоций нет; публикация в соцсеть идёт через показ и правку пользователем.

## Волны
| Волна | Что делает | Хост |
|---|---|---|
| 3025 | Реестр прозрачности + классификация 12 команд редактора В КОДЕ (команда без класса не собирается) | M4 |
| 3026 | Раскрытие при первом взаимодействии: веб-чат, публичная тетрадь, виджет; получатель ссылки получает СВОЁ раскрытие | A2 |
| 3027 | Единый слой машинно-читаемой маркировки + адаптеры на 4 пути выдачи (документы/PDF, звук, обложки, соцсети) | A2 |

## Классификация действий редактора (предварительно, уточняет волна 3025)
- `MARK_REQUIRED` — создаётся новый текст: «продолжить мысль», «извлечь суть».
- Кандидат в `STANDARD_EDITING_EXEMPT` — обычная правка языка: «полировка языка».
- Отдельная оценка по каждому: короче, длиннее, плотнее, проще, четыре тона, перевод — меняют ли существенно вход или смысл.

## Сдача
`AI TRANSPARENCY REGISTER`, список поверхностей, доказательства интерфейса и звука, реализация маркировки, промаркированные образцы выгрузки, классификация действий редактора, тесты, итоговый вердикт.

## KNOWN ISSUES / ТРАБЛШУТИНГ
- Симптом: раскрытие «есть», но человек его не видит → проверка: где именно и когда показывается → причина: текст в подвале или на странице ошибки → лечение: волна 3026 требует показ до или в момент первого взаимодействия.
- Симптом: маркировку завтра тихо уберут → проверка: негативный тест → лечение: в обеих волнах главный негативный тест — удаление раскрытия или маркировки обязано ломать проверку.
Лента
2026-09-08T22:19:08.912Z ·
Волны отданы 08.09 23:10Z на базе боевой линии l113z 30000baf9939f94d062b0e216f023a11faa4af3f: 3025 реестр прозрачности и классификация команд редактора (M4), 3026 раскрытие при первом взаимодействии (A2), 3027 единый слой маркировки происхождения (A2). Все три прошли гард-проверку. Отдельно зафиксировано: получатель ссылки на общую тетрадь — НОВЫЙ человек и обязан получить своё раскрытие; отдельное предупреждение для микрофона не требуется, если чат уже объявлен как ИИ; автопубликация в соцсети не включается, поток «сгенерировать → показать → дать поправить → опубликовать» сохраняется.
2026-09-08T22:22:14.675Z ·
ПОПРАВКА К ТЕЛУ ТИКЕТА по итогам волны 3010 (VERDICT=NO-GO — верный вердикт: он означает «продукт в текущем виде требованиям не отвечает», а не «работа плохая»). Проверено по коду линии l113y `53ffa358b`, каждая строка со ссылкой файл:строка.

НЕВЕРНО БЫЛО В МОЁМ ПЕРВОНАЧАЛЬНОМ ТЕЛЕ ТИКЕТА: я написала, что публичная страница обмена раскрытия не даёт. Даёт. На рабочей странице (`src/app/share/[slug]/page.tsx:29-47`, виджет `EmbedWidgetShell`) в ПОСТОЯННОЙ ШАПКЕ стоит «AI assistant». Я нашла эти слова на странице ОШИБКИ `not-found.tsx:6` и ошибочно заключила, что на рабочей их нет.

ПОДТВЕРЖДЕНО:
- В рабочем веб-чате приложения раскрытия при первом взаимодействии НЕТ. Пустой экран: «No messages yet» / «Start the conversation by asking a question about your sources»; имя говорящего — «NotebookLM Clone». Это не раскрытие.
- Звук подкаста: нет C2PA/Content Credentials, XMP, ID3-меток происхождения (`src/lib/podcast/api.ts:1675-1677`; ID3 встречается только как вход парсера длительности).
- Обложка: нет C2PA, XMP, EXIF и любого встроенного признака ИИ; успешный путь возвращает URL, запасной сохраняет исходный SVG.
- PDF: нет ни заголовка, ни автора, ни производителя от приложения — только умолчания библиотеки pdf-lib.
- Зависимости для машинно-читаемой маркировки в package.json НЕТ вообще.

НОВЫЙ ФАКТ В НАШУ ПОЛЬЗУ: DOCX редактор НЕ выгружает. Форматы: txt, md, html, pdf, epub, fb2, mobi (`src/lib/editor/exportFormats.ts:12-20`). Значит вопрос рецензента про метаданные DOCX не применим — такого пути нет. EPUB и FB2 несут заголовок и необязательного автора, но поля происхождения ИИ не добавляют (`src/lib/export/epub.ts:395-404`, `src/lib/export/fb2.ts:239-251`).

КЛАССИФИКАЦИЯ КОМАНД РЕДАКТОРА готова полностью, каждая со ссылкой на свою системную инструкцию: «продолжить мысль» и «извлечь суть» — создание нового текста; «полировка языка» — коррекция (и входит в подмножество переписывания); короче/длиннее/плотнее/проще/тона/перевод — переписывание с отдельной оценкой.

Отчёт целиком: /Users/milamarty/waves/AITRANSPARENCYEVIDENCE-REPORT.md (M4), бандл AITRANSPARENCYEVIDENCE.bundle, тест зафиксирован в tests/editor/ai-transparency-evidence.test.ts — чтобы ответ завтра не разошёлся с кодом молча.

Дыры закрывают волны 3026 (раскрытие в веб-чате) и 3027 (единый слой маркировки на четыре пути выдачи).
2026-09-09T01:39:28.766Z · coordinator
[09.09 01:39Z координатор] СУХОЙ ПРОГОН ЛИНИИ l114d ПОЙМАЛ БОЕВУЮ ПОЛОМКУ В БАРЬЕРЕ ARTICLE 28. Посадка без этого закрыла бы платный периметр на живом проде.

Симптом. Сухой прогон кандидата на :3011, `/api/ready/paid`:
```
"paidReady": false, "posture": "enforce_ready", "mode": "enforce",
"failures": [{"key": "egress_boundary",
  "detail": "paid egress proxy liveness probe has not passed; Article28ExternalCallUnregisteredError: Article 28 register is missing external provider paths: unregistered_external_host"}]
```
При этом `accountingHealth.ready = true`, незакрытых расчётов 0 — учёт был здоров, ломался именно выход наружу.

Корень, файл:строка. `src/lib/legal/article28Register.ts`:
- `article28ProviderForUrl()` возвращает `null` В ДВУХ РАЗНЫХ СЛУЧАЯХ: (а) адрес — петля (`localhost`, `127.0.0.1`, `[::1]`), то есть вызов вообще не внешний; (б) хост внешний, но его нет в реестре Article 28.
- `assertArticle28FetchDestination()` трактовал оба `null` одинаково и бросал `Article28ExternalCallUnregisteredError`.
- Следствие: ЛЮБОЙ `fetch` на петлю умирал. В том числе проба живости платного egress-прокси, которая ходит на `SPEND_EGRESS_PROXY_HEALTH_URL = http://127.0.0.1:35083/health`. Барьер ставится в `src/instrumentation.ts:110-111`, то есть на каждом процессе.

Лечение (коммит aa3ee917c178a962ef514554a8bd1d10af5c98ed): отдельная функция `article28IsLoopbackDestination()` и ранний возврат ДО броска. Негативный контроль сохранён — внешний незарегистрированный хост по-прежнему отклоняется.

Доказательство: `src/lib/legal/__tests__/article28Register.test.ts` — 10 из 10, включая новый тест «the process fetch barrier lets loopback destinations through untouched». Он проверяет три петлевых адреса (в том числе именно `http://127.0.0.1:35083/health`), что транспорт их видит, и тут же — что `https://new-vendor.example.test/api` всё ещё отклоняется, а число прошедших через транспорт вызовов не выросло.

ПОЧЕМУ ЭТО НЕ ПОЙМАЛОСЬ РАНЬШЕ. Существовавший тест барьера («rejects closed and unregistered external destinations before transport») проверял только внешние адреса. Петля не проверялась вообще — ни одного положительного случая. Правило в ранбук: у барьера, который что-то запрещает, обязан быть тест на то, что он ПРОПУСКАЕТ, а не только на то, что он режет.

ЛОВУШКА ПОСАДКИ (в ранбук): цикл ожидания здоровья в land-скрипте писал `st=$(curl ...)` под `set -e`. При обращении раньше, чем бэкенд успел занять порт, curl возвращает 7, и весь этап падал с RC=7, хотя служба поднималась нормально. Добавлено `|| true` во все три цикла ожидания.
2026-09-09T02:35:49.740Z · coordinator
[09.09 02:35Z координатор] 🔴 P0 ИНЦИДЕНТ: ЧАТ ОТВЕЧАЛ 500 ВСЕМ 32 МИНУТЫ (09.09 02:00–02:32Z). Прод откачен на l114c, чат живой, проверено живым запросом (http=200, ответ получен).

СИМПТОМ. После посадки l114d (01:59Z) и затем l114e (02:26Z) журнал прода:
```
Error in global chat [server]: Error [Article28PathClosedError]: Article 28 path closed:
confirmed contract and processing controls are required. provider=openai
[nc-a1][paid-operation-access] {"route":"global-chat","status":500,"clientClass":"browser",...}
```
Все 44 кейса батареи ролей на l114e упали с `!http_200`. Именно батарея и обнаружила аварию — ни мониторинг, ни посадка её не увидели.

КОРЕНЬ. Коммит `1d70754c7 feat(legal): close unconfirmed Article 28 paths` вооружил барьер сразу при посадке. В `src/lib/legal/article28Register.ts` запись провайдера `openai` заведена как `closedProvider(...)`: договор и условия обработки помечены как НЕ подтверждённые. `isArticle28PathOpen()` требует `contract.status==='confirmed'`, `processingTerms.status==='confirmed'`, `subprocessors.status==='confirmed'`; `assertArticle28PathEnabled()` бросает `Article28PathClosedError` — и любой вызов ИИ умирает.

Барьер написан ПРАВИЛЬНО: он честно фейлится в закрытую. Ошибка не в нём, а в том, что он приехал вооружённым, без флага, при заведомо неподтверждённом реестре.

ПОЧЕМУ СУХОЙ ПРОГОН НЕ ПОЙМАЛ. Он проверяет `/api/health`, `/api/ready` и `/api/ready/paid` — все три были зелёными, потому что барьер срабатывает только на настоящем вызове ИИ. Ни одного живого запроса в чат посадка не делала.

ЧТО СДЕЛАНО СРАЗУ:
1. Откат на l114c скриптом `/home/ubuntu/rollback-to-l114c.sh` (переписывает пути в nc-a1, nc-a1-b, nc-a1-indexing, nc-a1-extraction и во всех drop-in, воркеры первыми, потом веб, потом второй бэкенд через контроллер апстрима). Время отката — 3 минуты. Корень 200 ×4, ready true, paid enforce_ready, ошибок барьера ноль.
2. Написана и вшита в стадию dryrun живая проба чата: `/home/ubuntu/dryrun-chat-probe.sh <порт>` — вход фикстурой через csrf+credentials, POST `/api/chat-global`, требуется 200, иначе посадка останавливается с кодом 31. Проверена на живом проде: `ЧАТ-ПРОБА: http=200`.
3. Поставлена волна **3155**: перевести барьер под флаг `ARTICLE28_RUNTIME_ENFORCEMENT` (по умолчанию выключен) с гранулярностью по провайдеру, сохранить реестр как отчёт, добавить сквозной тест маршрута чата.

ВОПРОС ВЛАДЕЛЬЦУ, отправлен в Telegram 02:35Z. Барьер прав по существу: пока договор с обработчиком не подтверждён, данные людей туда идти не должны. Но по реестру не подтверждены OpenAI и остальные внешние обработчики — вооружённый барьер выключает продукт целиком. Статус «договор подтверждён» проставляет только владелец. Принятое до его ответа решение: барьер едет выключенным под флагом, реестр остаётся отчётом, вооружаем по одному провайдеру по мере подтверждения договоров.

## KNOWN ISSUES / ТРАБЛШУТИНГ

| Симптом | Проверка | Причина (файл:строка) | Лечение | Ссылки |
|---|---|---|---|---|
| Чат 500 у всех, в журнале `Article28PathClosedError provider=openai`, при этом `/api/ready` и `/api/ready/paid` зелёные | `cat ~/.r9-fixture-password.txt \| bash ~/dryrun-chat-probe.sh 3010` | `src/lib/legal/article28Register.ts` — запись `openai` заведена `closedProvider(...)`, `isArticle28PathOpen()` требует три `confirmed` | До волны 3155 — откат линии. После — держать `ARTICLE28_RUNTIME_ENFORCEMENT` выключенным, пока владелец не подтвердит договоры | rollback-to-l114c.sh |
| Батарея ролей даёт 0 из 50 за 90 секунд вместо 40 минут | `!http_200` во всех кейсах | Чат отвечает не 200. Это не регресс ролей | Чинить чат, батарею перечитывать после | — |
2026-09-12T22:17:55.136Z · coordinator
[12.09 22:17Z координатор] МОЙКА 12.09 (3569-wash-g4-compliance-process): эпик EU AI Act ст.50. Код в дереве есть (transparencyRegistry v2, disclosure.ts, inboundConsent.ts, тесты aiActDisclosure), но runtime-раскрытие флагом не включено, волны 3025–3027 открыты. Эпик — не DONE. Статус не меняю: KEEP.
Остаток: Эпик с открытыми дочерними волнами (3025–3027); Барьер Article 28 флагом off — runtime-раскрытие не включено; Решение владельца о включении не принято
Отчёт: /Users/milamarty/waves/3569WASH*-REPORT.md (M4), копия nc-ops-scripts/shift-20260912-resume/wash-20260912/collected/. Проверка по исходнику прода l115g (9c8a9762).
2026-09-12T23:18:35.927Z · coordinator
[12.09 23:18Z координатор] ВЗЯТО В РАБОТУ 12.09 23:17Z (владелец: «мойка = брать тикеты в работу»): волна 3588-gdpr-aiact-remainders (DeepSeek, M4): что из 3025–3027 в дереве, карта поверхностей ИИ-контента → маркировка, текст раскрытия RU/EN. Сдача — бандл + отчёт, комментарий сюда по вердикту.
2026-09-12T23:40:17.786Z · coordinator
[12.09 23:40Z координатор] Волна 3588 (DeepSeek, M4) — GO: карта поверхностей ИИ-контента → есть ли маркировка → где добавить; страница пользовательского раскрытия (RU/EN) в docs/; что из 3025–3027 уже в дереве. Включение runtime-раскрытия — решение владельца. refs/waves/3588.
2026-09-13T08:53:35.448Z · coordinator
[13.09 08:53Z координатор] РАЗБОР 13.09 (волна 3638, DeepSeek): Есть закон: если с человеком разговаривает робот, человек должен это знать, и всё, что робот создал, должно быть помечено. Мы уже сделали большую часть: страницу, где объясняем, что это ИИ, и список всех мест, где это надо показать. Осталось два шага. Первый — решить, когда это включить (это решает владелец). Второй — включить одну настройку и проверить, что объяснение видно в чате и на странице, а на выгруженных файлах стоит пометка. Я написал порядок: как включить и что проверить, и добавил проверку, что пометку нельзя тихо убрать. Карточка ещё не готова, поэтому статус оставляем «в работе».
Остаток: Runtime-включение раскрытия не сделано — флаг выключен, решение владельца не принято.; Точное имя runtime-флага раскрытия Art.50 не в входах — нужна проверка по дереву (grep transparencyRegistry.ts / disclosure.ts из волны 3588); ARTICLE28_RUNTIME_ENFORCEMENT — это барьер Article 28 (GDPR), отдельный от раскрытия.; Машинно-читаемая маркировка происхождения ещё не готова (нет C2PA/XMP/ID3/PDF-метаданных).; First-contact раскрытие в рабочем веб-чате ещё не готово (пустой экран «No messages yet» — не раскрытие).
Предложение: Код готов: transparencyRegistry v2, disclosure.ts, inboundConsent.ts, тесты aiActDisclosure.test.ts; волна 3588 подготовила карту поверхностей и страницу раскрытия. Включение — runtime-флаг через /api/feature-toggles (RuntimeConfig), не build-флаг (в prod-env l115f нет disclosure/art50 ключа). Порядок: (0) подтвердить имя ключа по дереву; (1) подтвердить карту поверхностей на l115i; (2) включить ф
Материалы: shift-20260912-resume/colN/ (RESULT.md). Статус не меняю.
2026-09-13T10:37:39.953Z · coordinator
[13.09 10:37Z координатор] Мойка доски, волна 3654. RETURN. Реестр прозрачности/классификация команд/страница раскрытия готовы (волна 3588 в l115i); runtime-раскрытие off (решение владельца), first-contact раскрытие в чате и машинно-читаемая маркировка C2PA/XMP/ID3/PDF не сделаны. Статус не меняю.
2026-09-13T10:59:18.717Z · coordinator
[13.09 10:59Z координатор] Волна 3661 (GO, refs/waves/3661 = 66dbb888) поправила карточку фактами, и два пункта из трёх оказались не такими, как записано в теле.
1. Рантайм-признака, который гейтит раскрытие по статье 50, в дереве НЕТ. Раскрытие безусловно смонтировано на всех двенадцати обязательных поверхностях ещё до этой волны. То есть «включить флаг» — нечего включать, оно уже включено всегда.
2. Раскрытие при первом контакте правок не потребовало: уже сделано и покрыто тестами в основе линии.
3. Настоящая дыра была не в PDF, как записано в теле карточки, а в книжных форматах: признак происхождения встраивался в разметку, но терялся при сборке книжного контейнера. Исправлено, добавлен общий слой для книжных форматов; третий формат унаследовал фикс как обёртка.
Вывод: решения владельца по «включению» здесь не требуется — требовалось исправление кода, и оно сделано.
2026-09-13T15:36:06.960Z · coordinator
[13.09 15:36Z координатор] Волна 3723 (NO-GO по эпику, но остаток стал узким и техническим) сверила состояние ПО ДЕРЕВУ кандидата, а не по отчётам.
Цифры: в реестре прозрачности 62 поверхности. Из них 18 отнесены к обязательным — прямой диалог человека с искусственным интеллектом. Раскрытие есть на ВСЕХ восемнадцати, ни одной с пометкой «отсутствует». Ещё 3 поверхности — служебные адаптеры без собственного экрана, там раскрытие обязан делать вызывающий клиент, и это осознанное решение, а не пропуск.
Подтверждено также, что волна 3661 правильно закрыла оба пункта, которые в карточке числились открытыми.
Эпик пока не закрываю: остаток назван волной точно, он технический, и я поставлю его следующим шагом.
2026-09-13T17:37:05.373Z · 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:49.325Z · 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-13T21:07:16.543Z · coordinator
[13.09 21:07Z координатор] ВОЗВРАЩАЮ ТИКЕТ В РАБОТУ. Я закрыл его преждевременно, независимая приёмка (волна 3743, другой исполнитель) это поймала и поставила `VERDICT=NO-GO`: `WEB-576=OK WEB-571=BAD WEB-583=BAD WEB-325=BAD`.

Что приёмка ПОДТВЕРДИЛА (чтобы не переделывали лишнего): все три заявленные «настоящие» до-фиксные пары честные — на до-фиксном коде пробник действительно краснеет, на релизном исходнике зеленеет, зелёного до фикса не найдено. Врущих проверок нет. Ошибка не в пробнике, а в ОБЪЁМЕ: он проверяет не весь путь, ради которого заводился тикет, а я закрыл тикеты так, будто проверяет.

Разбор по тикетам:
- **WEB-576 — остаётся закрытым.** Проверены все три формата (EPUB, FB2, MOBI), до-фиксная пара настоящая: до фикса `ncai.provenance` отсутствует во всех трёх, после — есть во всех трёх. Заявленный объём покрыт.
- **WEB-571 → review.** Проверен ТОЛЬКО путь запасного варианта (копирование в буфер + видимый тост). Настоящего `navigator.share` в jsdom нет, то есть главный путь — нативное меню обмена, ради которого тикет и заводился, — не проверен ничем. Нужна браузерная проба основного пути.
- **WEB-583 → review.** У пробника НЕТ настоящей пары: в до-фиксном коммите `11a076721^` вспомогательной функции `shouldShowIndexingDeferredNotice` ещё не существует, пробник получает ошибку сборки и превращает её в «не доказано». Ошибка сборки — это не наблюдение старого поведения. Плюс из трёх дефектов тикета проверяется только первый. Нужен адаптер к настоящему до-фиксному `updateDocument`, а не к функции, появившейся вместе с фиксом.
- **WEB-325 → review.** Проверено только сохранение рубильников при очистке localStorage. Запрет вставок ИИ в месте вызова (`EditorModal.tsx`) — то есть сам смысл «рубильник действительно блокирует правки ИИ» — не проверяется.

Почему записываю это подробно: сегодня я уже один раз поднял ложную тревогу по WEB-467 из-за неверного допущения инструмента, а теперь — обратная ошибка: принял частичную проверку за полную. Оба раза спасала независимая приёмка. Правило для следующего агента: вердикт пробника закрывает тикет только если покрыт ЗАЯВЛЕННЫЙ В ТИКЕТЕ путь целиком, и до-фиксная пара краснеет по НАБЛЮДЕНИЮ СТАРОГО ПОВЕДЕНИЯ, а не по ошибке сборки.
2026-09-14T12:07:41.775Z · coordinator
[14.09 12:07Z координатор] WEB-576 — в выгруженных документах нет пометки, что текст сделан с ИИ
Обновление от 2026-09-14. Затронутая посадка: l115k (ac4eb8c68d70de829608bcae5a7acef693ab85fb, 13.09 17:27:44Z).
Карточка написана для человека, который открывает её впервые и не имеет ни журнала смены, ни переписки.

1. ЧТО БЫЛО СЛОМАНО

Пользователь выгружает документ в книжном формате — и в файле нет пометки о том, что текст создан с участием искусственного интеллекта. По закону такая пометка обязана быть.

2. КАК НАШЛИ И ПОЧЕМУ НЕ ПОЙМАЛИ РАНЬШЕ

Нашла волна 3661 (`refs/waves/3661` = `66dbb888`) СВЕРКОЙ ПО ДЕРЕВУ, а не проверкой одного места.
Главное: ТЕЛО ТИКЕТА УКАЗЫВАЛО НЕ ТУДА. В карточке была записана дыра в PDF. Настоящая дыра оказалась в КНИЖНЫХ ФОРМАТАХ. Плюс выяснилось, что рантайм-признака раскрытия в дереве НЕТ ВООБЩЕ — раскрытие смонтировано БЕЗУСЛОВНО на всех двенадцати поверхностях.
Почему не поймали раньше: искали там, где написано в карточке. Пока никто не прошёл по дереву целиком, ошибочный адрес просто переносился из отчёта в отчёт.

3. ЭВОЛЮЦИЯ, ВКЛЮЧАЯ ТУПИКИ

3.1. Волна 3723 (эпик закона об ИИ) вернула NO-GO ПО ЭПИКУ, но именно этот отказ сузил остаток до проверяемого: в реестре прозрачности 62 поверхности, из них 18 обязательных; раскрытие есть НА ВСЕХ ВОСЕМНАДЦАТИ, ни одной с пометкой «отсутствует»; 3 служебных адаптера осознанно без своего экрана.
NO-GO по эпику при этом НЕ означал, что раскрытие сломано — он означал, что ОСТАТОК ЭПИКА не закрыт. Эти вещи легко перепутать.

3.2. Волна 3727 (`refs/waves/3727` = `9a893cf68`) закрыла ровно то, что закрывается кодом.

3.3. ВАЖНОЕ ОТЛИЧИЕ ОТ СОСЕДНИХ ТИКЕТОВ. Координатор закрыл четыре тикета по вердикту DOM-пробника, и независимая приёмка 3743 вернула ТРИ из четырёх. ЭТОТ ТИКЕТ — ЕДИНСТВЕННЫЙ, КОТОРЫЙ ПРИЁМКА ОСТАВИЛА ЗАКРЫТЫМ. Причина именно та, которой не хватило остальным: пара «до/после» НАСТОЯЩАЯ.

4. ЧТО СДЕЛАЛИ В ИТОГЕ

Волна 3727 (`9a893cf68`) влита в кандидат линии l115k; линия `ac4eb8c68d70de829608bcae5a7acef693ab85fb` посажена 13.09 17:27:44Z. Комментарий о посадке разослан в этот тикет в числе прочих.

5. ЧЕМ ДОКАЗАНО И ГРАНИЦЫ ЗАЯВЛЕНИЯ

ДОКАЗАНО:
  Пара «до/после» настоящая и проверена независимой приёмкой 3743: на коммите, предшествующем `66dbb8882`, признака `ncai.provenance` НЕТ ВО ВСЕХ ТРЁХ форматах (EPUB, FB2, MOBI); на релизе он ЕСТЬ во всех трёх.
  Сверка по дереву: раскрытие присутствует на всех 18 обязательных поверхностях из 62.
  Пост-QA линии l115k (волна 3777) подтвердил.

ГРАНИЦЫ:
  Доказано поведение прод-кода офлайн, на коммите, работающем в проде. ВЫГРУЗКА ЧЕЛОВЕКОМ ИЗ БРАУЗЕРА НЕ ПРОВЕРЯЛАСЬ.
  Три служебных адаптера ОСОЗНАННО оставлены без своего экрана раскрытия — это решение, а не пропуск.

6. ЧТО ОСТАЛОСЬ ОТКРЫТЫМ

Блокирующего по этому тикету не осталось. Остаток эпика закона об ИИ, из-за которого волна 3723 дала NO-GO, к этому тикету не относится и живёт отдельно.

7. TROUBLESHOOTER — ЕСЛИ ПОМЕТКА СНОВА ПРОПАДЁТ

Шаг 1. Выгрузить документ и искать признак `ncai.provenance` в файле. Проверять ВСЕ ТРИ книжных формата: EPUB, FB2, MOBI.

Шаг 2. НЕ начинать с PDF. Тело тикета исторически называло PDF, и это было неверно: настоящая дыра была в книжных форматах. PDF — другой путь.

Шаг 3. Если признака нет в одном формате из трёх — это регресс конкретного экспортёра, а не общего механизма: раскрытие смонтировано безусловно, отдельного рантайм-признака, который мог бы его выключить, в дереве нет.

Шаг 4. Годный якорь для пары «до/после»: коммит, предшествующий `66dbb8882` — на нём признака нет ни в одном из трёх форматов.
2026-09-15T01:25:03.961Z · 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 нет.

**Это эпик** — статус эпика не меняю по посадке, он живёт по своим детям. Пост-QA делается по детям, а не по эпику.
2026-09-15T22:04:50.059Z · coordinator
ДЛЯ ТИКЕТА WEB-576 - сводка под нулевого агента (составлено 2026-09-15, read-only)

Симптом. Пользователь выгружает документ в книжном формате - и в файле нет пометки о том, что текст создан с участием ИИ. По закону (EU AI Act, ст. 50) такая пометка обязана быть.

Главная отмена - тело указывает не туда. Тело говорит: "НЕ сделано: runtime-включение раскрытия (флаг off, решение владельца не принято); first-contact раскрытие в рабочем веб-чате; машинно-читаемая маркировка C2PA/XMP/ID3/PDF". Волна 3661 (2026-09-13T10:59:18.717Z, GO, refs/waves/3661 = 66dbb888) опровергла три пункта из трёх:
1. Рантайм-признака, который гейтит раскрытие по ст. 50, в дереве НЕТ. Раскрытие безусловно смонтировано на всех двенадцати обязательных поверхностях ещё до этой волны. "Включить флаг" - нечего включать, оно уже включено всегда.
2. Раскрытие при первом контакте правок не потребовало - уже сделано и покрыто тестами в основе линии.
3. Настоящая дыра была не в PDF, как записано в теле, а в книжных форматах: признак происхождения встраивался в разметку, но терялся при сборке книжного контейнера. Исправлено, добавлен общий слой для книжных форматов; третий формат унаследовал фикс как обёртка.
Вывод волны дословно: "решения владельца по "включению" здесь не требуется - требовалось исправление кода, и оно сделано".

Проверено по дереву, а не по отчётам. Волна 3723 (2026-09-13T15:36:06.960Z, NO-GO по эпику, остаток узкий): в реестре прозрачности 62 поверхности, из них 18 обязательных (прямой диалог человека с ИИ). Раскрытие есть на всех восемнадцати, ни одной с пометкой "отсутствует". Ещё 3 поверхности - служебные адаптеры без собственного экрана: там раскрытие обязан делать вызывающий клиент, и это осознанное решение, а не пропуск.

Чем доказано живьём. 2026-09-13T20:18:49.325Z: пост-QA раунд 2, инструмент scripts/postqa/l115k-postqa-dom.mjs (волна 3742), прогон координатора против исходника коммита, который сейчас в проде (ac4eb8c68d70de829608bcae5a7acef693ab85fb, отдельный worktree wt-postqa-release), результат /tmp/l115k-postqa-dom.json на A1. WEB-576 - маркер происхождения ИИ переживает выгрузку EPUB/FB2/MOBI - PROVEN. До-фиксная пара настоящая: до фикса ncai.provenance отсутствует во всех трёх, после - есть во всех трёх (2026-09-13T21:07:16.543Z, независимая приёмка 3743 подтвердила честность пары, WEB-576=OK).

Посадка. 2026-09-13T17:37:05.373Z: линия l115k, источник ac4eb8c68d70de829608bcae5a7acef693ab85fb, артефакт me2-standalone-linux-arm64-ac4eb8c68-20260913T165733Z sha256 eafbeb5146ddf0b498f82d608ddd30d15053d23156b43603dfb88dfe71aaebed, релиз arm64-l115k-20260913T165733Z, переключение 13.09 17:27:44Z; откат sudo python3 /home/ubuntu/transition-l115k.py rollback -> l115j (133fe00c). 2026-09-15T01:25:03.961Z: работа вошла в посадку l115o (68e25d8df..., с 00:56Z 15.09).

Чего в карточке НЕТ - и это пробел. Датированного закрывающего вердикта на l115o нет: последний содержательный факт - доказательство на линии l115k от 13.09, а закрывающий комментарий - шаблон "требуется пост-QA" от 2026-09-15T01:25:03.961Z. Плюс поле доказательств пусто, и полных путей к отчётам волн 3661/3723/3742 в карточке не приведено.

Первый шаг нулевого агента (2 минуты). Открыть выгрузку в EPUB/FB2/MOBI с текущей линии l115o (68e25d8df...) и проверить наличие ncai.provenance в контейнере - тест scripts/postqa/l115k-postqa-dom.mjs уже переносим, менять сценарии не нужно. Если маркер на месте - дописать в карточку датированную расписку с путём к результату и снять из тела опровергнутые пункты, иначе следующий агент снова пойдёт включать несуществующий флаг.
Воркер
не привязан — привязать: curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \ -d '{"issueId":"WEB-576","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-13T20:18:56.142Z