AI コーディング・ループにおける形式検証ゲート

2026/05/21 0:25

AI コーディング・ループにおける形式検証ゲート

RSS: https://news.ycombinator.com/rss

要約

日本語翻訳:

最も重要な発見は、アクセス制御の脆弱性が依然として最大のセキュリティリスクであり、モデル指示のみを頼ることは本質的に不安定であるという点です。モデルは規則を容易に忘れたり、権限を妄想したりする可能性があるためです。これを解決するために、Shen-Backpressure は脆い振る舞いのプロンプトを置き換え、静的型付けコンパイラによって強制される堅牢な構造的ソリューションを採用します。従来の手法とは異なり、このアプローチはメンバーシップチェックをばらばらなハンドラーコードから集約された構築境界へとシフトさせ、未承認アクセスを構造的に困難かつ高コストに違反させるようにしています。この方法は、静的型付け Lisp 言語である Shen と演算子計算式の型システムを利用し、テナントアクセスルールなどの厳格な権限付与不変量を強制します。開発プロセス中、ビルドループは決定論的な失敗データをプロンプトへフィードバックし、専用ツールが Go ストラクチャなどというターゲット言語のガード型を生成して、これらのセキュリティポリシーを固定化します。今後、このスケルトンには Claude Code や Cursor などの高度な LLL ハネスを組み込み、コード生成を自動化する予定です。この拡張では、型チェッカーとジェネレータを信頼できる計算基盤の一部として扱い、ガードコードへの未承認の手動編集を拒否します。結局のところ、ユーザーは指定された不変量が実際には偶然違反されることが不可能であるという監査可能な確実性を得るとともに、企業は Go、TypeScript、Python、Rust のような複数の言語をサポートする単一ツールの恩恵を受け、ハンドラーコードに散在するセキュリティ失敗を大幅に削減できます。

本文

いくつか最も深刻なソフトウェアバグが、同時に最も退屈なのも事実です。ユーザーが他のテナントのデータを読み込むことを許してはなりません。これは誰も異議を唱えず、システム設計レビューにおいて「A 氏が B 氏の記録を読むこと」を防ぐための対抗意見を立てる者は一人もいません。にもかかわらず、「アクセス制御の不備」は依然として OWASP Top 10 の第 1 のカテゴリーとなっています。

これらのバグが製品に組み込まれてしまうのは、規則をシステムの誤った位置に配置したからであります。その規則はプロンプト(指示文)に置かれ、レビューチェックリストの項目にされ、「すべての将来のエンジニア」、そして今や「すべての将来的なモデル呼び出し」もその不変条件(invariant)を覚えていて正しく再適用するという共有された期待の中に存在しています。

この前提はもともと脆弱であり、AI がコードの大部分を生成する現在では outright に失敗します。当然のことを行っても構いません:規則を CLAUDE.md に置くこと、慎重なシステムプロンプトを作成すること、エージェントの指示に「認可(authorization)は非常に重要である」と加えることなどです。そのようにすべきなのは確かですが、モデルが 16,000 行ものコードを書き上げた後の真の問題は、「そのコードが望む通り動作していることをどのように知っているか」という点にあります。テストも役立ちますが、テストは実証的(empirical)でありすぎます。 tester とモデルが書き残すケースをチェックするに留まり、来週の誰かが追加するハンドラについて語ることはできません。

私は別のレバーを引きたいと考えています。率直に言えば私の賭けは次の通りです:広範なクラスの生産用ソフトウェアに対しては、「構造的なバックスプレッシャー(構造による制約)」の方が、エージェントの知能への漸進的改善よりも優れています。既存のモデルはすでにあなたのコードのほとんどを記述できますが、制限要因となっているのは「彼らが望むとおりに動作していることを知ることができるか」という点であり、その知識はモデルが構築する際の基盤(substrate)から得られ、より賢いモデルを待つことからは得られません。

Shen-Backpressure は、その賭けを検討するために私が構築したツールおよび方法論です。ここでは実行可能なデモを通じてそれが何を行うかを示し、続いてどのようにそれをあなたのプロジェクトのループに接続するかを示します。

振る舞いによるゲートと構造的なゲート

多くのプロンプトレベルの制約は「振る舞いによるゲート(behavioral gate)」です。モデルには「認可をスキップしないこと」「入力を検証すること」「共有ヘルパーを使用すること」などと伝えます。モデルはこれらの指示に十分な頻度で従っては有用ですが、同時に不十分な頻度で失敗し、その全体としての仕組みを不安定なものにします。振る舞いによるゲートは、モデルが規則を記憶し、適用範囲を認識し、局所的な文脈の重力的な引力に抗する能力に依存しており、さらに人間レビューヤーがコードベース全体を通じて同じ不変条件を維持しなければなりません。

