Skip to content

feat(guardrails): implement 8 anti-pattern guards in profile (plugin/command/permission/skill) #284

Closed

Description

@terisuke

背景

ADR specs/ai-guardrails-anti-patterns.md(PR #283)で、5 リポジトリ横断調査から抽象化した 8 つの実装アンチパターンを OpenCode の仕組みで止める。epic #1 の「plugin- and command-based guardrails」workstream の具体化。

ゴール

packages/guardrails/profile/ に以下のガードを実装し、「ドキュメントではなく仕組み」で 8 パターンを防ぐ。全ガードは反証付き(無効化すると落ちる)で実装すること。

実装内容(Phase 1: 即効)

1. Plugin: 変更の影響範囲ガード(パターン A)

  • ファイル: packages/guardrails/profile/plugins/removal-guard.ts
  • tool.execute.before フック:
    • git rm / git add -A(削除含む)を検知 → 削除対象ファイルを抽出
    • リポジトリ全体で逆被参照 grep → 参照があれば警告ログ + エージェントに確認を強制
  • 反証: ガードを無効化すると、削除時に参照が検出されないことをテストで示す

2. Permission: 並列実行の権限整備(パターン B)

  • ファイル: packages/guardrails/profile/opencode.json の permission
  • 読み取り系 git を allow: git worktree list / git merge-base * / git status* / git log*
  • 破壊系を ask/deny: git worktree add *(ask)/ git branch -D *(ask)/ git push --force*(deny)
  • 反証: subagent が git worktree list を実行でき、git push --force を実行できないことをテストで示す

3. Plugin: セッション開始時の衛生警告(パターン E)

  • ファイル: packages/guardrails/profile/plugins/hygiene-warning.ts
  • event フックでセッション開始時に worktree 数・マージ済み放置ブランチ数をカウント
  • 閾値(worktree > 8 / 放置ブランチ > 10)超えで警告
  • 反証: 閾値以下のリポジトリでは警告が出ないことをテストで示す

4. Command: /plan-light(パターン C / G)

  • ファイル: packages/guardrails/profile/commands/plan-light.md
  • 実装前に「最小の検証パス」(fake テスト → CI → PR)を 1 行で宣言させる
  • 重厚なパイプライン(複数環境・重層レビュー)を提案したら「まず最小パスで」と誘導
  • 反証: 重厚な計画を提示したときに /plan-light が最小パスに誘導することをテストで示す

5. Command: /env-check(パターン D)

  • ファイル: packages/guardrails/profile/commands/env-check.md
  • 新環境を作る前に「既存環境(dev 等)で足りるか」を確認させる
  • 新環境構築は最後の手段であることを明示
  • 反証: 既存で足りるケースで新環境構築をブロックすることをテストで示す

6. Command: /repo-hygiene(パターン E)

  • ファイル: packages/guardrails/profile/commands/repo-hygiene.md
  • 放置ブランチ/worktree/マージ済み残骸を列挙し、削除候補をドライラン提示
  • 実際の削除は実行せず、エージェントの判断を求める

7. Skill: 4 本(パターン F / G / H / A)

  • packages/guardrails/profile/skills/falsifiable-change/SKILL.md(F): 修正は「外すと落ちる」を実測してから報告
  • packages/guardrails/profile/skills/lean-pipeline/SKILL.md(C / G): 最小検証パスをデフォルトに
  • packages/guardrails/profile/skills/self-check/SKILL.md(H): 外部エージェント非依存の客観性証明(結線テスト)
  • packages/guardrails/profile/skills/impact-analysis/SKILL.md(A): 変更前に逆被参照を列挙

受入条件

  • 全 8 パターン(A〜H)に対応するガードが packages/guardrails/profile/ に存在する
  • 各ガードが反証付き(無効化すると落ちるテストが同 PR にある)
  • 既存の guardrail plugin / team plugin と競合しない(新規ファイル)
  • 既存テスト(bun run local:check 等)が green
  • PR は小さく分割可(1 PR = 1 ガード)

参照

Activity

  1. terisuke commented on Aug 3, 2026

    @terisuke
    Author

    追記(2026-08-03): パターン I / J を追加

    ADR を 10 パターンに拡張しました(specs/ai-guardrails-anti-patterns.md の Decision 4 / 5 参照)。以下の受入条件を全ガードの必須条件に追加します。

    I: ガードレールの過剰制限(over-restriction)

    過去の失敗: サブエージェントの git deny 過剰反応 / 「high」ワードでマージ停止(ワードベース誤検知)/ メインがマージ不可・サブ経由のみ可能(権限の非対称)。

    全ガードに必須の証明:

    • 陰性テスト: ガードの対象外である安全な操作(読み取り系 git / 通常の PR / 無関係ワードを含むコメント)がブロックされないことをテストで固定
    • 構造ベース検出: ブロック条件はワード/文字列マッチでなく構造(コマンド種別・対象パス・状態)で判定。「high」等の無関係ワードで発火しないことをテストで示す
    • 権限の対称性: メインエージェントとサブエージェント(team/subagent)で同じガードが同じ挙動。一方だけがブロックされる非対称をテストで防ぐ
    • 反証: ガードを無効化すると危険な操作が通る(ガードが危険パターンを正確に捕捉していることの証明)

    J: CI の過剰適用(変更種別と強度の不一致)

    実測: docs のみの変更(specs 1 ファイル)に e2e / nix-eval / unit / typecheck のフル CI が走る(本 ADR の PR #283)。

    • CI ワークフローに paths-filter を導入し、変更種別でジョブを選択(docs → lint のみ / code → full / ガード変更 → フル)
    • ガード実装(plugin / permission)は「コア相当」としてフル CI を維持(安全側)
    • docs PR で e2e 等の重いジョブがスキップされることを実測
  2. terisuke commented on Aug 3, 2026

    @terisuke
    Author

    実装完了・マージ済み: #285

    • Plugin: removal-guard (A) / hygiene-warning (E)
    • Permission: 読み取り git allow + force-push deny + 対称性テスト (B/I)
    • Command: /plan-light /env-check /repo-hygiene (C/D/E/G)
    • Skill: falsifiable-change / lean-pipeline / self-check / impact-analysis (F/G/H/A)
    • CI 層化: docs-lint + test/typecheck/nix-eval paths filter (J)
    • 受入: 反証 + 過剰制限しない陰性テスト(packages/opencode/test/plugin/anti-pattern-guards.test.ts 19 pass)
    • ローカル実証: local:deploy / local:check green、removal ガード ON/OFF 反証済み
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions