policy.yaml

policy.yaml の完全なスキーマです。概念 — レイヤー、floor、評価順、信頼 — は policies ガイド にあります。

ファイル

~/.config/loopkeep/policy.yaml        # home layer
<workspace>/.loopkeep/policy.yaml            # project layer(commit する)
<workspace>/.loopkeep/policy.local.yaml      # project-local layer(gitignore する)

完全なスキーマ

version: 1

policies: # 名前付き policy: 再利用できる振る舞いのまとまり
  ask-me:
    level: ask-first # 必須
    timeout: # 任意。waiting 中の run にのみ
      after: "72h"
      then: abort # abort | deny

rules:
  - id: infra-approval # 必須、ファイル内で一意
    policy: ask-me # このファイルで定義した名前付き policy を参照…
    # level: ask-first          # …もしくはレベルをインラインで持つ — 両方は不可
    # timeout: { ... }          # インライン形式も timeout を持てる
    match:
      paths: ["infra/**"] # gitignore 形式の glob、workspace 相対。リスト内は OR
      tool: [bash, edit] # リスト内は OR、キーどうしは AND
      tags: [migration] # x-loopkeep.tags / harness が割り当てた tag に一致
      workflow: [deploy, "release-*"] # run の workflow 名。完全一致 + * glob
      command: ["migrate"] # 生コマンドの部分一致、大文字小文字を無視、いずれか一致
    allow_override: false # floor ルール: どの layer も緩められない(既定: true)
    reason: "Production infra always gets a human"

defaults:
  level: notify # どのルールにも一致しないとき。最も厳しく宣言した layer が勝つ

delivery: # 個人 layer のみ。配信を整え、レベルは変えない
  digest: { cron: "0 9 * * *" }
  quiet_hours: ["23:00-07:00"] # notify の配信を保留する。ask-first は常に鳴る

# 任意、個人 layer のみ: リポジトリの .claude permissions.ask を
# ask-first の引き上げとして取り込むのをオプトアウトする。
import_repo_ask: false

レベル

auto-approve < notify < ask-first < deny。順位が意味を持ちます。floor と 自己申告の引き上げは最大値を取ります。

match の意味論

  • paths — gitignore 形式: ** は任意の深さ、* は 1 セグメント内、? は 1 文字、[...] は文字クラス。brace 展開はなし。workspace ルートからの相対で照合。
  • tool — アクションのツール名。MCP ツールは mcp:<server>/<tool>
  • workflow — 完全一致に加え * glob。評価に workflow 名がないとき (例: --workflow なしの lk policy test)、workflow 制約を持つルールは 一致しません。
  • command — 部分一致、大文字小文字を無視、いずれかの要素が一致。同じ「文脈なし」 ルール: 生コマンドがなければ一致しません。シェル変数でかわせます — floor をこれに 作らないでください。
  • 空・省略した軸は無制約です。存在するすべての軸が一致しなければなりません(AND)。

名前付き policy

ファイルごとに定義します。policy: の参照は同じファイル内でのみ解決されます。 未知の参照はパースエラーです。policy:level:/timeout: の両方を持つルールは エラーです — 振る舞いは 1 か所にあります。

ルールの timeout

そのルールで止まった waiting 中の run に適用されます。期限が切れると run は abort され(または then: に従ってアクションが deny され)、その決定は timeout として 記録されます。timeout がなければ、waiting 中の run はいつまでも待ちます — 見えて いて、勝手に決められることはありません。

CI で policy をテストする

lk policy test は daemon なしで動き、結果から exit code を決めます — --expect <level> は 0/1 を、--expect なしはレベルの順位(0–3)を返し、エラーは exit ≥ 10 です。policy の変更も、ほかのコードと同じようにテストと一緒に出せます。 CLI リファレンス を参照してください。

スターター policy

lk init はこれを書きます:

version: 1
rules:
  - id: block-deploy
    match:
      tags: [deploy]
    level: ask-first
    allow_override: true
defaults:
  level: notify

すべては notify、deploy タグの付いたものは ask first。緩めるにも締めるにも使える、 意図的な出発点であって、推奨ではありません。