一方、構造的なゲート(structural gate)は異なります。コンパイラ、型チェッカー、テストランナー、リンター、証明チェッカーなどです。それぞれがその前にあるアティファクト(生成された成果物)について具体的な答えを生み出します。その答えは完璧ではありませんが、それは現実であり、その範囲内ではコードが間違っていれば拒否します。

その「拒否」こそが目的です。これにより、仕事をモデルの指示領域から抜き取り、モデルが構築を続ける基盤へと移すことができます。トークンを費やしてモデルに不変条件を覚えておいてほしいと beg を代わりに、コード自体の配列を工夫し、偶然に違反されにくいようにします:最も重要とする属性を機械が検証できる形に変換し、実装へと投影し、そのチェックに対してループを跳ね返らせ、創発する成果物がそれを満たすまで続けます。

これが、Geoff Huntley の Ralph または論文『あなたのバックスプレッシャーを浪費しないでください』において使用される用語の意味における「バックスプレッシャー」が力を持つ理由です。前回のエラーが次のイテレーションにパイプされるとき、決定論的なゲート(deterministic gate)はループに、「フィーリング(vibes)」よりも固いものを押し返すための何かにします。そのループはもはやニッチなアイデアではなく、Codex CLI が現在

/goal
をリリースしており、OpenAI 自身による Ralph ループの解釈として、ターンを超えて目標を維持し、達成されるまで止まらずに拒否する仕組みを持っています。

基盤への移行

強制すべき不変条件は、通常は正確な表現が容易です。ユーザーは認証済みであり、テナントメンバーであり、かつそのリソースがそのテナントに属している場合のみ、リソースにアクセスできるといったことは、完全で有界された規則です。英語はそれを強制するための不適切な媒体です。

Shen-Backpressure は、その種類の規則を、モデルがターゲット言語の型、コンスストラクター、ゲートコマンドに対して記述しなければならない形において、機械に投影可能な形式に変換するために、静的型付けされた Lisp の一種である Shen を使用します。一度に仕様(spec)を書き、コードジェネレーター

shengen
がそれをターゲット言語へのガードタイプへ降下(lower)させます。モデルが Go や TypeScript を記述している場合でも、Shen が存在することを知る必要はありません。コンパイルできるコードであり、ゲートを通すだけの必要があります。

マルチテナント認証のための証明連鎖

マルチテナント API デモの心臓部である、

specs/core.shen
から抜粋されたものです:

(datatype jwt-token
  X : string;
  (not (= X "")) : verified;
  ============================
  X : jwt-token;
)
(datatype tenant-access
  Principal : authenticated-principal;
  Tenant : tenant-id;
  IsMember : boolean;
  (= IsMember true) : verified;
  ================================
  [Principal Tenant IsMember] : tenant-access;
)
(datatype resource-access
  Access : tenant-access;
  Resource : resource-id;
  IsOwned : boolean;
  (= IsOwned true) : verified;
  ================================
  [Access Resource IsOwned] : resource-access;
)

水平線が役目を果たします。線の上の前提条件は、下の結論が構築される前に満たされなければなりません。

resource-access
を得るには
tenant-access
と、リソースが所有されていることの証明が必要であり、
tenant-access
を得るには認証されたプリンシパルとメンバーシップの証明が必要です。完全な連鎖は
jwt-token
authenticated-user
tenant-access
resource-access
のようになります。完全な仕様については中間の規則を確認してください。

これらの型は「証人(witness)」です。そのいずれかの値を構築するには、その規則に宣言された前提条件を解除(discharge)する必要があります。

仕様からガードタイプへ

shengen
は各規則をターゲット言語内のガードタイプへと降下させます。Go の場合、フィールドは非公開になり、生成されたコンスストラクターがそれらを満たす唯一の手段となります:

type TenantAccess struct {
	principal AuthenticatedPrincipal
	tenant    TenantId
	isMember  bool
}

func NewTenantAccess(principal AuthenticatedPrincipal, tenant TenantId, isMember bool) (TenantAccess, error) {
	if !(isMember == true) {
		return TenantAccess{}, fmt.Errorf("isMember must equal true")
	}
	return TenantAccess{principal: principal, tenant: tenant, isMember: isMember}, nil
}

