mcpField
P
policy-algebra

policy-algebra

github.com/camachoエージェントワークフロー551 回インストール
リポジトリ

policy-algebra について

policy-algebra は、短い意図や詳細な計画から凍結済みの Starlark ガバナンスルールを生成するスキルです。レビューや任意のファイル出力に加え、正規化した内容で差分を検出できます。

主な機能

  1. 01意図やファイルから不変条件を抽出
  2. 02Starlark でガバナンスルールを作成
  3. 03凍結前にドラフトをレビュー
  4. 04ルールブロックをファイルに保存
  5. 05--verify で差分を確認

活用シーン

  1. 01短いポリシーの意図からルールを生成
  2. 02計画の制約をガバナンスルールに変換
  3. 03保存済みルールブロックの差分を確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/camacho/ai-skills --skill policy-algebra

インストール後、Claude Code で/policy-algebraを入力して読み込まれたか確認します。

詳細

/policy-algebra

簡潔な意図の文字列(詳細なインタビュー)または詳細な計画入力(簡単な確認)から、凍結され、ドリフトをチェックできるガバナンスルールを生成します。呼び出し元が後続の作業に挿入できるフェンス付き Starlark ブロックを生成し、正規化したうえでドリフトを検出する --verify を提供します。

呼び出し方法

/policy-algebra <target>                      # generate rules
/policy-algebra <target> --write <path>       # generate + persist raw block
/policy-algebra --verify <frozen> <candidate> # drift check

<target> は、読み取り可能なファイルパス(SHALLOW モード)または意図の文字列(DEEP モード)です。

適応型入力検出

if target is a readable file path:
    mode = SHALLOW
    input = read(target)
else:
    mode = DEEP
    input = target

DEEP フロー

  1. /grill-me 用の枠組みとなるプロンプトを作成します。

    「次の内容について、ルールの不変条件を抽出するためにユーザーへインタビューしてください。 <target prompt>

    次の点に関する質問に重点を置いてください。

    • 範囲:このルールはどの成果物/イベント/フェーズを対象としますか?
    • 不変条件:常に真でなければならないことは何ですか?決して起きてはならないことは何ですか?
    • 変数の空欄:インスタンス間で何が変わりますか?
    • 結合子:既存の演算子(+、diff、intersect、メソッド呼び出し)で十分ですか?それとも新しいヘルパーが必要ですか?
    • 失敗モード:ルールを満たせない場合、どうなりますか?

    自然言語で述語を構造化したリストとして返してください。 /policy-algebra が出力から Starlark を作成します。」

  2. Skill ツールを使い、このプロンプトを指定して /grill-me を呼び出します。

  3. /grill-me の出力を不変条件のリストとして取得します。

  4. 下書き作成に進みます(SHALLOW フローのステップ 5)。

SHALLOW フロー

  1. ファイルの内容を読み取ります。
  2. 不変条件の宣言をスキャンします。「Invariants」「Rules」「Constraints」などの見出し、MUST/NEVER/ALWAYS を含む箇条書き、述語のようなコードブロックを確認します。
  3. これらを不変条件のリストとして抽出します。
  4. 抽出できた不変条件が 2 つ未満、または内容が曖昧な場合は、ファイルの内容をターゲットとして DEEP モードに移行します。
  5. notation.md の規約に従って、不変条件のリストから Starlark を作成します。
  6. 下書きを /review に渡します(パネルのヒントは指定しません。/review が編成します)。
  7. /review が収束すれば凍結します。上限に達した場合は、/review のエスカレーションをそのまま適用します。

下書きの規約

対象ごとにまとめます(まず DEFAULTS、次に名前付き関数)。各関数本体は 5 行以内にし、関数ごとに説明コメントを 1 つ付けます。変更は行いません。ルールの全容については notation.md を参照してください。

凍結して返す

/review が APPROVE した後、Starlark のテキストを正確に FROZEN ブロックとして取得します。凍結時に正規化してはいけません。正規化は比較時のみ行い、凍結と返却の処理を単純に保ちます。

出力形式:

ALGEBRA:
```starlark
<raw frozen starlark block, as /review approved>

REVIEW_ROUNDS: PANEL: STATUS: CONVERGED FILE: (「--write」を使用した場合のみ) NOTE: (任意)


If `--write <path>` was supplied, write the raw Starlark block to that path and include `FILE: <path>` in the return block.

## `--verify` flow

1. Read both files.
2. Extract first ` ```starlark ` fenced block from each file.
3. Normalize both blocks (strip trailing whitespace, collapse blank lines, trim edges).
4. If equal → print `MATCH`, exit 0. Else → print `DRIFT` + unified diff, exit 1.

Use the following bash to verify drift — no external dependencies needed:

