mcpField
F
fallow-review

fallow-review

github.com/fallow-rsテスト・品質137908 回インストール今日更新
リポジトリ

fallow-review について

fallow-reviewは、変更セットを依存グラフに基づくレビュー概要に変換するスキルです。重要な構造上の判断にレビューを集中させ、エージェントの判断をグラフのシグナルとスナップショットで検証します。CIゲートを担うauditとは役割が異なります。

主な機能

  1. 01注意度スコアで変更箇所を順位付け
  2. 02決定的な検出結果を判断対象から除外
  3. 03構造上の決定を質問として提示
  4. 04グラフスナップショット付きのエージェントガイドを生成
  5. 05判断シグナルとスナップショットの鮮度を検証

活用シーン

  1. 01マージ前のブランチや差分のレビュー
  2. 02自動コーディング後に残る判断事項の抽出
  3. 03コード作成者に返すレビューコメントの作成

MCP 対応

READMEでは、CLIと同じ依存関係の判断事項を提示するMCPツールdecision_surfaceに言及しています。その他のMCP連携の詳細は抜粋に記載されていません。

インストール

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

$npx skills add https://github.com/fallow-rs/fallow-skills --skill fallow-review

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
references/
production-runtime-data.md
tradeoff-elicitation.md

詳細

Fallow Review:グラフに基づくコードレビュー

fallow review は変更セットを、決定的なグラフ由来のレビュー概要とエージェント契約のループに変換します。「CI でブロックされるか?」(これはゲートとして機能する fallow audit が判定します)ではなく、「どこを見ればよいか、実際にどの呼び出しに人の判断が必要か?」に答えます。review は常に終了コード 0 を返すため、判定結果にかかわらず安全に実行できます。

次の 4 つの処理を、この順番で行います。

  • subtract:変更されたファイルのデッドコード、複雑さ、重複、スタイルを報告し、判断ループから除外します。これにより、決定的なチェックですでに確認できる内容に注意を費やさずに済みます。
  • focus:変更されたファイルのユニットを、複合的な注目度スコア(ファンイン/ファンアウト、リスクゾーン、変更の形状)でランク付けし、review-here/not-prioritized のラベルと、完全な deprioritized の例外リストを付けます。これにより、何も隠されません。
  • structure:判断サーフェスでは、重要な STRUCTURAL 判断を少数だけ diff から取り出し、それぞれを判断を促す質問として提示します。作業記憶に収まる数に制限し、各項目を fallow が出力した signal_id に結び付けます。
  • direct:ウォークスルーガイドでは、グラフ由来のダイジェスト、レビューの方向性、グラフスナップショットのピン、および返すべき判断スキーマをエージェントに提示します。

使用する場面

  • マージ前に、PR、ブランチ、または diff(AI 生成でも人間が作成したものでも)をレビューする場合。
  • エージェントが作業を終え、可能な fallow の指摘を取り除いた後に、残った人間/エージェントの判断が必要な箇所を明らかにする場合。
  • コードを書いたエージェントに戻せる、インラインレビュー可能な判断を作成する場合。

使用しない場面

  • CI を合否判定でゲートする場合:fallow audit を使用してください(失敗判定では 0 以外の終了コードを返します)。
  • プロジェクト全体の健全性、クリーンアップ、またはデッドコードのレポートを作成する場合:fallow スキルを使用してください。

人間向けの概要をすばやく確認

# Auto-detect the base (merge-base against the upstream / remote default):
fallow review

# Pin the base, or scope to a precise diff:
fallow review --base origin/main
git diff --find-renames origin/main...HEAD | fallow review --base origin/main --diff-stdin

人間向けの概要には、状況を把握するための事実、注目箇所マップ、判断サーフェス(「決定事項」)が出力されます。--format json を指定すると、構造化された全データ(decisions、focus、deltas、impact_closure、partition、graph_facts)が出力されます。--max-decisions N で上限を調整できます(小さな範囲内に制限されます)。--show-deprioritized を指定すると、注目箇所マップで折りたたまれた内容が展開されます。

