Next 16 грузит sharp обычным require и NEXT_SHARP_PATH не читает: без sharp /_next/image отдавал исходный JPEG. Критик 3 (9/10): точка-разделитель нот и «·» в скобке недели не висят в начале/конце строки, имя и фамилия латиницей не разрываются.
9.6 KiB
9.6 KiB
Ошибки ИИ
Записи по ходу работы: что ИИ сделал не так, чем поймали, что исправили. Источник для раздела 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 |