# Хватит защищать свой ров документами (3/5)

Source: https://lodos.md/ru/blog/make-your-moat-a-ratchet-ru
Published: 2026-08-11 · Author: Samet Samyeli · Language: ru · Reading time: 8 min

Ров, который держится на регламентах, начинает гнить в тот день, когда в команду приходит новичок или кто-то правит код в три часа ночи. У меня на каждом коммите работают две проверки: одна роняет сборку, если в код вернулось запрещённое, вторая роняет wiki, если из неё выпал добытый урок. Обе запечатаны в одной HMAC-цепочке.

---

> Большинство AI-продуктов защищают свой ров регламентами, а регламенты тихо гниют в тот день, когда в команду приходит новичок или кто-то правит код в три часа ночи. Я защищаю свой двумя жёсткими проверками, и обе идут на каждом коммите. Первая роняет сборку, если я всё-таки протащил в продукт то, что клялся никогда не строить. Вторая роняет wiki, если добытый кровью урок стало нельзя найти запросом или он начал противоречить сам себе. Обе запечатаны в общей HMAC-цепочке. Так получается единственный ров, который щёлкает только в одну сторону: каждый отказ и каждый урок делают систему строго труднее откатить назад и строго полезнее, чем вчера.

На каждом коммите у меня запускаются два скрипта.

Первый прогоняет grep по всему коду и ищет то, что я поклялся никогда не выпускать: динамические вычислители выражений, инструменты, возвращающие значение секрета, сырые модули провайдеров, ту самую смертельную триаду, через которую агент утаскивает данные наружу. Нашлось хоть одно совпадение, и сборка падает, причём падает жёстко.

![Две зеркальные колонки над общей HMAC-цепочкой: слева код проходит через grep, который ищет запрещённое, пока сборка не упадёт; справа wiki проходит через lint, который ищет недостающее, пока не сломается целостность; события с обеих сторон пишутся в один и тот же журнал, где подделка сразу заметна.](/blog/make-your-moat-a-ratchet/2a.webp)

Второй обходит wiki и задаёт обратный вопрос: чего здесь нет, хотя должно быть? Утверждение без источника. Страница о понятии, на которую никто не ссылается. Два текста, написанные с разницей в полгода и спорящие друг с другом. Первый скрипт не даёт системе превратиться в CVE. Второй не даёт ей забыть то, что она уже поняла.

Весь lodos построен вокруг одного правила. Каждый значимый отказ живёт в сборке как grep. Каждое значимое знание живёт как версионируемая страница, к которой можно обратиться запросом.

Обе половины лежат внутри HMAC-цепочки, которая громко рвётся при первой же попытке подправить что-то задним числом. Запишите то, что отказываетесь добавлять. Запишите то, что отказываетесь забывать. И заставьте сборку не выпускать релиз, пока нет обоих списков. Большинство AI-продуктов записывают, какими хотят быть, и защищают это регламентами. Кто-то записывает, какими отказывается становиться, и защищает это кодом. Совсем немногие записывают ещё и то, что отказываются забывать, и защищают это через wiki, которая заваливает собственную проверку целостности, стоит одной странице уплыть в сторону. Только у последних ров прирастает сам, как сложный процент.

![Слева ров на регламентах: письменное обещание проходит через новичка в команде, через рефакторинг и через тихий дрейф, никто ничего не замечает, и кривая доверия сползает к нулю. Справа ров-храповик: grep и lint громко падают на каждом коммите, и за те же двенадцать месяцев кривая доверия поднимается ступенями.](/blog/make-your-moat-a-ratchet/3a.webp)

## Что разрушается, а что нет?

Ров на регламентах умирает тихо. «Мы никогда не пишем секреты в логи». «Вывод каждого инструмента у нас изолирован». «Мы проверяем данные до того, как их увидит модель». Такие фразы живут в документах SOC 2 и в день написания честны. Потом новичок добавляет отладочный вывод. Рефакторинг прячет очистку данных за флагом. Фраза в документе остаётся прежней, система ведёт себя иначе. Ничего не падает. Никто не замечает.

Ров на знании рушится ещё быстрее. В два часа ночи основатель наконец понимает, почему ушёл клиент, кидает мысль в Slack и через неделю о ней не помнит. Урока нет нигде, где его можно было бы найти запросом. Через три месяца та же история повторяется, и за тот же урок он платит второй раз. Это самая дорогая потеря, потому что о ней никто так и не узнаёт.

Лечится и то и другое одинаково: привяжите нужное вам свойство к структуре, которая ломается вместе с ним. Пусть сборка падает, когда отказ откатился назад. Пусть wiki заваливает собственный lint, когда страница осталась без входящих ссылок, уехала от темы или начала спорить сама с собой. Дело не в процессе. Дело в проверке, которую система прогоняет против самой себя каждый раз, без исключений.

![Цикл из трёх операций: загрузка превращает сырые источники в черновик страницы, который сначала проходит через окно с построчным сравнением и только потом становится каноническим; запрос собирает ответ со ссылками на источники, и такой ответ можно сохранить обратно страницей; проверка ищет страницы-сироты, утверждения без источников и противоречия. Ниже перечислены три отличия lodos: зашифрованное хранилище на SQLite, право агента только предлагать и журнал, запечатанный HMAC-цепочкой.](/blog/make-your-moat-a-ratchet/4a.webp)

## Подход Karpathy, переведённый в продукт

Половина про знание придумана не мной. Andrej Karpathy описал wiki для языковой модели: три операции и одно утверждение. Wiki здесь работает как исполняемый файл, сырые источники как исходный код, модель как компилятор, lint как тесты, а запросы как выполнение программы.

