Next 16 грузит sharp обычным require и NEXT_SHARP_PATH не читает: без sharp /_next/image отдавал исходный JPEG. Критик 3 (9/10): точка-разделитель нот и «·» в скобке недели не висят в начале/конце строки, имя и фамилия латиницей не разрываются.
30 lines
9.6 KiB
Markdown
30 lines
9.6 KiB
Markdown
# Ошибки ИИ
|
||
|
||
Записи по ходу работы: что ИИ сделал не так, чем поймали, что исправили. Источник для раздела README «где ИИ ошибся».
|
||
|
||
| # | Шаг | Ошибка ИИ | Чем поймали | Исправление |
|
||
|---|---|---|---|---|
|
||
| 1 | План, деплой | Предложил `docker compose run …`, не проверив сервер; там нет плагина compose, только `docker-compose` v2.23 | Осмотр сервера по ssh перед планом деплоя | Везде `docker-compose` |
|
||
| 2 | План, Telegram | Предложил скрипт `tg:setup` через `getUpdates`, а позже — long polling в api; два потребителя одного потока обновлений конфликтуют | Сам заметил при проектировании восстановления через бота | Скрипт заменён командой бота `/setup` (ADR-0002) |
|
||
| 3 | Шаг 1, каркас | Сгенерировал `onlyBuiltDependencies` для pnpm, а в pnpm 11 формат сменился на `allowBuilds` — нативный better-sqlite3 молча не собрался | Ошибка `ERR_PNPM_IGNORED_BUILDS` и проверочный запуск `new Database(':memory:')` | `allowBuilds` + `pnpm rebuild better-sqlite3` |
|
||
| 4 | Шаг 1, каркас | Поставил самую свежую ESLint 10, плагины eslint-config-next её ещё не поддерживают | `pnpm peers check` | ESLint 9 |
|
||
| 5 | План, контракт | В плане «X-Real-IP доверяем только с 127.0.0.1» — в Docker запрос от nginx приходит со шлюза bridge-сети, и все посетители попали бы в один rate-limit | Агент api при реализации (вывод, не проверен на Docker) | `TRUSTED_PROXIES` + фиксированная подсеть в compose |
|
||
| 6 | Шаг 6, тесты | Тест «два одновременных запроса» проходит и без транзакции: better-sqlite3 синхронный — тест ничего не доказывает | Самопроверка агента api | Оставлен как регрессионный; защита — `IMMEDIATE`-транзакция, отмечено честно |
|
||
| 7 | Шаг 2, телефон | Первая версия считала российский `8 912…` «неверным кодом оператора», а 10 цифр без префикса — «иностранным номером» | Дописанные тесты на граничные вводы | Явное правило: `7…`, `8[1-9]…` и > 11 цифр — иностранные |
|
||
| 8 | Шаг 4, landing | Агент не увидел существующий `next.config.ts` (фильтр `grep -v .next` — точка в regex съела `next.config`) и перезаписал его, потеряв standalone, transpilePackages и прокси на api | Сообщение инструмента «updated» вместо «created» и `git status` с `M` | `git checkout` файла до коммита |
|
||
| 9 | Шаг 4, landing | Мутировал ref внутри апдейтера `setState` — в StrictMode апдейтер вызывается дважды, предзаполненный комментарий посчитался бы текстом посетителя | Самопроверка агента при перечитывании хука | Комментарий хранится в одном state со значениями формы |
|
||
| 10 | Шаг 8, landing | Синхронное исключение при сборке тела запроса оставляло кнопку навсегда в «Отправляем…» | Ревью своего кода агентом | Сборка тела внутри промиса с `catch` → блок «позвоните» |
|
||
| 11 | Шаг 5, deploy | Запустил сборку под amd64, не проверив эмуляцию на Apple Silicon — `exec format error` | Первый же `RUN` в сборке | Скрипт распознаёт ошибку и подсказывает включить Rosetta в Docker Desktop |
|
||
| 12 | Шаг 5, deploy | Пустой аргумент `previous` в `ssh … bash -s --` исчез бы при склейке строки и сдвинул остальные аргументы | Ревью агентом до прогона | Заглушка `-` вместо пустой строки |
|
||
| 13 | План, деплой | Заявил цели «образ ≤ 150–160 МБ» без расчёта: один бинарник node весит ~120 МБ, на `node:22-slim` это недостижимо | Замер `docker image ls` агентом deploy | Ужали с 281 до 224 МБ, по сети (gzip) — 64 и 71 МБ |
|
||
| 14 | Шаг 10, бэкапы | Копия из `db.backup()` унаследовала режим WAL: в архив попадала WAL-база, рядом с временными копиями оставались `-wal`/`-shm` | Тест `backup.test.ts` на чистоту временного каталога | Временная копия переводится в `journal_mode = DELETE` перед gzip |
|
||
| 15 | Шаг 9, тесты | Тест «без CHAT_ID» передавал `undefined`, и деструктуризация подставляла значение по умолчанию — тест проверял не то | Сам тест повёл себя не так, как ожидалось | `null` вместо `undefined` |
|
||
| 16 | План, восстановление | В плане пауза приёма включалась после снимка pre-restore — заявка, пришедшая во время gzip снимка, пропала бы | Агент api при реализации | Пауза до снимка, ожидание опустошения очереди Telegram |
|
||
| 17 | Шаг 5, прод | `TRUSTED_PROXIES=172.31.120.1` не срабатывал: Node отдаёт адрес сокета как `::ffff:172.31.120.1`, и все посетители снова делили один лимит. Тесты этого не ловили — в них адреса без префикса | Проверка на проде: 6 запросов с X-Real-IP «A», затем «B» получил 429 | Нормализация IPv4-mapped адресов + тест; на сервере проверено пробным контейнером |
|
||
| 18 | План, Telegram | План исходил из того, что VPS ходит в api.telegram.org напрямую; не проверил — с сервера в РФ Telegram недоступен (таймаут), бот не получил `/setup` | Тишина после `/setup` автора, затем проверка `fetch` из контейнера | Ретранслятор Bot API на домашнем сервере (`deploy/tg-relay`) по Tailscale + `TELEGRAM_API_BASE` |
|
||
| 19 | Шаг 9, бот | Сетевые ошибки `getUpdates` молча повторялись без единой строки в логе — недоступность Telegram была невидима | Пустой `docker logs` при неработающем боте | Предупреждение в лог раз в 10 минут |
|
||
| 20 | Оркестрация | Оркестратор закоммитил ретранслятор через `git add -A` в том же чекауте, где дизайнер вёл незакоммиченную вёрстку шага 12 — почти весь шаг 12 уехал в коммит `20db25b` «ретранслятор Bot API», а на прод выкатилась половина вёрстки | Отчёт дизайнера | История переписана с согласия автора: `20db25b` разделён на «ретранслятор» и «секции», `push --force-with-lease`; впредь — `git add` по путям |
|
||
| 21 | Шаги 12–13, дизайн | Самопроверка дизайнера по своим же скриншотам пропустила: полупрозрачную подложку штампа (просвечивало фото), фильтр «краски», съевший половину даты, ряд hero-метрик, запрещённый его же DESIGN.md, и повтор «ЧТ» лентой и штампом на каждой этикетке | Независимый критик по скриншотам, без доступа к коду | Итерация критика 1 |
|
||
| 22 | Шаг 12, дизайн | Секция доставки свёрстана во всю ширину без привязки к контейнеру — «Самовывоз» на 1440 вылез за правый край на 24px | Критик по скриншоту 1440 | Колонки 7–12 контейнера 1280 |
|
||
| 23 | Шаг 5, образы | Оркестратор подключил sharp через `NEXT_SHARP_PATH` по памяти о старых версиях Next; Next 16 эту переменную не читает и при отсутствии sharp молча отдаёт оригинал — `w=750` весил 838 КБ JPEG | Lighthouse mobile на проде: «image delivery, savings 777 KiB», затем `curl` по `/_next/image` | `NODE_PATH=/sharp/node_modules`; проверено: тот же запрос — 151 КБ webp |
|