Image: AI generated
how-make-questはQuest CLIを素手で建てる方法だった。ratchetとは何か、ゲートをどう掛けるか、cheeseをどう塞ぐか。記事一本をエージェントに渡せばcobraベースのGo製CLIが出てくる。
だが二つ目のQuest CLIを建てると何が起きるか。同じ一方向ステートマシンをまた書く。同じscan/next/submit/status/exportをまた書く。同じPASSロック、同じremainingの単調減少、同じJSONL exportをまた書く。変わるのはゲート一つだけなのに、毎回残り全部を書き直す。 これがクエストを一つ建てるたびに課されるボイラープレート税だ。
パターンは再利用できた。コードはできなかった。reinsはその間隙を閉じる。
何が不変で何がドメインか
Quest CLIを二つ重ねて差分(差分)を見ると、境界が鮮明だ。
不変 (すべてのクエストが共有) ドメイン (クエストごとに異なる)
───────────────────────── ─────────────────────
ratchet: TODO→PASS 不可逆 何が一つのクエストか
コマンド骨格: scan/next/submit… 何が「事実」か
レベル集計: Fail/Review→verdict どのcheeseを塞ぐか
進行の永続・resumable
export: 一度きりの放出
左側はhow-make-questが証明したそのままだ — ドメインが会社名でもエンドポイントでも関数でも、ratchetの歯車は同じように噛む。右側だけを人が知っている。reinsは左側をフレームワークとして供給し、あなたには右側だけを残す。
これは新しい主張ではなく、reinsがコードで強制する古い原則だ — 決定と実装の分離。 ゲートは決定(このドメインで何が真か)であり、ratchet・CLI・集計は実装だ。実装を毎回書き直すのは、決定を実装に縛りつける失敗である。
ゲート一つだけを実装する
reinsでクエストを作るとは、インターフェース一つの四つのメソッドを埋める作業だ。
type Definition interface {
Seed(args []string) ([]*quest.Item, error) // 入力 → 初期 TODO シード
Render(it *quest.Item) (string, error) // next が見せる作成プロンプト + 検証コンテキスト
Prepare(it *quest.Item, raw []byte) (gate.Context, *quest.Verdict, error) // 提出デコード
Rules() []gate.Rule // ゲート違反ルールのカタログ
}
func main() { cli.NewQuestCmd("myquest", myDef{}, cli.Options{}).Execute() }
main一行がratchet・六つのコマンド・集計・export・resumableセッションを全部供給する。あなたが書いたのはドメインの四つのピースだけだ。エージェントは相変わらずコマンド二つだけ知っていればよい — nextで受け取りsubmitで出す。残りは機械が決める。
ゲートはcheese防御ルールのカタログだ
how-make-questの核心は「cheese不可能なゲートを設計せよ」だった。reinsはその設計をデータ構造にする — ゲート = ルールカタログ。 ルール一つが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を見つけるたびにルールを一つ追加すれば、ゲートはその分だけ堅くなる。そしてカタログは自分自身を文書化する — rulesコマンドがルール一覧を出力すれば、それがそのまま「私が塞いでいるcheeseの監査リスト」だ。何を塞いでいるか分からないゲートは存在しない。
深刻度は重みではなくレベルだ。Fail一つあれば即FAIL。決定的な違反は交渉されない — 99点の違反九つで一つのFailを覆い隠せない。Evaluateは発動したルールをレベルで集計する: 一つでもFailならFAIL、そうでなくReviewがあればREVIEW、全部通過ならPASS。
権限の非対称性を型で強制する
how-make-questで最も重要な一行は「PASSロックは機械だけ」だった。reinsはこれを規約ではなく型で打ち込む。
L1 機械(決定論) PASSをロックする唯一の権限
L2 AI(懐疑者) REVIEWだけ — 疑いを提起するが完了を授与できない
L3 人間 両方が見逃した残余
機械ゲートはPASSを出す。AI検証器をゲートに入れても、それができる最大はREVIEWに回すことだ。間違ったことを最初から不可能にする — フレームワークがAIにPASS権限を与えるAPIを提供しなければ、誤って酔った友人に判定を任せることもできない。
二つ目のバックエンド — defeatグラフ
独立したルールたちのレベル集計で十分なゲートは多い。だがルールたちが互いに競合し始めると — 「この違反はあの違反があるときだけ意味を持つ」「この失敗の根本原因は実はあれだ」 — 手書きのif-elseガードがゲートを侵食する。弱いゲートが壊れる場所ではなく、複雑なゲートが腐る場所だ。
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評価
ゲートが決定論的であるためには、ネットワークがゲートの中にあってはならない。net/httpを直接呼ぶルールは単体テストが不可能で、判定が回線事情によって揺れる。
reinsは副作用をpkg/groundに追い込む — HTTPBody・MXResolvesのような原始演算が注入型Resolverとリクエストごとのスナップショットで外部照会を所有する。ルールは純粋なまま残り、外部世界はgroundが責任を負う。
そしてstaged評価: 安い検査が先に回り、それが失敗すればネットワークfetchはそもそも起きない。形式が間違った提出にDNSを照会する理由はない。高くて揺れるものを、安くて確実なものの後ろに立てる。
N=1抽象化禁止
reinsの規約の一つが、このフレームワークの性格を最も正確に表す — 一つの消費者から抽象を抜くな。 新しい抽象は二つ目の消費者で検証した後にだけ凍結する。
これは気難しさではなく第一原理だ。一つの事例から抜いた抽象は、その事例の偶然を本質と取り違える。二つ目のドメインが同じ抽象を要求したときにはじめて、それが不変であると証明される。フレームワークが自分自身の進化にまで「主張ではなく検証」を適用するのだ。ゲートがエージェントの主張を信じないように、抽象は一つの事例の主張を信じない。
同じ一文が、ライブラリになる
reinsはpkg/の七つのパッケージで立つ — textmatch(幻覚遮断の原始演算)、temporal(時間正規化)、quest(ratchetコア)、gate(ゲート契約)、graph(defeatグラフ)、ground(ネットワーク隔離)、cli(cobraスキャフォールド)。go build・go test通過、全関数カバー。そしてtoulminはグラフバックエンドにだけ一方向に結合されており、グラフを使わない消費者はtoulminをリンクすらしない。
コード: github.com/park-jun-woo/reins
how-make-questが一つの文だったとすれば — 生成は確率的でいい、検証は決定論的でなければならない — reinsはその文をコンパイル可能な形に固めたものだ。ゲートはドメインの事実を再検証し、ratchetは通過したものをロックし、グラフは負けた理由を事実で返し、おべっかするモデルはその事実に順応する。
次にQuest CLIが必要になったら、ratchetを書き直すな。ドメインのゲートだけ書いて、手綱(reins)は借りろ。
一緒に読みたいもの
reinsがコードで固めた原則 — 生成は確率的、検証は決定論的 — は、reinsだけの発見ではない。互いに知らない人々が同じ壁にぶつかり、同じ結論に到達した。how-make-questが集めた独立収束プロジェクトたちがその証拠だ。
- episteme — 取り返しのつかない作業の前にReasoning Surfaceを強制。reinsのratchetと同じ直観 — PASSはロックする前に検証する。
- MagLab — 「LLMは推論だけ、数字は決定論的ツールが」。reinsが副作用を
pkg/groundに隔離するのと同じ分離。 - Manifesto — 「Agent proposes, World verifies.」 reinsの権限の非対称性(L1だけがPASSをロックする)を一文に要約する。
- oh-my-kamisama — 「diffs beat claims.」 ゲートがエージェントの主張ではなく事実を再検証するのと同じ原則。
そしてdefeatグラフバックエンドの根は論証理論だ — 下記の出典のToulmin・Dung・Amgoud系列。reinsのpkg/graphは、その60年を超える形式論理をGoのデータ構造に移したものだ。
出典
- Toulmin, S. (1958). The Uses of Argument. Cambridge University Press. — defeatグラフのWarrant・Ground・Backingがそのまま取られた論証モデル。
- 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. —
pkg/graphが採用したweighted h-Categoriser。攻撃を受けたノードが再び防御されると受容度が回復する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グラフの系譜。
- Gabriel, V.O. et al. (2020). “Reasoning in BDI agents using Toulmin’s argumentation model.” Theoretical Computer Science, 805, 76–91. — トゥールミンモデルをソフトウェアで実装した先行事例(BDIエージェント)。reinsの
pkg/graphはこれをゲート判定に移す。 - 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 — 能力が高いほどゲートの隙間をよりうまく見つける → ゲート=ルールカタログが育たねばならない理由。
- Thaman, K. (2026). “Reward Hacking Benchmark: Measuring Exploits in LLM Agents with Tool Use.” arXiv:2605.02964 — ゲートを意図的に堅くすればエクスプロイトが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 — 手綱のあるAI — ハーネスは柵、クエストは手綱。reinsがコードで打ち込んだ決定と実装の分離。
- Ratchet Pattern — エージェントを最後まで走らせる方法 —
pkg/questが実装した一方向ロック・単調減少の本編。 - toulmin — 契約を計算するルールエンジン — defeatグラフバックエンドのh-Categoriser。主張を事実ではなく反論可能なclaimとして扱う。
- トリプルは事実ではなく主張だ — 同じ論証エンジンを知識グラフに適用した事例。Warrant・Counter・Supersedesのもう一つの舞台。
- huma — エンドポイントを飛ばさないratchet —
Definition四メソッドを埋めたドメインインスタンス。ゲートだけ変えれば別のツールになるという証拠。 - モデルIQよりフィードバックトポロジー — 結果を分けるのはモデルではなくフィードバック構造。グラフが返す攻略集の理論的背景。
- LLMマルチエージェントの精度向上の前提条件 — L2 AI検証が独立性を備えてはじめて機能する理由。権限の非対称性の理論的背景。
変更履歴
- 2026-06-05: 初版