Я взял этот подход целиком и осознанно поменял три вещи.

- **Хранилище.** У Karpathy это папка markdown-файлов под git. У меня SQLite и хранилище, зашифрованное посекционно. Я меняю совместимость на конфиденциальность. Чистый экспорт в markdown никуда не делся, так что Obsidian всегда под рукой.
- **Свобода агента.** Karpathy разрешает модели писать напрямую. У меня любая правка идёт через окно сравнения, где я её одобряю. Канонической страницы агент не касается вообще. На каждое одобрение уходит от пяти до десяти секунд, зато агент не может тихо переписать моё поведение.
- **Аудит.** Karpathy ведёт обычный markdown-лог. Я веду HMAC-цепочку, подписанную производным ключом от мастер-пароля. Подделанный журнал всплывает разрывом цепочки при следующем запуске.

Это не спор о философии. Это перевод личной практики в коммерческий продукт: дух сохранён, а цена уже такая, какую платит покупатель, которому нужен комплаенс.

## Обе половины щёлкают только вперёд

Сторона отказов и сторона знания устроены одинаково. Одна ищет то, чего быть не должно никогда. Вторая ищет пропажу того, что быть обязано. Обе проверяют отсутствие, обе падают громко, обе запечатаны в одной HMAC-цепочке.

Когда я задаю wiki вопрос и ответ выходит удачным, интерфейс предлагает в один клик сохранить его страницей. Соглашаюсь, и ответ становится долговечным: следующая сессия его найдёт, а задавать тот же вопрос больше не придётся. Метрика тут простая: доля сохранённых ответов, и со временем она растёт. Wiki остаётся единственной частью системы, которая становится строго сильнее оттого, что я ею пользуюсь.

Сторона отказов работает так же. Каждая новая возможность, угрожающая инварианту, приносит с собой новый инвариант в скрипт проверки. За восемь месяцев скрипт вырос с семи проверок до тридцати двух. Любая функция выходит в релиз вместе с тем grep, который закрывает её класс злоупотреблений. Запретов в коде становится только больше, и обратного хода у этого счётчика нет.

Обычно эти две задачи разводят по разным углам. На деле это одна дисциплина, применённая к двум разным пустотам: к тому, чего быть не должно, и к тому, что нельзя забывать.

## Плата за такой ров и есть его смысл

Я теряю скорость ровно там, где новая функция спорит с отказом, и там, где переписывание прошло бы мимо wiki. Опытный пользователь просит вычислитель выражений прямо в поле ввода. Отказано. Клиент просит инструмент, который вернёт значение секрета. Отказано. Мне самому через полгода захочется выдрать цикл одобрений, потому что он кажется медленным. Сборка не даст.

Мой список изменений к релизу не похож ни на один конкурентский: отказы там встречаются не реже новых функций. Красивой истории роста, из которой вычеркнуто всё сознательно несделанное, у меня не выйдет.

То, что я получаю взамен, не влезает в рекламный текст, зато отлично звучит в разговоре с покупателем из регулируемой отрасли. Такой покупатель слышит «мы не можем» совсем не так, как «мы обещаем, что не будем». Специалист по комплаенсу смотрит на HMAC-цепочку, где подделка сразу заметна, иначе, чем на markdown-лог. А основатель, который читает wiki сегодня, на самом деле пишет её для себя же через полгода. Ни до кого из этих людей маркетинговым обещанием не достучаться.

![Пять деталей сначала лежат карточками, потом соединяются в схему: репозиторий кода питает скрипт инвариантов на стороне отказов, lint для wiki закрывает сторону знания, обе стороны пишут в общую HMAC-цепочку, а любая правка идёт по маршруту, где агент только предлагает, и проходит через окно сравнения, прежде чем стать канонической.](/blog/make-your-moat-a-ratchet/5a.webp)

## Пять деталей, которые можно украсть

Ни одна из них не требует остальных. Вместе они складываются в общий подход.

1. Декларативный движок автоматизаций, в котором нет вычислителя выражений ни в каком виде.
2. Хранилище из двух частей, устроенное так, что модель физически не может вернуть секрет в открытом виде.
3. Скрипт инвариантов на этапе сборки, каждая проверка которого доказана намеренным нарушением.
4. Wiki с тремя операциями Karpathy, журнал которой обёрнут в HMAC-цепочку.
5. Цикл обучения, в котором агент только предлагает и никогда не пишет собственное поведение.

Порядок внедрения любой. Общее у них ровно одно: запишите, что отказываетесь выпускать и что отказываетесь забывать, поставьте на оба списка проверку в сборке и убедитесь, что проверки живые, попробовав нарушить их нарочно. Дальше начинается обычная инженерия.

![Следующий цикл из шести шагов: агент слушает разговор, замечает пробел в своих навыках и готовит предложение; предложение упирается в окно с построчным сравнением, отмеченное как единственный проход; там человек одобряет или отклоняет, и только после этого правка становится канонической и уходит в релиз, а само предложение и решение по нему попадают в HMAC-цепочку.](/blog/make-your-moat-a-ratchet/6a.webp)

## Что дальше?

*Последний цикл дался мне дольше всех остальных. Агент слушает разговор, замечает, что его собственный набор навыков стоит поправить, и предлагает правку. Я одобряю или отклоняю. Правка идёт через то же окно сравнения, что и любое предложение для wiki. Собственное поведение агент не пишет никогда. Настоящий ров проходит ровно там, где предложение упирается в одобрение и другого пути нет. Следующий текст будет про этот цикл и про короткий кусок в промпте с описанием поведения, ради которого вся эта инженерная работа и затевалась.*

[Записаться в лист ожидания](https://lodos.md/)