ここでは奇抜なトリックはなく、単なる通常の Go の可視性です。パッケージ外からのコードはフィールドが小文字であるため

TenantAccess{isMember: true}
を記述することはできません。コンスストラクターだけが値を保持したオブジェクトへの唯一のパスであり、それは
isMember == false
を拒否します。
authenticated-principal
のようなサムの型も同様により、密封されたインターフェースを取得します。生成されたガードを確認してください。

Go はこの投稿全体にわたって例として使用されますが、概念やツールは Go 固有ではありません。Go と TypeScript は現在の生産向けターゲットであり、Python と Rust への参照エmitter もあります。ターゲット言語は実際の選択肢で、実際のトレードオフを持っています:シール(密封)の強度は言語が提供するカプスレーションによって決まり、エージェントもまた言語中立ではありません。

スマートコンスストラクターは古いです。型ラッパーは古いです。コード生成も古いです。有用な動きは、それらをループの一部として配置し、その Enforcement コードよりも短くレビューしやすい仕様から単一の拒否表面(refusal surface)を導き出すことです。

マルチテナントハンドラを書く通常の通りは、各エンドポイントに

if
を置くことです:

if !user.IsMemberOf(tenantID) {
    http.Error(w, "forbidden", http.StatusForbidden)
    return
}

このパターンも理にかなっていますが、まさに第七のハンドラや第三のリファクターで忘れられる種類の「理にかなったこと」です。Shen-Backpressure バージョンではメンバーシップチェックも依然存在します。データベースクエリも存在しますが、それはハンダラー全体に散在する慣習ではなく、

TenantAccess
の構築境界に集中しています:

isMember := exists > 0
access, err := shenguard.NewTenantAccess(principal, tenantID, isMember)
if err != nil {
    return shenguard.TenantAccess{}, fmt.Errorf("tenant access denied: %s is not a member of %s", userID, tenantID.Val())
}

ハンダラーは、すでに通過した連鎖を表現する値に対して動作します。証明はその値と共に移動します。実行中のデモでは、Acme のメンバーである A 氏は Acme リソースのリストを表示できますが、Globex のリソースには拒否されます:

=== Alice requests Globex resources (NOT member - should fail) ===
tenant access denied: user u-alice is not a member of tenant t-globex

エージェントがこの連鎖をスキップして生値(raw value)を渡そうとする場合、バイナリが存在する前にビルドが失敗します:

cannot use tenantID (variable of type string) as shenguard.TenantId value
    in argument to CheckTenantAccess: string does not implement
    shenguard.TenantId (missing method Val)

その短い機械的な「いいえ」こそがバックスプレッシャーです。私はこれらをもっと多く、プロンプトの段落はもっと少なく欲しいです。

やってみましょう

デモは最初から最後まで読むことを意図して構築されています。リポジトリをクローンして

examples/multi-tenant-api/
を開くと、仕様、生成されたガード、そのループを構築した Ralph ループ(
cmd/ralph/
)、そして
demo.md
の cURL スクリプトが含まれています。

これを自分のプロジェクトに接続するには、

sb
CLI をインストールして実行します:

sb init    # 仕様に core.shen + ゲートスクリプトをスケルフトする、
           # .claude/sb ループに /sb:* コマンドをインストールする、
           # ゲート駆動によるバックスプレッシャーを持つ Ralph ループを実行する

sb init
は起動用の仕様とゲートスクリプトをスケルフトし、
-config
を指定すると
sb.toml
マニフェストもスケルフトします。ループの各イテレーションは、
sb.toml
で宣言された固定セットのゲートを走査します:

ゲートコマンド捕捉する事項
shengen
Shen 仕様と生成されたガード間のドリフト
go test ./...
ランタイム不変条件の失敗および通常の退化
go build ./...
型シグネチャの不整合、無効な証明連鎖の使用
shen tc
+
bin/shen-check.sh
Shen 仕様の内部一貫性の欠如
tcb audit
+
bin/shenguard-audit.sh
生成されたガードコードへの手動編集

これら 5 つがデフォルトセットです。