判断サーフェス

各判断は、グラフから fallow が決定的に導出した signal_id(差分キーまたは調整ギャップキー)に結び付いた、判断を促す質問として提示されます。出荷可能なカテゴリは、次の 3 つだけです。

  • coupling-boundary:新しいゾーン間の依存エッジ。
  • public-api-contract:新しいエクスポート済みパブリック API サーフェス、またはこの diff の外部にあるモジュールが使用する契約の変更(確認または判断を促すシグナル)。
  • dependency:サードパーティのエントリーを追加する、または宣言済みエントリーのメジャーバージョン(あるいは 0.x のマイナーバージョン)を上げる package.json の変更。マニフェストと種類ごとに判断を 1 つにまとめ、影響を受けるパッケージをリポジトリ内でインポートしている数に応じて重み付けします。blast はインポーター数、internal_consumer_count は diff の外部にあるインポーター数です。どちらの数も、まとめられたパッケージ全体の和集合です。dependencies 以外のエントリーには、質問に (dev)、(optional)、または (peer) のタグが表示されます。digest.deltas には、キーが dependency_added(<manifest>::<name>)および dependency_major_bumped(<manifest>::<name>@<from>-><to>)として格納されます。どちらのリストも常に存在し、空の場合もあります。マイナーおよびパッチバージョンの更新、ならびに数値以外の範囲(workspace、file、git、タグ)は候補になりません。dependency 判断には suppress アクションがありません。判断の基点はコメントを記述できない package.json であるため、マニフェストに // fallow-ignore の行を貼り付けないでください。decision_surface MCP ツールは、CLI と同じ依存関係の判断を提示します。質問の形式ルール:変更履歴に関する質問(「<from> から <to> へのどの変更が、この N 個のインポーターに影響しますか?」)を提示してください。動作の変更を推測しないでください。

判断の基点となるファイルが変更時に名前変更されている場合、判断には previous_signal_id が含まれることがあります。これは、旧パスで同じ判断に付与されていたはずの signal_id です。これにより、レビュービューで git mv をまたいで以前のレビュアーコメントを再添付できます。

より広範なトレードオフの引き出し(テイストの決定権)

上記の決定対象は、DETERMINISTIC な範囲、つまり fallow がグラフから証明できるトレードオフ(3つのカテゴリ)のみです。実際のアーキテクチャ上のトレードオフはさらに広範です(抽象化のレベル、エラー処理の方針、データモデルの形、先行評価と遅延評価、状態の所有権、拡張性とYAGNIのバランス、テスト容易性、信頼境界など)。これらはいずれもグラフから検出できません。これらを明らかにするには、静的な解析ではなく、差分を読み取るモデルが必要です。

references/tradeoff-elicitation.md のトレードオフ引き出しプロンプトを、差分とガイドに対して実行します。このプロンプトはテイストの決定権を適用します。モデルはそれぞれの選択を明確にし、真に未決の質問として提示し、人間が判断します。このプロンプトには、誠実性に関する契約(差分への根拠付け、observed/tradeoff/question の分離、deterministic: false による明確な区分、出典情報、誠実に回答を控えることを認めた上での最大5件の制限、決定論的な対象との重複禁止、選択を決して決めない options)が含まれます。fallow は証明できる内容を担当し、プロンプトが残りを扱い、明確な区分によって両者が混同されないようにします。

レビュー手順としての実行

決定論的な判断に加えて、トレードオフも確認する場合:

  1. ガイドを取得し、差分を読み取ります:
    fallow review --base <ref> --walkthrough-guide --format json > guide.json
    git diff <ref>...HEAD            # or: git diff --cached  for staged work
    
  2. 差分と guide.json に対して references/tradeoff-elicitation.md のプロンプトを実行します。
  3. エンベロープ({ graph_snapshot_hash, abstained, tradeoffs[] } の形式)を保持します。以下の統合レビューで使用します。