```bash
# policy-algebra verify — inline, no dependencies
# Usage: bash verify.sh <frozen_file> <candidate_file>
normalize() { sed 's/[[:space:]]*$//' | sed '/^$/d'; }
extract_starlark() { sed -n '/^```starlark/,/^```$/p' "$1" | sed '1d;$d'; }

FROZEN=$(extract_starlark "$1" | normalize)
CANDIDATE=$(extract_starlark "$2" | normalize)

if [ "$FROZEN" = "$CANDIDATE" ]; then
  echo "MATCH"
  exit 0
else
  echo "DRIFT"
  diff <(echo "$FROZEN") <(echo "$CANDIDATE")
  exit 1
fi

複数ブロックの動作

ファイルに ```starlark ブロックが複数含まれる場合、extractAlgebra は最初のブロックのみを暗黙的に使用します。これは意図的な動作です。あらゆるドキュメントで、正規ルールを最初のフェンス付きブロックに記述してください。

失敗モード

失敗動作
ターゲットが省略されているエラー:「target required」
SHALLOW:ファイルを読み取れないパス文字列を意図として DEEP に移行
SHALLOW:抽出可能な不変条件が 2 つ未満ファイルの内容を意図として DEEP に移行
DEEP:/grill-me を利用できないエラー:「deep interview requires /grill-me skill」
DEEP:ユーザーがインタビューを中断/grill-me の終了時の動作をそのまま適用
下書きの Starlark が空エラー:「no invariants found to codify」。不変条件のリストを返す
/review が収束せず上限に達した/review のエスカレーションをそのまま適用し、独自の処理は行わない
--write <path> の書き込み先に書き込めないパスを含むエラーを返しますが、インラインの結果も返します
--verify のいずれかのパスを読み取れないパスを含むエラーを返し、終了コード 2
```starlark ブロックがないNoAlgebraBlockError とパスを返し、終了コード 2
canonicalize が例外をスロースタックトレースを含むエラーを返し、終了コード 3

終了コード

コード意味
0MATCH(verify)/SUCCESS(通常)
1DRIFT(verify のみ)
2入力エラー(ファイルがない、不正な引数、NoAlgebraBlockError)
3内部エラー

ツール共通の注意事項

  • Claude Code:Skill ツールを使って、/grill-me(DEEP インタビュー)と/review (パネルによる合意形成)を呼び出します。どちらもプロジェクトローカルの スキルとして.claude/skills/にあります。
  • Codex / Cursor:Skill ツールは Claude Code 専用です。該当するスキルファイルを直接読みます。
    • .claude/skills/grill-me/SKILL.md — インタビュー手順
    • .claude/skills/review/SKILL.md — パネルによる合意形成 コマンドとして呼び出すのではなく、手順をその場で適用します。 この SKILL.md のドラフト作成、凍結、--verifyのロジックは ツールに依存せず、Claude Code、Codex、Cursor で同じように動作します。
  • **CLI(--verifyパス)**は実行環境に依存しません。上記の--verifyセクションにあるインラインの bash スニペットを使ってください。Node や pnpm は不要です。

ガバナンス

このスキルはセルフホスト可能です。独自のルールは、凍結された Starlark ガバナンスブロックとして記述されています。これらの不変条件からの逸脱はバグです。/policy-algebra --verifyで検証してください。

# policy-algebra governance — self-hosted
# FROZEN — do not edit; regenerate via /policy-algebra

DEFAULTS = {
    "min_invariants": 2,
    "exit_codes": {"match": 0, "drift": 1, "input_error": 2, "internal_error": 3},
    "required_output_fields": ["ALGEBRA", "REVIEW_ROUNDS", "PANEL", "STATUS"],
    "converged_status": "CONVERGED",
}

# SELECT_MODE: file path → SHALLOW; intent string → DEEP.
def SELECT_MODE(target):
    if is_readable_file(target):
        return "SHALLOW"
    return "DEEP"

# SHALLOW_OR_DEEP: fall through to DEEP when extraction yields < min_invariants or is ambiguous.
def SHALLOW_OR_DEEP(invariants, ambiguous):
    if len(invariants) < DEFAULTS["min_invariants"] or ambiguous:
        return "DEEP"
    return "SHALLOW"

# EXTRACT_BLOCK: use first starlark fence only; multiple blocks → first wins.
def EXTRACT_BLOCK(fences):
    if len(fences) == 0:
        return None
    return fences[0]

# OUTPUT_VALID: output must carry all required fields; STATUS=CONVERGED only after review.
def OUTPUT_VALID(output, review_loop_passed):
    fields_present = all([f in output for f in DEFAULTS["required_output_fields"]])
    converged_ok = output.get("STATUS") != DEFAULTS["converged_status"] or review_loop_passed
    return fields_present and converged_ok

# VERIFY: canonicalize both blocks and compare; never modify source files.
def VERIFY(frozen_canon, candidate_canon):
    if frozen_canon == candidate_canon:
        return DEFAULTS["exit_codes"]["match"]
    return DEFAULTS["exit_codes"]["drift"]

# EXIT_CODE: map outcome strings to numeric codes.
def EXIT_CODE(outcome):
    return DEFAULTS["exit_codes"].get(outcome, DEFAULTS["exit_codes"]["internal_error"])

コメント