ポリシーと信頼
policy はアテンションのルーターです。エージェントが提案するすべてのアクション — 編集、コマンド、MCP のツール呼び出し — は、実行される前に 決定的にあなたの ルールで評価され、4 つのレベルのいずれかに振り分けられます。エージェントが自分の レベルを決めることはありません。
| レベル | 何が起きるか |
|---|---|
auto-approve | あなたなしで実行。通知なし。 |
notify | 実行し、あなたに知らせる — 望めば digest にまとめる。 |
ask-first | run は止まり、受信箱であなたの決定を待つ。 |
deny | アクションはきっぱり拒否。run は続き、監査記録が残る。 |
policy の置き場所
~/.config/loopkeep/policy.yaml # home — あなた、すべての project で共通
<workspace>/.loopkeep/policy.yaml # project — チーム、commit してレビューする
<workspace>/.loopkeep/policy.local.yaml # project-local — あなた、この project だけ(gitignore する)
レイヤーは意図的に「最も近いものが勝つ」ではありません。2 種類のルールは異なる 振る舞いをします:
- default は出発点です。project-local → home → project の順で解決し、最初に 一致したものが勝ちます — project の default はいつでも自分向けに上書きできます。
- floor(
allow_override: false)は交渉不能の最低ラインです。すべてのレイヤーに またがる、一致するすべての floor が適用され、最も厳しいものが勝ちます。これは 両側に効きます。チームの floor をあなた個人の設定で緩めることはできず、home policy の floor は、信頼していないリポジトリの中でもあなたを守ります。
ルールを書く
ルールはアプリの ポリシー 画面(project のレイヤー)または 個人ポリシー(home の
レイヤー)で編集します。Rules Editor フォームが 1 項目ずつ組み立て、Raw タブが
ディスク上の policy.yaml そのものを持ちます。ファイルを直接編集してもかまいません。
スキーマはどちらでも同じです:
version: 1
policies:
ask-me: { level: ask-first, timeout: { after: "72h", then: abort } }
rules:
- id: prod-migration
match:
paths: ["migrations/**", "infra/prod/**"] # gitignore 形式の glob、リスト内は OR
tool: [bash, edit] # 異なる match キーは AND
policy: ask-me
allow_override: false
reason: "Production changes always get a human"
defaults:
level: notify
delivery:
digest: { cron: "0 9 * * *" }
quiet_hours: ["23:00-07:00"]
ルールは 5 つの軸で突き合わせます。paths、tool、tags、workflow、そして
command(生のシェルコマンドに対する部分一致)です。ルールはレベルをインライン
(level:)で持つか、名前付き policy を参照します(policy:)— 両方は不可です。
完全なスキーマは policy file リファレンス にあります。
2 つの軸には注意が要ります。tags は workflow の自己申告で、command はシェル変数で
かわせます — 便利なケースのエスカレーションに使い、硬い floor はエージェントが
書き換えられない paths と tool で書いてください。
評価の仕組み
提案された各アクションについて:
- default を解決する — project-local → home → project の順で最初に一致した
default ルール。なければ、どこかのレイヤーが宣言した最も厳しい
defaults.level。 - floor を計算する — すべてのレイヤーで一致する
allow_override: falseの ルールのうち最大のレベル、加えて組み込みの floor。 - 自己申告を適用する — エージェントは自分のアクションを sensitive と申告できます。 これはレベルを 上げる ことしかできず、下げることはできません。
- 最終レベル = この 3 つの最大値。
floor がより低い default を上書きしたとき、その引き上げは監査イベントとして記録され ます — 監督が実際に働いた瞬間が見えます。
組み込みの floor
loopkeep 自身の監督の仕組みへの書き込みは常に ask first で、どのレイヤーもこれを
緩められません。対象は、あなたの loopkeep 設定、workspace の .loopkeep/
ディレクトリ(エージェントが正当に作業する run の worktree は除く)、実行中の
workflow 自身の定義ファイル、loopkeep のバイナリ、そしてイベントログです。シェル
コマンドも検査されます — 保護されたパスへ書き込む、または生のテキストにそれを含む
bash の呼び出しは floor がかかります。エージェントが、自分を監督する policy を
こっそり編集することはできません。アプリは、これらの保護対象を 個人ポリシー 画面に
読み取り専用で一覧表示します。
これを 2 つの backstop が締めくくります。承認画面は常に生の diff かコマンドを主表示 とし(エージェント自身の要約は副次)、verdict なしに実行されているアクションを 検知したら、run はただちに一時停止します。
信頼
clone したばかりのリポジトリは、緩い policy と前のめりなトリガーを積んでいるかも しれません。そこで policy は direnv のように動きます。workspace を信頼するまで、その project policy と自動トリガーは無効です — あなたの home policy と手動の run だけが 動きます。信頼は policy ファイルのハッシュを記録します。あとで編集があると、あなたが diff を承認するまで workspace は信頼されていない状態に戻ります。あなた個人の floor は、 信頼に関係なくどこでも適用されます。
アプリでは、ポリシー 画面でルールを確認して 保存して信頼(または 信頼し直す、
信頼されていないバナーの ポリシーで信頼する)を選びます。ターミナルからは lk trust。
信頼した workspace の trigger を policy を変えずに止めたいときは lk untrust(アプリの
プロジェクト設定 → すべてのトリガーを停止)。承認は残るので、policy が変わっていなければ
lk trust で再確認なしにそのまま再開できます。
explain と test
すべてのアテンションはその provenance を示します — どのルール、どのレイヤー、どの ファイルの何行目か。同じ仕組みをオンデマンドでも使えます。
ポリシー 画面の Check the policy カードは、ツール(と任意の paths・tags)を受け取り、 最終レベルと、どのレイヤーのどのルールが決めたかを表示します。期待するレベルに対して テストすることもできます。
explain は一致した各ルール、そのレイヤーとファイルの場所、上書き可能かどうか、
そして最終レベルを表示します。test は結果から exit code を決めるので、policy の
変更もほかのコードと同じように CI テストに載せられます。
digest と quiet hours
delivery(個人レイヤーのみ)は通知が届く 方法 を整えるもので、レベル は決して
変えません。digest は notify レベルの項目をスケジュールでまとめ、quiet_hours は
notify の配信を夜間保留します。ask-first は常にすぐ鳴ります — あなたで止まっている
run が、朝まで静かに待つべきではないからです。
リポジトリの permission 設定は尊重される
リポジトリの .claude/settings.json があるツールに確認を求めている場合
(permissions.ask)、loopkeep はそれをエスカレーション専用の引き上げとして
ask-first に取り込みます — アクションのレベルを上げることはできても、下げることは
できません。workspace ごと、またはグローバルに、個人レイヤーで
import_repo_ask: false にすればオプトアウトできます。