Image: AI generated
how-make-quest была про то, как построить Quest CLI голыми руками. Что такое ratchet, как повесить gate, как заблокировать cheese. Дай агенту одну статью — и на выходе Go CLI на основе cobra.
Но что произойдёт, когда возьмёшься за второй Quest CLI. Снова напишешь тот же однонаправленный конечный автомат. Снова напишешь те же scan/next/submit/status/export. Снова напишешь ту же блокировку PASS, то же монотонное убывание remaining, тот же JSONL export. Меняется лишь один gate, а ты каждый раз заново пишешь всё остальное. Это налог на boilerplate, который ты платишь с каждого нового квеста.
Паттерн был переиспользуем. Код — нет. reins закрывает этот зазор.
Что инвариантно, а что — домен
Положи два Quest CLI рядом и посмотри на разность (差分) — граница станет резкой.
Инвариант (общее для всех квестов) Домен (своё у каждого квеста)
───────────────────────────────── ─────────────────────
ratchet: TODO→PASS необратим что является одним квестом
скелет команд: scan/next/submit… что есть «факт»
свод уровней: Fail/Review→verdict какой cheese нужно блокировать
персистентность·resumable прогресс
export: однократная эмиссия
Левая часть — ровно то, что доказала how-make-quest: будь домен названием компании, эндпоинтом или функцией, зубцы ratchet цепляются одинаково. Правую знает лишь человек. reins поставляет левую часть как фреймворк и оставляет тебе только правую.
Это не новое утверждение, а старый принцип, который reins принуждает соблюдать кодом — разделение решения и реализации. Gate — это решение (что в этом домене истинно), а ratchet·CLI·свод — это реализация. Переписывать реализацию каждый раз — это провал, привязывающий решение к реализации.
Реализуешь лишь один gate
Создать квест через reins — значит заполнить четыре метода одного интерфейса.
type Definition interface {
Seed(args []string) ([]*quest.Item, error) // вход → начальный TODO-seed
Render(it *quest.Item) (string, error) // промпт на запись + контекст проверки, что покажет next
Prepare(it *quest.Item, raw []byte) (gate.Context, *quest.Verdict, error) // декод заявки
Rules() []gate.Rule // каталог правил-нарушений gate
}
func main() { cli.NewQuestCmd("myquest", myDef{}, cli.Options{}).Execute() }
Одна строка main поставляет ratchet, шесть команд, свод, export и resumable-сессию целиком. Ты написал лишь четыре доменных куска. Агенту по-прежнему достаточно знать две команды — получает через next, сдаёт через submit. Остальное решает машина.
Gate — это каталог правил защиты от cheese
Суть how-make-quest была: «проектируй gate, который невозможно зачизить». reins превращает это проектирование в структуру данных — gate = каталог правил. Одно правило — один детектор cheese. Обнаружив нарушение, оно срабатывает (true) и грузит факт (Fact).
// Одно правило защиты от cheese для квеста извлечения новостных событий.
// «Существует ли who-якорь в оригинале» — если агент выдумает персону, он попадётся.
var whoAnchorPresent = gate.Rule{
Meta: gate.RuleMeta{ID: "who-anchor-present", Level: gate.LevelFail, Desc: "обязательный who-якорь существует в оригинале"},
Check: func(ctx gate.Context) (bool, quest.Fact) {
sub := ctx.Submission.(*Event)
if miss := textmatch.MissingTokens(ctx.Source, sub.Who.Anchors); len(miss) > 0 {
return true, quest.Fact{Where: "who.anchors", Expected: "substring оригинала", Actual: miss[0]}
}
return false, quest.Fact{}
},
}
Достоинство этой структуры в том, что она растёт. Каждый раз, обнаружив новый cheese, добавляешь одно правило — и gate становится настолько же твёрже. И каталог документирует сам себя: когда команда rules выводит список правил, это и есть «аудит-список cheese, который я блокирую». Нет gate, не знающего, что он блокирует.
Серьёзность — это не вес, а уровень. Один Fail — значит сразу FAIL. Решающее нарушение не торгуется: девятью нарушениями на 99 баллов не покрыть один Fail. Evaluate сводит сработавшие правила по уровням: есть хоть один Fail — FAIL, нет, но есть Review — REVIEW, всё прошло — PASS.
Асимметрию полномочий принуждаем типом
Самая важная строка в how-make-quest была: «блокировать PASS может только машина». reins вбивает это не как соглашение, а как тип.
L1 машина(детерминизм) единственное право блокировать PASS
L2 ИИ(скептик) только REVIEW — поднимает сомнение, но не присуждает завершение
L3 человек остаток, упущенный обоими
Машинный gate выносит PASS. Даже если поставить ИИ-верификатор в gate, максимум, что он может, — вытолкнуть в REVIEW. Неверное дело делаем невозможным изначально: если фреймворк не даёт ИИ API для выдачи PASS, ты даже по ошибке не доверишь вердикт пьяному другу.
Второй backend — defeat graph
Многим gate достаточно свода уровней из независимых правил. Но когда правила начинают конкурировать — «это нарушение значимо лишь при наличии того», «корневая причина этого провала на самом деле вон та» — написанные руками if-else-гарды разъедают gate. Не там, где ломается слабый gate, а там, где гниёт сложный gate.
Второй backend gate у reins переносит эту конкуренцию в декларативный граф — toulmin h-Categoriser. Модель аргументации Тулмина прямо становится структурой данных:
- Warrant — tautology PASS. Основание «нет возражений — значит прошло».
- Counter — нарушение атакует warrant.
- Supersedes — приоритет между правилами. Какое возражение бьёт какое возражение.
Написанные руками клаузы-гарды испаряются в рёбра Attacks·Supersedes. И когда рёбер 0, этот граф в точности эквивалентен своду уровней — сложность это цена, включаемая (opt-in) лишь при необходимости (включается, когда Definition реализует gate.Evaluator).
Настоящий подарок графа — не вердикт, а обратная связь. Оценка графа возвращает агенту прямое прохождение — Verdict.Feedback: «почему проиграл и что поменять, чтобы выиграть». Это не простое «FAIL», а корневая причина, вычисленная из структуры аргументации.
Здесь снова срабатывает парадокс how-make-quest. Модель угодлива — она покорно следует указаниям. Для мнений угодливость яд, но для фактов угодливость актив. Прохождение — это не мнение («как-то странно»), а факт («who.anchors нет в оригинале, поменяй это»). Чем угодливее модель, тем покорнее она принимает этот факт и сходится. Детерминированный граф + угодливый LLM = цикл с гарантированной сходимостью.
Побочные эффекты изолируем — ground и staged-оценка
Чтобы gate был детерминированным, сети не должно быть внутри gate. Правило, напрямую вызывающее net/http, невозможно покрыть юнит-тестом, а вердикт колеблется от состояния канала.
reins сгоняет побочные эффекты в pkg/ground: примитивы вроде HTTPBody·MXResolves владеют внешними запросами через инъецируемый Resolver и снимок на каждый запрос. Правило остаётся чистым, а внешний мир берёт на себя ground.
И staged-оценка: сначала идут дешёвые проверки, и если они провалились, сетевой fetch вообще не происходит. Нет смысла резолвить DNS для заявки в неверном формате. Дорогое и шаткое ставим за дешёвым и надёжным.
Запрет на абстракцию при N=1
Одно из соглашений reins точнее всего раскрывает характер этого фреймворка — не вытаскивай абстракцию из одного потребителя. Новую абстракцию замораживаем лишь после проверки вторым потребителем.
Это не придирчивость, а первопринцип. Абстракция, вытащенная из одного случая, принимает случайность этого случая за сущность. Лишь когда второй домен требует ту же абстракцию, доказывается, что она инвариантна. Фреймворк применяет «не утверждение, а проверку» даже к собственной эволюции. Как gate не верит утверждениям агента, так абстракция не верит утверждению одного случая.
Та же фраза, ставшая библиотекой
reins стоит на семи пакетах в pkg/ — textmatch (примитив отсечения галлюцинаций), temporal (нормализация времени), quest (ядро ratchet), gate (контракт gate), graph (defeat graph), ground (изоляция сети), cli (cobra-скаффолд). Проходят go build·go test, покрыты все функции. И toulmin сцеплен однонаправленно только с graph-backend, так что потребитель, не использующий граф, даже не линкует toulmin.
Код: github.com/park-jun-woo/reins
Если how-make-quest была одной фразой — генерация может быть вероятностной, верификация обязана быть детерминированной — то reins застыл этой фразой в компилируемой форме. Gate перепроверяет факты домена, ratchet блокирует прошедшее, граф возвращает причину проигрыша как факт, а угодливая модель подчиняется этому факту.
В следующий раз, когда понадобится Quest CLI, не пиши ratchet заново. Используй лишь gate своего домена, а поводья — одолжи.
Что почитать вместе
Принцип, который reins застыл в коде — генерация вероятностна, верификация детерминирована — это не открытие одного лишь reins. Незнакомые друг с другом люди упёрлись в одну стену и пришли к одному выводу. Проекты независимой конвергенции, собранные how-make-quest, тому свидетельство.
- episteme — принудительная Reasoning Surface перед необратимой операцией. Та же интуиция, что и ratchet у reins: PASS проверяют, прежде чем заблокировать.
- MagLab — «LLM лишь рассуждает, числа — детерминированному инструменту». То же разделение, что и изоляция побочных эффектов reins в
pkg/ground. - Manifesto — «Agent proposes, World verifies». Одной фразой суммирует асимметрию полномочий reins (только L1 блокирует PASS).
- oh-my-kamisama — «diffs beat claims». Тот же принцип, что gate перепроверяет не утверждение агента, а факт.
А корни defeat-graph-backend — в теории аргументации, в линии Toulmin·Dung·Amgoud из источников ниже. pkg/graph у reins переносит этот более чем 60-летний формальный логический аппарат в структуры данных Go.
Источники
- Toulmin, S. (1958). The Uses of Argument. Cambridge University Press. — модель аргументации, чьи Warrant·Ground·Backing прямо взяты в defeat graph.
- Dung, P.M. (1995). “On the Acceptability of Arguments and its Fundamental Role in Nonmonotonic Reasoning, Logic Programming and n-Person Games.” Artificial Intelligence, 77(2), 321–357. — первоисточник абстрактного фреймворка аргументации и attack(defeat)-графа.
- Amgoud, L. & Ben-Naim, J. (2013). “Ranking-based semantics for argumentation frameworks.” SUM 2013, LNCS 8078, 134–147. — weighted h-Categoriser, принятый в
pkg/graph. Свойство Compensation, при котором приемлемость атакованного узла восстанавливается, если он снова защищён, и гарантия сходимости. - Nute, D. (1994). “Defeasible Logic.” In Handbook of Logic in Artificial Intelligence and Logic Programming, Vol. 3. Oxford University Press. — классификация strict/defeasible/defeater. Формальный корень уровней правил reins (Fail/Review) и приоритета
Supersedes. - Modgil, S. & Prakken, H. (2014). “The ASPIC+ Framework for Structured Argumentation: A Tutorial.” Argument & Computation, 5(1), 31–62. — система аргументации, структурировавшая классификацию Nute внутри фреймворка Dung. Родословная defeat graph.
- Gabriel, V.O. et al. (2020). “Reasoning in BDI agents using Toulmin’s argumentation model.” Theoretical Computer Science, 805, 76–91. — предшествующий пример программной реализации модели Тулмина (BDI-агенты).
pkg/graphу reins переносит это в вердикт gate. - Von Neumann, J. (1956). “Probabilistic Logics and the Synthesis of Reliable Organisms from Unreliable Components.” Automata Studies, Princeton University Press. — принцип построения надёжного протокола поверх нестабильных компонентов (предпосылка reins).
- Stechly, K., Valmeekam, K., & Kambhampati, S. (2024). “On the Self-Verification Limitations of Large Language Models.” arXiv:2402.08115 — самопроверка почти не повышает качество → причина отдать право PASS машине L1.
- McKee-Reid, L. et al. (2024). “Honesty to Subterfuge: In-Context RL Can Make Honest Models Reward Hack.” arXiv:2410.06491 — даже честная модель манипулирует, когда судит собственную награду → основание асимметрии полномочий.
- Bondarenko, A. et al. (2025). “Demonstrating Specification Gaming in Reasoning Models.” arXiv:2502.13295 — чем выше способности, тем лучше находит лазейки gate → причина, почему gate=каталог правил должен расти.
- Thaman, K. (2026). “Reward Hacking Benchmark: Measuring Exploits in LLM Agents with Tool Use.” arXiv:2605.02964 — преднамеренное упрочнение gate сократило эксплойты на 87,7%.
- Fanous, A. et al. (2025). “SycEval: Evaluating LLM Sycophancy.” AAAI/ACM AIES 2025. arXiv:2502.08177 — замер уровня капитуляции под угодливостью. Две стороны «для фактов угодливость актив».
- Shapira, I. et al. (2026). “How RLHF Amplifies Sycophancy.” arXiv:2602.01002 — теорема о том, что RLHF усиливает угодливость. Предпосылка цикла сходимости фактическая обратная связь + угодливость.
- Deque Systems (2021). “Automated Testing Study Identifies 57 Percent of Digital Accessibility Issues.” — граница машинно-судимой области (57%) и человеческого остатка (20%).
Связанные статьи
- Как создать Quest CLI — методология, которую reins застыл во фреймворк. От принципа (почему) до скелета команд (как).
- Reins Engineering — ИИ на поводьях — harness это забор, квест это поводья. Разделение решения и реализации, вбитое reins в код.
- Ratchet Pattern — как заставить агента дойти до конца — основная статья про однонаправленную блокировку и монотонное убывание, реализованные в
pkg/quest. - toulmin — правило-движок, вычисляющий контракт — h-Categoriser defeat-graph-backend. Обращается с утверждением не как с фактом, а как с опровержимым claim.
- Триплет — это не факт, а утверждение — пример применения того же движка аргументации к графу знаний. Другая сцена для Warrant·Counter·Supersedes.
- huma — ratchet, не пропускающий эндпоинты — доменный инстанс, заполнивший четыре метода
Definition. Доказательство, что смена одного gate даёт другой инструмент. - Топология обратной связи важнее IQ модели — результат решает не модель, а структура обратной связи. Теоретическая подоплёка прохождения, возвращаемого графом.
- Предусловия повышения точности мультиагентных LLM-систем — почему ИИ-верификация L2 работает, лишь обладая независимостью. Теоретическая подоплёка асимметрии полномочий.
История изменений
- 2026-06-05: Первая версия