sb
は、明示的に構成された場合のみ実行される、第六のゲート(
shen-derive
、仕様同等性テスト用)という、まだ実験的なオプションゲートも持っています。ゲートが失敗すると、その失敗は具体的な文脈として次のプロンプトにフィードされます。それがバックスプレッシャーです。あなたが手動でループを驅動したい場合は、イテレーションの間に
sb
ゲートを自分で実行できます。ハネス(harness)はプラグ可能で、デフォルトは Claude Code(
claude -p
)ですが、Cursor や Codex も
RALPH_HARNESS
を設定することで動作します。ゲート 4 は Shen ランタイムを必要とします:
brew tap Shen-Language/homebrew-shen && brew install shen-sbcl
。また、
sb init -lang ts
は TypeScript 用の全ゲートループを接続し、コード生成だけでなく完全に Go と並ぶターゲット言語となります。さらに、
/sb:*
コマンド
sb init
がインストールする
.claude/
には、新しいターゲット言語向けの
shengen
イミッターを生成するための完全なプロンプトである
/sb:create-shengen
も含まれています。

コストと限界

仕様に書き込むことは無償ではありません。どの不変条件をエンコードするかを決め、両に読みやすく投影可能なノテーションで表現し、ジェネレーターとオーディットスクリプトを維持する必要があります。生成されたガードコードは聖なるものであり、手動で編集するとオーディットゲートが拒否します。あなたの信頼すべき計算基盤(trusted computing base)には、Shen 型チェッカー、ジェネレーター、ターゲットコンパイラが含まれます。

これでもバイパスを不可能にすることはできません。ここがターゲット言語のトレードオフが本当に浮き彫りになる場所です。Go の場合、ガードパッケージ内のコードは値を偽造できるかもしれませんし、反射とゼロ値も理論的にはエスケープハッチとして利用可能です。不注意な SQL クエリは、コンスストラクターにそれがあるべきではない

true
を渡すことができます。私の主張は意図的に狭く設定されています:
shengen
を使用して仕様の証明をターゲット言語へ降下させることは、指定された不変条件を偶然にバイパスすることを事実上不可能にし、完全に不可能にすることではありません。形式手法の聴衆にはこれは特筆にも値せず、わりと弱い主張です。しかし、LLM 生成コードを製品化している実行者にとっては非常に高いレバレッジを持つツールです。今では、忘れられたチェック、リークしたテナント ID、コピーされて不完全なハンドラーは、偶然に導入することが構造的に難しく高コストとなりました。

仕様自体が間違っていることも、ジェネレーターがドリフトすることも、テストがケースを逃すことも可能です。これらの限界を名指しすることは、ツールを理解し、提供するものを規律を持ってレバレッジするために重要です。

これらゲートをインストールするコスト自体も下がっています:仕様に書くこと、イミッターを書くこと、オーディットスクリプトを書くことは、モデルがずっと上手くなっている作業です。より良いモデルは基盤を不要にしません;それらはそれをスキップすることを正当化しにくくします。

結論(テーゼ)

生産用 AI コディングループにおいては、より良いモデルよりも、より良いバックスプレッシャーが必要です。アティファクトが意図する形状を持っているかどうかを示す決定論的なシグナルが必要なのです。テストは一つのそのようなシグナルを提供し、コンパイラのもう一つ提供し、Shen 仕様に降下したガード型はコンパイラの拒否表面をさらに拡張します——デザイン意図からコードそのものへ移動する証明形状の制約です。

これらはいずれもより良いモデルに対する賭けではありません。しかし能力と確信は異なります。「モデルは信頼できる」というのは書き手についての主張であり、「このアティファクトが不変条件を保持している」は目の前の一つのオブジェクトについての主張です。誰かが、あなたが思いつくすべてのテストを通過する実装をフィーリングコーディング(vibe coding)し得ていても、その実装を書いた人の信頼性(モデルか人間か)はまだ、構造的ゲートがアティファクト自身について何を告げるかには教えてくれません。これが、間違いの道が偶然に取りづらくなっていることがモデル能力のあらゆるレベルで重要である理由です。

そして、あなたがその確信を与える同じゲートは、それを証明するアティファクトもあなたに与えます。「私たちは有能なモデルを使った」ということは規制官や監査人に渡すことができませんが、仕様が、通過したゲート、および緑の CI ラン(CI の実行完了)は渡せるものです。

同じ日のほかのニュース

一覧に戻る →

2026/05/20 22:43

GitHub、悪意のある Visual Studio Code エクステンションによる 3,800 リポジトリの侵害を確認。