この手順は、以下の post-validate エージェント契約ループには意図的に含まれていません。トレードオフのエンベロープが fallow review --walkthrough-file を介して往復することはありません(このコマンドは出力された signal_id のみを検証します)。そのため、これは fallow グレードの保証を持ちません。すべての項目は deterministic: false のままで、グラフによる検証ではなく、エージェントが差分と照合して自己チェックします。fallow による検証済みとして提示しないでください。

エージェント契約ループ

このループでは、エージェントが判定を行い、fallowが稼働中のグラフに対して事後検証します。検証を行うのはグラフであり、2つ目のモデルではありません。

  1. ガイドを取得します:

    fallow review --base origin/main --walkthrough-guide --format json > guide.json
    

    ガイドには、digest(概要と判断対象)、direction(確認する場所)、graph_snapshot_hash(古さを判定するための固定値)、agent_schema(返す値の厳密な形式)、injection_note が含まれます。digestはグラフのみから作られ、PRの説明文は一切取り込まれません。そのため、設計上、ガイドはインジェクションへの耐性があります。

  2. digest の判断対象を読みます。それぞれに signal_id、category、整理された question、anchor_file/anchor_line が含まれます。

  3. agent_schema に一致する判定を返します:

    {
      "graph_snapshot_hash": "<echo the value from the guide>",
      "judgments": [
        {
          "signal_id": "<one signal_id fallow emitted>",
          "framing": "<your reasoning for the human reviewer>",
          "action": "<block | address | consider | fyi>",
          "concern": "<optional: one lens from agent_schema.concern_vocabulary>"
        }
      ]
    }
    

    すべての signal_id は、ガイドで出力されたもの(emitted_signal_ids)でなければなりません。アンカーのないIDは拒否されます。graph_snapshot_hash はそのまま返してください。

    検出事項のない変更領域については、signal_id の代わりに、出力済みの change_anchor(ガイドの change_anchors にある chg: ID)を判定に記載できます。各アンカーには file、start_line、line_count が含まれます。不明なIDは unknown-change-anchor として拒否されます。

    action は、その判定が作成者に求める内容を示します。block と address は必須のアクション、consider は任意、fyi は対応不要です。concern は観点を示します。ガイドの agent_schema.concern_vocabulary にある13種類のケバブケース形式の観点を使うことを推奨します:abstraction、coupling、data-model、error-handling、control-flow、performance、dependencies、api-ergonomics、compatibility、state-ownership、extensibility、testability、trust-boundary。ガイドには agent_schema.action_vocabulary と agent_schema.concern_vocabulary の両方が記載されています。このファイルではなく、ガイドから読み取ってください。action_vocabulary は適用必須ですが、concern_vocabulary は参考情報であり、任意の文字列を受け付けます。

  4. 事後検証します:

    fallow review --base origin/main --walkthrough-file judgment.json --format json
    

    応答では、各判定が次のように分類されます:

    • accepted:signal_id が出力済みで、スナップショットが一致しています。エージェントの framing は非決定的なもの(deterministic: false)として区別され、ゲートとして使われることはありません。action も agent_framing の隣に同じように区別して記載されます。これは作成者への指示であり、fallowの事実ではありません。
    • reason: "unanchored-signal-id" を伴う rejected:signal_id が一度も出力されていません(幻覚です)。削除するか、修正してください。
    • reason: "invalid-action" と invalid_value(fallowが拒否したラベル)を伴う rejected:action が語彙の範囲外です。このエラーが報告されるのはアンカーの解決後のみです。幻覚のアンカーと不正なラベルが組み合わさっている場合は、代わりに unanchored-signal-id/unknown-change-anchor として拒否されます。まずアンカーを修正し、その後ラベルを修正してください。
    • reason: "stale-snapshot" と stale: true を伴う rejected:ガイドの取得後にツリーが変更されています。ガイドを再取得し、判定をやり直してください。

