ポリシーと信頼

policy はアテンションのルーターです。エージェントが提案するすべてのアクション — 編集、コマンド、MCP のツール呼び出し — は、実行される前に 決定的にあなたの ルールで評価され、4 つのレベルのいずれかに振り分けられます。エージェントが自分の レベルを決めることはありません。

レベル何が起きるか
auto-approveあなたなしで実行。通知なし。
notify実行し、あなたに知らせる — 望めば digest にまとめる。
ask-firstrun は止まり、受信箱であなたの決定を待つ。
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 つの軸で突き合わせます。pathstooltagsworkflow、そして command(生のシェルコマンドに対する部分一致)です。ルールはレベルをインライン (level:)で持つか、名前付き policy を参照します(policy:)— 両方は不可です。 完全なスキーマは policy file リファレンス にあります。

2 つの軸には注意が要ります。tags は workflow の自己申告で、command はシェル変数で かわせます — 便利なケースのエスカレーションに使い、硬い floor はエージェントが 書き換えられない pathstool で書いてください。

評価の仕組み

提案された各アクションについて:

  1. default を解決する — project-local → home → project の順で最初に一致した default ルール。なければ、どこかのレイヤーが宣言した最も厳しい defaults.level
  2. floor を計算する — すべてのレイヤーで一致する allow_override: false の ルールのうち最大のレベル、加えて組み込みの floor。
  3. 自己申告を適用する — エージェントは自分のアクションを sensitive と申告できます。 これはレベルを 上げる ことしかできず、下げることはできません。
  4. 最終レベル = この 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 にすればオプトアウトできます。