Коротко
Автор описывает, как проверял релиз 0.12 локальной памяти для кодовых агентов: вместо общего запроса «отревьюй код» две ИИ-модели искали воспроизводимые нарушения заранее записанных инвариантов. Такой подход выявил ошибки доверия, конкурентности и сохранности данных, но потребовал около десяти дней и не устранил все известные риски.
Контекст
Автор проекта skillmem — локального MCP-сервера на SQLite с девятью инструментами mem_*, базу которого могут совместно использовать Claude Code, Codex, Cursor и другие клиенты. После релиза 0.11 автор счёл ревью без чётких критериев субъективным и перед разработкой 0.12 составил список проверяемых обещаний программы.
Главное
- В docs/INVARIANTS.md зафиксировали 16 инвариантов INV-01…INV-16: о данных, доверии, конкурентности и прочих свойствах; для каждого указаны формулировка, ответственная функция и статус.
- Условие выпуска: ноль ошибок P1/P2 в классах данных, доверия и конкурентности. Остальные проблемы можно оставить в Known issues, но раскрыть явно.
- Код независимо проверяли Codex от OpenAI и Claude Opus 5.5 от Anthropic. Цикл работы занял около десяти дней: с 0.11.0 от 17 сентября до 0.12.0 от 27-го.
- Находку засчитывали только при воспроизведении: каждый исправленный дефект получил тест, который должен падать на родительском коммите. scripts/release-gate.sh отсекает тесты, проходящие и до, и после исправления.
- Property-тесты написаны на hypothesis; конкурентность проверяли настоящими процессами и потоками над одним файлом, а не моками блокировок. Хуки также испытывали битым вводом, базами и путями.
- На Windows перенаправленный из NUL ввод ошибочно распознавался как TTY. Агент мог сохранить запись как одобренную и запечатанную, хотя команда была запущена без настоящего терминала.
- Хук рекапа допускал повторный вызов из-за будущего времени mtime на Windows; отдельная гонка возникала, когда два Stop-хука читали временную метку до получения лока.
- Проверку рамки, отделяющей недоверенный текст от инструкций, обходили маркеры после необычных разделителей и невидимых символов, а также символы ⨠ и ⪥, похожие на угловые скобки.
- Прерывание записи при ожидании лока могло оставить транзакцию SQLite открытой: последующие записи казались успешными, но исчезали при закрытии соединения. Ещё одна ошибка позволяла копии базы вмешиваться в бэкапы оригинала и удалять используемые им файлы тел.
- Набор тестов вырос примерно с 430 до 2 538. CI проверяет Linux, macOS и Windows на Python 3.11–3.13, а также семантический поиск, сборку и Docker-образ; проверки повторяются при публикации на PyPI.
Как сделано
Сначала автор перевёл ожидания от программы в 16 инвариантов и связал каждый с конкретными участками кода. Затем два независимых ревьюера искали контрпримеры к этим обещаниям, а не оценивали код по общему впечатлению.
Для каждой находки требовался воспроизводимый тест, падающий до исправления и проходящий после него. Конкурентные сценарии проверяли реальными процессами и потоками; для ввода и файловых путей использовали фаззинг и property-тесты. Изменения проверялись в CI на трёх ОС и нескольких версиях Python.
Результаты
Релиз 0.12 получил около 2 538 тестов против примерно 430 ранее. Были найдены и исправлены дефекты, затрагивавшие подтверждение владельца, ограничение частоты хуков, защиту от инъекций инструкций, откат транзакций и изоляцию копий базы. За ревью не было отдельного счёта за токены: модели использовались по фиксированным подпискам. Релиз стал строже к некоторым сценариям, которые раньше принимались молча, включая команды владельца без TTY.
Ограничения
В CHANGELOG осталось около двадцати Known issues. Проверка TTY и deny-правила не защищают от агента, способного выполнять произвольные shell-команды; для этого нужна песочница. Некоторые поля всё ещё показываются модели без защитной рамки, журнал уже показанных правил не защищён от параллельных хуков, а опасное регулярное выражение на Windows прерывает только таймаут Claude Code в 10 секунд. Также uninstall —purge-db не работает, пока MCP-сервер держит базу открытой. Автор не утверждает, что устранены все риски; часть проверок поведения и полной защиты от недоверенного агента остаётся за пределами исправлений.
Что взять себе
- Для ревью ИИ полезнее задавать проверяемые свойства и требовать воспроизводимый контрпример, чем просить просто «проверить код».
- Связывайте каждый инвариант с кодом и тестом: так проще оценивать находки и проверять исправления.
- Проверяйте поведение на реальных ОС и при настоящей конкуренции: ошибки терминала, файловой системы и блокировок могут не проявиться при чтении кода или в тестах с моками.
- Отделяйте известные ограничения от исправленных ошибок и сообщайте о несовместимостях до обновления.
- Не считайте проверки ввода и терминала заменой песочнице, если агент может запускать произвольные команды.
Читать оригинал, если…
Откройте оригинал, если нужны сами инварианты, список известных проблем, детали регрессионных тестов или инструкция по обновлению skillmem.