本番ランタイムデータ(Fallow Cloud)

プロジェクトから本番カバレッジをFallow Cloudに送信している場合は、変更する関数をそのデータと照合してください。ランタイムコンテキストをすべて取得するのではなく、対象を絞った読み取りを使います:

  • 編集前: fallow coverage review-packet --repo <owner/repo> --base <ref>(MCP:get_cloud_review_packet)。hit_count、covered_by_test、および存在する場合は呼び出し元を確認します。covered_by_test: null のホットな関数を編集する場合は、リスクが高くなります。
  • 削除前: tracking_state だけでなく、対象期間の period_tracking_state: "never_called" を必須とし、evidence_window.observed_hours を確認します。観測時間が少ない場合やトラフィックの少ない領域は、「訪問されていない」ことを意味し、「使われていない」ことを意味するわけではありません。
  • デプロイ後: fallow coverage deployment-changes --repo <owner/repo>(MCP:get_cloud_deployment_changes)。comparable が false の場合は、reason を報告し、変更があったとは主張しないでください。
  • file_path ではなく、repo_path でファイルを開きます。

このデータはコンテキストとして使います。ゲートとしてではなく、framing に記載してください。各フィールドの意味と手順の全容については、references/production-runtime-data.md を参照してください。

レビューをまとめる

検証とレビューは別物です。判断が承認されたら、読者がまず結論を左右する内容を把握し、その後で決定論的な残りを確認できるよう、以下の固定順で人間向けに表示してください。

  1. 承認された判断をdirection.orderの順に表示します。各判断には、ダイジェストのquestionとtradeoffをそのまま含め、続けてframing、さらに重要度を示す数値(internal_consumer_count、out_of_diffのパス、またはユニットのscoring_budget)を記載します。
  2. 聞き取りステップで得たトレードオフをconsequence順に、最大5件表示します。エンベロープがabstained: trueの場合は、その旨を1行で表示し、この欄には項目を追加しないでください。
  3. 差し引きは、ブリーフに記載された件数を使って次のように1行で表示します。「決定論的に処理済み:デッドコードN件、重複N件、複雑性N件、スタイルN件。議論の対象外」。これらの値をdiffから再計算しないでください。すでにブリーフで管理されています。
  4. 優先度を下げた項目は、件数と、表示するための指定方法--show-deprioritizedを含めて1行で表示します。項目を隠さず、数を水増ししないでください。
  5. 判断が0件で、トレードオフのエンベロープが棄権の場合、レビューは完了です。「重大な影響なし。決定論的な指摘:N件」。失敗ではなく、項目を捏造する理由にもなりません。

