WEB-584 · Дефект · — · web
P1 [чат]: инструменты не вызываются — на «сколько ехать» и «погода» чат отвечает «не могу подтвердить по источникам» вместо честного «путь провайдера закрыт»
Закрыт
P1 · важно
ведёт: —
Суть
---
## Эволюция 09.09 (вечер) — полный след для нулевого агента
**Живой прод:** l114u `54243a5cff19ef2bacf2531a0951b7bb82a71633`, посажен 09.09 ~20:0xZ. Откат = l114t `3b1a451cf6cf5b300bd32ce75c9304098448a308`.
**Расписки линий:** `L114S-RELEASE-RECEIPT.md`, `L114T-RELEASE-RECEIPT.md` — лежат в очередях волн на A1/A2/M4 и у security lead в `~/audit/inbox` на M1.
**Обзорный документ эпика энтерпрайза:** https://bugs.wool2.online/labs/enterprise-ent093-20260909.html
**Паспорт, топология парка (добавлен Нео, исправлена строка M4):** https://bugs.wool2.online/passport/03-TOPOLOGY-INFRA.md
**Живой журнал координатора:** `/Users/annakorin/Downloads/OPS-STATUS-LIVE.md` на ноуте владельца.
**Линии, посаженные 09.09:** l114m → l114u, каждая с браузерной пробой открытия документа на проде.
### Инструменты чата — посажено
- **Симптом владельца:** инструменты не вызываются.
- **Волна 3214 → GO**, коммит `2ed7668b8 fix(chat): execute direct tools and preserve refusal reasons`.
- **Посажено:** линия l114s, прод с 09.09 18:02Z.
### Инструменты ИИ в РЕДАКТОРЕ — отдельный дефект, починен, ждёт приёмки
- **Симптом владельца 09.09:** «аи инструменты в редакторе перестали работать».
- **Подозрение координатора (записано в бриф КАК подозрение, с требованием опровергнуть):** гард расхода `src/lib/billing/spendGuard.ts:158` отказывает с `request_identity_missing` — «This request could not be given a stable identity, so it was refused to protect against duplicate charges».
- **Волна 3263 на M4 подтвердила подозрение самостоятельно**, коммиты `a908efb13 fix(editor): restore AI tool billing identity` + `7b6f26a49 chore(billing): refresh editor activation evidence`.
- новые файлы: `src/lib/billing/editorActionRequestIdentity.ts`, `src/lib/billing/editorActionCallsites.ts`;
- переведены действия редактора: `gardenerActions`, `lensActions`, `mirrorActions`, `nudgeActions`;
- 6 сфокусированных тестов зелёные; локальная браузерная проба открыла документ, нажала инструмент «Critic Lens», POST серверного действия наблюдался (`~/.agent_runs/3263-editor-ai-tools-dead/verify.json` на M4).
- **🔴 РИСК ПОСАДКИ, вписан в бриф приёмки 3271:** фикс меняет `generatedActivationManifest.ts`, `monet-w34-activation-manifest.json`, `monet-w35-activation-attestation.json` и реестр платных точек входа. Если они разойдутся с тем, что вычисляет сборка, платный периметр закроется и чат ответит 500 ВСЕМ — ровно это случилось 09.09 утром на 32 минуты. Приёмка обязана доказать, что файлы СГЕНЕРИРОВАНЫ, а не правлены руками.
- **Ловушка сбора:** волна не создала маркер и не положила бандл на ожидаемое место; `git bundle` из общего репозитория отказывал («Refusing to create empty bundle»), потому что коммиты жили только в рабочем дереве волны `/Users/milamarty/wt-3263-editor-ai-tools-dead`. Бандл собран оттуда.
**Приёмка 3271 круга 2 (Нео, Клод):** механизм фикса ПРАВИЛЬНЫЙ, тесты не вакуумные, защита от двойного списания не ослабла. Но **NO-GO по двум причинам**, и первая — ровно тот риск, который координатор вписала в бриф: автор перегенерировал свидетельства активации БЕЗ и , и пустое окружение молча удалило 6 релизных строк манифеста → 2 регрессии в гейте активации. В ревью невидимо: диф выглядит как +337 строк. Если бы это село вместе с остальными, платный периметр закрылся бы и чат ответил 500 всем. Вторая причина: точек входа инструментов редактора 12, личность запроса есть у 8, **4 не покрыты**, и две из них срабатывают автоматически при наборе текста. Круг 3 — волна 3272.
**ПОПРАВКА к предыдущей записи (шелл съел имена в обратных кавычках).** Блокер 1 приёмки 3271: автор запустил генератор
свидетельств активации без переменных `MODEL_ALLOWLIST` и `SPEND_DEPLOYMENT_MANIFEST`, которых требует документированная
команда (`WEB351E-REPORT.md:92`). Генератор синтезирует часть строк манифеста из этих переменных, поэтому пустое окружение
молча удалило 6 релизных строк. Полный прогон каталога `src/lib/billing/__tests__` (91 файл) даёт ровно 2 регрессии
против базы, обе в гейте активации.
---
## Обновление 10.09 утро — состояние и статус
**Живой прод:** l114v `76f02b486189d481ebdeb7735580481d60ff205d`. Откат: l114u `54243a5cff19ef2bacf2531a0951b7bb82a71633`.
**Собирается:** l114w с принятым гейтом схемы P19.
**Документ эпика (обновлён):** https://bugs.wool2.online/labs/enterprise-ent093-20260909.html
### Инструменты редактора: круг 3 в приёмке
Круг 2 получил NO-GO по двум причинам, обе зафиксированы: генератор свидетельств активации запускали без `MODEL_ALLOWLIST` и `SPEND_DEPLOYMENT_MANIFEST`, пустое окружение молча удалило 6 релизных строк манифеста → 2 регрессии в гейте активации при полном прогоне 91 файла тестов биллинга; и из 12 точек входа личность запроса имели 8, четыре нет, две из них срабатывают автоматически при наборе текста.
Волна 3272 (вершина `4f017a34b`) доделала оба пункта, приёмка круга 3 идёт на M4 (бриф 3276).
Лента
2026-09-10T13:14:03.718Z · coordinatorЭВОЛЮЦИЯ 10.09 — НАЙДЕНА КОРНЕВАЯ ПРИЧИНА, и она объясняет, почему прошлая починка была пустой.
src/lib/ai/clientApiKeys.ts: функция resolveClientApiKeys возвращает undefined БЕЗУСЛОВНО,
начиная с коммита 3def9644. Не по ветке, не по условию — всегда.
Следствие: путь провайдера закрыт наглухо. Чат не может вызвать инструмент и вместо честного
«путь провайдера закрыт» отвечает «не могу подтвердить по источникам» — то есть маскирует
отсутствие ключа под отсутствие источников. Именно это владелец видел на «сколько ехать» и «погода».
ВАЖНО для нулевого агента: этим же измерением доказано, что починка генерации книг (волна 3264)
была ИНЕРТНОЙ — она чинила слой над функцией, которая всегда отдаёт undefined. Зелёные тесты
там ничего не значили.
Урок: перед починкой поведения проверять, доходит ли до него ключ/флаг вообще
(ср. правило «флаги и зависимости проверять первыми»). Слой почин��н — не значит фича жива.
2026-09-10T15:17:55.464Z · coordinatorВЕРДИКТ 10.09 — GO. Статус in_progress -> review (сдано, ждёт линии).
Волна 3292 на M4, gpt-5.6-sol xhigh. Сдача: /Users/milamarty/waves/CLIENTAPIKEYS-REPORT.md (32 КБ)
+ CLIENTAPIKEYS.bundle с sha256-распиской.
Напомню предмет: `resolveClientApiKeys` в `src/lib/ai/clientApiKeys.ts` возвращала `undefined`
БЕЗУСЛОВНО с коммита `3def9644` — не по ветке, не по условию, всегда. Из-за этого путь провайдера
закрыт наглухо, чат не может вызвать инструмент и вместо честного «путь провайдера закрыт»
отвечает «не могу подтвердить по источникам», маскируя отсутствие ключа под отсутствие источников.
Этим же измерением ранее было доказано, что починка генерации книг (волна 3264) была ИНЕРТНОЙ:
она чинила слой над функцией, которая всегда отдаёт undefined, и зелёные тесты там ничего не значили.
2026-09-10T16:09:57.629Z · coordinatorЗАКРЫВАЮ 10.09 16:0xZ — посажено в l115a (8d598d69a) и ДОКАЗАНО НА БОЕВОМ.
Проба боевого чата (порт 3010) вопросом, требующим инструмента, «Какая сейчас погода в Дублине?»:
http=200
routed={"provider":"local","model":"direct-chat-tool","intent":"weather"}
Инструмент ВЫЗВАН. До починки на такой вопрос приходило «не могу подтвердить по источникам».
(Сам ответ — «I couldn't find Дублине, try a different city name» — это инструмент погоды не разобрал
русскую предложную форму; это уже другой, косметический вопрос, а не закрытый путь провайдера.)
ЭВОЛЮЦИЯ ЦЕЛИКОМ, для нулевого агента:
1) Симптом от владельца: на «сколько ехать» и «погода» чат отвечал «не могу подтвердить по источникам».
Это МАСКИРОВКА: настоящей причиной было отсутствие ключа, а пользователю говорили про источники.
2) Координатор нашла измерением: `src/lib/ai/clientApiKeys.ts` -> `resolveClientApiKeys` возвращала
`undefined` БЕЗУСЛОВНО начиная с коммита `3def9644`. Не по ветке, не по условию — всегда.
3) ВАЖНОЕ СЛЕДСТВИЕ: этим же измерением доказано, что починка генерации книг (волна 3264) была
ИНЕРТНОЙ — она чинила слой НАД функцией, которая всегда отдаёт пустоту. Зелёные тесты там
ничего не значили. Отсюда общее правило: перед починкой поведения проверять, доходит ли до него
ключ или флаг вообще.
4) Волна 3292 (M4, gpt-5.6-sol xhigh) — коммит `ce91ea481 fix(chat): resolve provider keys on server`,
18 файлов, +430/-112, новый `src/lib/ai/providerPathMessage.ts` и два теста
`tests/unit/client-api-keys-provider-path.test.ts`, `client-api-keys-server-resolver.test.ts`.
Отчёт: `/Users/milamarty/waves/CLIENTAPIKEYS-REPORT.md` (32 КБ), бандл с sha256-распиской.
5) Посажено в линии l115a вместе с SEC-047, починкой входящих и тестом версии извлечения.
ЛОВУШКА ДЛЯ ТОГО, КТО БУДЕТ ПРОБИТЬ ЭТОТ ПУТЬ: боевой `chat-global` при вооружённом P11 требует
заголовок `x-idempotency-key`, иначе отдаёт 400 `idempotency_key_required`. Выкаченный веб-клиент
его шлёт (проверено: 11 файлов клиента в релизе содержат заголовок), а старые пробы координатора — нет.
400 в пробе означает «проба старая», а не «чат сломан». Ср. WEB-477.
Связано: WEB-591 (та же волна проверяла, вызывается ли инструмент), WEB-477 (идемпотентность и P11).
Воркер
не привязан — привязать:
curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \
-d '{"issueId":"WEB-584","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-10T16:09:57.636Z