## 日本語翻訳: GitHub は、従業員が悪意のある Visual Studio Code (VS Code) 拡張機能のインストールによって、約 3,800 の内部リポジトリが侵害された重大なセキュリティインシデントを確認しました。主な影響は、機密性の高い GitHub 内部のソースコードと、ハッカーグループ「TeamPCP」がサイバー犯罪フォーラムで所持していると主張する約 4,000 つのプライベートリポジトリの漏洩可能性がある点にあります。このインシデントは、ソフトウェアサプライチェーン内で長年見られる課題を浮き彫りにしており、過去には悪意のある拡張機能が認証情報を窃取したりマルウェアを配布したりするために利用されてきました。特に以前の年には、数百万回のインストール数を誇りながらセキュリティリスクにより削除されたトロージャン化された VS Code 拡張機能や、クリプトStealing の拡張機能、データを漏洩させる AI ベースのコーディングアシスタントを含む他のインシデントもありました。これら過去の事例は外部ユーザーを標的としたものであったのに対し、今回のインシデントは GitHub の自前のインフラストラクチャと開発チームに限定されており、これらの内部リポジトリの外に保存された顧客データに影響があったという証拠はありません。

2026/05/21 6:33

Google がウェブに対して「宣戦布告」に出たとして言われている。

## Japanese Translation: Google は、オープンウェブのリンクを AI が生成したサマリー(「AI オーバービュー」)に置換する活動を積極的に進めており、これは閉鎖的で管理されたインターネットを創出するというリスクを孕んでいます。現在、ウェブは開かれた文化的リソースとして扱われるべきですが、Google は自社の独占的なニーズを満たすために情報を文脈から切り離し、既存のデータを報酬なしの原材料として使用し、事実上その独り占め体制を支えています。このアプローチは、かつて企業が行ってきた「壁の中庭(walled gardens)」建設の試みに酷似しており、不制御された外部世界に対して安全でフィルタリングされたインターフェースを提供しています。この動きはリンクから LLM 生成のレスポンスへ移行するものであり、時々誤っている答えを提供することで、ウェブに対する Google の独占的な管理層を確立し、ウェブサイト、ユーザーの創作活動、デジタルアートが synthetic generation に餌を与える限り、それらを無関係にしてしまうという脅威をもたらしています。業界基準がこの優越性に適応して変化するリスクもあり、将来的には早期のアール「slopified AOL」に類似した、劣化しアルゴリズムによってキュレートされたプラットフォームとなる可能性があります。アクセスは Google のアルゴリズムが「関連する」と判断したコンテンツに限られます。主な影響は、デフォルト設定に依存するユーザーの情報多様性の低下です。真理および文化へのアクセスの独占に対抗するためには、個人はすぐにデジタル習慣を「De-googlify」する必要性に直面しており、代替検索エンジンへ移行し、Chrome を避ける必要があります。情報の独占化へのこのシフトはオープン標準にも脅威を与え、Google の「安全な」抽象化と対照的に、参加型ウェブに対して非難ラベルが適用される可能性があります。記事は Patreon での呼びかけで締めくくり、本文はクリエイティブ・コモンズアトリビューション・シェアアライク 4.0国際ライセンスの下で提供されていることを示しています。

2026/05/18 11:04

N トークン毎秒とは、実際にはどのような速度なのでしょうか?

## 概要: この報告書の中核的なメッセージは、ローカル LLM のパフォーマンスが単なる生速度だけでは決定されるのではなく、主にコンテンツタイプとハードウェアの制約に大きく依存することである。スループットベンチマークは、コード、テキスト、思考/推論、エージェントの 4 つの明確なストリーミングモードを明らかにしており、同等のトークン率においてでも識別子の高い密度のためプロース(文章)に比べてコードが著しく遅く感じられる。補足のために、本研究では長い識別子を分割する特定のパターン付き BPE(Piece-wise Byte Encoding)方式のトークナイゼーション手法を使用しており、例えば「processUserInput」は「process」「User」「Input」に分けられ、句読点や演算子もトークンとして扱われる。これは tiktoken や Claude のトークナイザーなど一般的なツールとは異なる。テスト範囲は広く、Raspberry Pi クラスのデバイスから 4090 などのハイエンド GPU、Groq などのクラウドサービスまでをカバーしている。重要な知見として、ハイエンドシステムではハードウェアが 1 秒あたり最大 800 トokens を処理できる一方で、実際のユーザー体験は人間の視覚処理速度で決定される上限に達し、極限スピードにおいてはボトルネックは計算能力からシフトして、人が画面を閲覧または視聴する速さという要因に移行する。したがって、これらのモデルを展開する企業は、これらの 4 つの特定のストリーミングモードに合わせて期待値と最適化戦略をカスタマイズし、ユーザーのニーズに合わせる必要がある。

AI コーディング・ループにおける形式検証ゲート | そっか~ニュース