3つのグラフ情報が構成に反映されます。項目を追加できるのはtest_reachの注記だけで、その基点はchange_anchorです。

  • 各direction unitにはtest_adjacencyが含まれます。値は、none(このユニットをインポートするテストファイルがない)、untouched(テストからインポートされているが、そのテストはdiffに含まれない)、changed(テストからインポートされており、そのテストもdiffに含まれる)のいずれかです。テストファイルの場合、およびグラフが保持されていない場合は、この値はありません。review-hereユニットの値がnoneの場合は、framingで作成者に検証方法を尋ねてください。カバレッジがあると断言してはいけません。この値が示すのは、テストがそのユニットをインポートしているかどうかであり、変更をテストしているかどうかではありません。
  • digest.test_reachは、変更された各値エクスポートの到達状況を示します。statusはmeasuredまたはno-testsです。countsにはすべてのクラスの件数が含まれます。exportsには、directまたはframework以外のクラスのみ、file、export_name、line、reachを含む行が記載されます。
    • transitive:テストからエクスポートに到達しますが、エクスポートを直接指定するテストはありません。
    • mocked-only:テストではファイルがモック(mocked_targets)に置き換えられるため、実際のコードは実行されません。
    • none:テストからファイルには到達しますが、エクスポートに到達するテストはありません。
    • none-file:ファイルに到達するテストはありません。 test_reach には次のルールを適用します。
    • 存在しない場合は、事実がないことを意味します。古いバージョンの Fallow ではこのフィールドが出力されず、値のエクスポートに変更がない場合も存在しません。その場合は test_adjacency を使います。
    • review-here ユニットのファイルに mocked-only、none、または none-file の行がある場合は、その行(ファイル、エクスポート、クラス)を示します。検証の経緯を作成者に尋ねます。
    • 行には signal_id がありません。エクスポート宣言と範囲が重なる、同じ file 内の change_anchor に注記を紐付けます。重なるアンカーがない場合は、そのファイル内で最初のアンカーを使います。そのファイルに判定がある場合は、その枠組みの中に注記を記載します。
    • test_reach と test_adjacency が食い違う場合は、エクスポートごとに判定され、モックも検出できる test_reach を使います。
    • これらの事実から「テスト済み」や「カバー済み」と記述してはいけません。direct は、テストでそのエクスポートが指定されていることを意味し、変更された行をテストが実行することを意味するものではありません。
    • reach セットに含まれる値は固定されていません。不明な値には注意が必要です。
    • exports_omitted が 0 より大きい場合、一覧は不完全です。行がないファイルは、direct に到達している証拠にはなりません。counts を使います。
    • status: "no-tests" の場合は、エクスポートごとではなく、全体の概要を示す行を 1 行記述します。
    • masking: "capped" の場合、グラフはモックを検出できません。mocked-only の行がないことは、何の証明にもなりません。
    • エンドツーエンドテストはファイルをインポートしません。エンドツーエンドランナーがあるプロジェクトでは、none-file の行があってもエンドツーエンドテストが存在する場合があります。決めつけず、尋ねてください。
  • digest.partition.independent_slices は、ユニット間依存関係グラフの連結成分を示します。各成分はモジュールディレクトリのソート済みリストです。スライスが 2 つ以上ある場合にのみ存在し、存在しない場合は変更箇所が 1 つの連結したまとまりであることを意味します。digest.triage.risk_class が high で、このフィールドが存在する場合は、概要を示す事実として「この変更は、グラフで確認された境界に沿って K 個の独立したスライスに分かれています」と明記します。分割を求めるものではありません。判断は作成者に委ねられます。

文章作成では、次の 2 つのルールに従います。まず、活用を重視します。構造に関する判断 1 件と小さな注記 10 件がある場合、レビューの中心となるのはその判断です。注記はその下に添えるか、省略します。形容詞ではなく、数値を示します。すべての framing には、ガイドにある数値またはパスを少なくとも 1 つ含めます(利用側の数、差分外のパス、scoring_budget など)。「遅くなる可能性があります」では根拠になりません。「14 個のモジュールからインポートされ、そのうち 9 個はこの差分の外です」と記述します。

人間が介在するウォークスルー(ターミナル)

上記のエージェント契約ループでは、エージェントが枠組みを設定します。同じループを使えば、人間の評価も同じグラフ検証済みのハルシネーション防止保証付きで伝達できるため、ターミナルでレビューする人は、fallow が検証して往復処理するアンカーにメモを残せます。契約は既存の --walkthrough-guide / --walkthrough-file による往復処理であり、新たなインターフェースではありません。

判断基準は人間が決め、あなたはメモを伝えるだけです。fallow が検証するのはアンカー(シグナルまたは変更箇所が存在すること)であり、メモの正しさではありません。伝達されるメモはすべて deterministic: false のままで、ゲートとして機能することはありません。

  1. ツアーを表示し、アンカーを確認します:

    fallow review --base origin/main --walkthrough                       # the staged human tour
    fallow review --base origin/main --walkthrough-guide --format json > guide.json
    

    guide.json には、判断に関する signal_id(枠組みが示された構造的な問い)、変更箇所ごとの change_anchors セット(各要素は { "change_anchor": "chg:<hex>", "file", "start_line", "line_count" })、および古さを判定するピンである graph_snapshot_hash が含まれます。人間にツアーを提示し、フラグを付ける項目ごとに、短い評価またはメモと、作成者に求める対応を集めます。選択肢として提示するラベルは block、address、consider、fyi の4つのみです。不明なラベルは invalid-action として拒否されます。

  2. 各人間のメモを判断として伝達します(ハッシュをそのまま含め、フラグを付けた判断について fallow が出力した signal_id、または人間がメモを残すその他の変更箇所について change_anchor を指定し、人間の対応内容を action として伝えます):

    {
      "graph_snapshot_hash": "<echo from guide.json>",
      "judgments": [
        { "signal_id": "<an emitted decision signal>", "framing": "<the human's verdict/note>", "action": "address", "concern": "<optional>" },
        { "change_anchor": "<an emitted chg: id>", "framing": "<the human's note on this region>", "action": "consider", "concern": "<optional>" }
      ]
    }
    
  3. 記録を検証します:

    fallow review --base origin/main --walkthrough-file judgment.json --format json
    

    応答はエージェント契約ループと同じ形式で並べ替えられますが、2つの項目が追加されます。accepted には anchor_kind("signal" または "change")が含まれ、fallow が出力したことのない change_anchor は unknown-change-anchor として拒否されます。実在するシグナルまたは変更箇所を再度アンカーとして指定してください。アンカーを捏造してはいけません。

  4. 対応します: 受理された人間の評価をコーディングセッションに伝えます。受け取るエージェントが優先順位を判断できるよう、各メモの action も伝えてください。block と address は必須の対応、consider は任意の対応、fyi は変更不要です。メモはアンカー付きで明確に区分されて届き、fallow が認定した事実として扱われることはありません。

保証:人間は、fallow が出力していないシグナルや変更箇所にメモをアンカーできません。また、変更されたツリーに対するメモは、誤った箇所に暗黙的に紐付けられるのではなく拒否されます。

このループが退ける誤った理由付け

誤った理由付け実際のところ
「差分にデッドコードが見えるので、すぐにフラグを付けよう」差し引きはすでに Subtract が担当しているため、二度目の導出はノイズになり、誤る可能性もあります。ブリーフの件数を伝えてください。
「この signal_id は正しそうだ」存在するのは emitted_signal_ids だけです。それ以外はハルシネーションであり、fallow に unanchored-signal-id として拒否されます。
「トレードオフは5つが目標だ」5つは上限です。空のリストを伴う abstained: true も、妥当で完全な回答です。
「問いは未解決だから、修正方法だけ伝えよう」修正方法を名指しするのは処方です。未解決の判断として表現し直すか、実際のコストを伴う選択肢を2つ以上挙げてください。
「ツリーは少ししか変わっていないので、ガイドはまだ使えるだろう」これは stale-snapshot です。ガイドを再取得し、判断をやり直してください。
「テストが成功しているので、変更は良いものだ」成功は検証上の事実であり、判断対象についての評価ではありません。判断には引き続き人間の決定が必要です。
「テストがこのファイルをインポートしているので、テスト済みだ」test_adjacency が確認するのはインポートだけです。mocked-only、none、none-file の行は、インポート経由では実際のエクスポートに到達するテストがないことを示します。検証方法について確認してください。
「本番環境で一度も呼び出されていないので、削除しよう」period_tracking_state と evidence_window.observed_hours を確認してください。計測期間が短い、またはまれにしか通らない経路であれば、「未訪問」であって「デッド」ではありません。

注記

  • review は audit --brief のエイリアスです。--format はブリーフとは独立しています。
  • プロジェクト全体の分析については fallow スキルを、フラグの一覧についてはその references/cli-reference.md を参照してください。

コメント