| name | review-respond |
| description | rikai のレビューリクエストを処理する。.claude-review/requests/<id>.json を読み、変更の解析・スレッド返信・チャット応答を行って .claude-review/responses/<id>.json に書き出す。 |
review-respond
rikai が書いたリクエストを 1 件処理する。
.claude-review/requests/<id>.json を読む
kind に応じた作業を行う
.claude-review/responses/<id>.json に JSON だけを書く
language フィールドが出力言語を指定する(ja か en)。人間に読ませる文字列はすべてこの言語で書く。
diff はリクエストに入っていない。自分で読む。
patchFile があるとき:そのファイルが差分そのもの。git は使わない(このベースは git の ref では表せない)
patchFile が無く base.to が null のとき:git diff <base.from> に加え、git ls-files --others --exclude-standard の新規ファイルも読む
- それ以外:
git diff <base.from> <base.to>
files がレビュー対象の全ファイルで、fileKey はその key を指す。応答で使う fileKey は必ずこの一覧の key と完全一致させる(a/ や b/ を付けない、絶対パスにしない)。一致しないものは黙って捨てられる。
kind: analyze
グループ、レビュー順、案内カード、コメントを生成する。
グルーピング
関心事(独立した論理変更)単位で切る。層で切らない。 def-use で繋がった変更のまとまりが 1 グループになる。
- 典型のグループ種別:本編の機能変更(複数あり得る)、準備リファクタ、機械的変更、ついで修正
- import 整理やリネーム追従などの機械的変更は独立グループに分け、
bulkComplete: true を付ける
- テストは独立グループにせず、検証対象の関心事の末尾に置く
- グループとファイルは多対多。同じ
fileKey を複数グループの items に入れてよい。初出が本編で、以降は再掲として扱われる。再掲側には "focus": { "line": 28, "label": "分離後の呼び出し側" } を付け、そのグループで見るべき行と一言のラベルを示す
- リクエストの
symbols / edges はシンボルグラフ。自分のグルーピングをこれで検算する。グラフ上で繋がらないファイルが同居していたら分割を疑う
グループ内の順序
変更の性質で選び、選んだ理由を narrative に一文で書く。
- 新機能・ユースケース追加:top-down(エントリポイントから)
- データモデル起点:bottom-up(データの流れ順)
- バグ修正:再現テストから
- リファクタ:インターフェース、次に呼び出し元
フロー図
実行の道筋があるグループにだけ flow を付ける。付けるかどうかは自分で判断する。
- 付ける:機能実装、データの流れ、往復のあるやりとりなど、「何がどの順に起きるか」が説明できるもの
- 付けない:設定変更、ドキュメント更新、1 ファイルで閉じた処理、
bulkComplete を付けたグループ
- 迷ったら付けない。意味の無い図は読み手の負荷にしかならない
steps は実行順。各ステップの what は「何が起きるか」を一文で書く。飛び先として fileKey を付けられる(line と symbol は任意)。fileKey は files[].key と完全一致させる。
分岐は branches で書く。ネストは 1 段まで。 branches の中のステップに branches を持たせない。
案内カード
ファイルごとに analyses を 1 件書く。
priority:P1〜P4。下流への影響が大きいものほど高い
reason:なぜこの順で読むのか、何が起点なのかを 1〜2 文で
points:そのファイルで見るべき点。1 行 1 点、3 点まで
reason と points では次の記法が使える。
`identifier` — コード片として表示される
[ラベル](fileKey) — そのファイルへ飛ぶチップになる
[ラベル](fileKey#L52) — その行へ飛ぶチップになる
コメント
comments に書く。種別は無い。全て自分の実装についての説明として書く。
simplify と code-review を通過した成果物を提出している前提なので、既知の要修正を残したままレビューに出すことはない。
判断を仰ぎたい箇所も、警告としてではなく「こう決めた、根拠はこうで、ここは確かめられていない」と説明の形で書く。
コメントはコードリーディングの補助であって、対応事項ではない。
読み手が必ず読むべき行だけに付ける。件数の下限は無い。1 件も付かないファイルがあってよい。
付けるのは、その行を読んだだけでは分からないことがあるとき。次の 3 つが典型。
- この行が何を起こすか — 呼び出し先の挙動が変わる、ここで状態が確定する、といった見た目から離れた影響
- ここが何との約束か — 引数や戻り値がどう使われる前提か、どの不変条件を守っているか
- なぜこの形にしたか — 他の選択肢を捨てた理由、境界をそこに置いた理由、既定値の根拠
付けないもの。
- コードを読めば分かること。型・命名・制御構造が既に語っていること
- 定型、生成物、リネーム追従などの機械的な変更
- ファイルや変更全体のまとめ。それは案内カード(
analyses)の仕事
- 件数を揃えるためのコメント。読み手の負荷にしかならない
確かめられていないことは、確かめられていないと書く。「動くはず」で終わらせない。
line は side の側の行番号。追加行に付けるなら side: "additions" で新しい側の行番号、削除行に付けるなら side: "deletions" で古い側の行番号。
応答
{
"kind": "analyze",
"groups": [
{
"name": "公開日時の nullable 化",
"narrative": "データの流れ順に辿ります",
"items": [
{ "fileKey": "src/db/schema/articles.ts" },
{ "fileKey": "src/repositories/articleRepository.ts" }
]
},
{
"name": "機械的変更",
"narrative": "import 整理のみ",
"bulkComplete": true,
"items": [{ "fileKey": "src/features/articles/index.ts" }]
groups は全ファイルを少なくとも 1 回は含めること。
kind: thread-reply
thread が対象スレッド、message が人間の発話。修正依頼か質問かはこちらで解釈する。
thread.type が human のものは、人間が diff の任意の箇所に自分で立てたスレッド。line と endLine がその範囲を指す。
- 修正依頼だと判断したら、実際にコードを直す
- 直したら
threadReply に何をどう変えたかを書く。無言で diff だけ変わる状態を作らない
- 修正の影響が他の行やファイルに及んだら、その箇所に
newComments を足す
- 実際に編集したファイルのパスを
updatedFiles に列挙する。編集していなければ空配列
{
"kind": "thread-reply",
"threadReply": "`inArray` 一括取得に変更し、削除済みカテゴリの除外は取得後のフィルタで維持しました。",
"newComments": [
{
"fileKey": "src/repositories/articleRepository.test.ts",
"line": 4,
"side": "additions",
"body": "一括取得に合わせてカテゴリ取得のモックを更新しました。"
}
],
"updatedFiles": ["src/repositories/articleRepository.ts"]
}
kind: chat
message が質問、history が直近のやりとり。変更内容についての質問に答える。コードは変更しない。
{ "kind": "chat", "reply": "`GET /articles` のレスポンスで `publishedAt` が null になり得ます。" }
書き出し
.claude-review/responses/<id>.json に JSON だけを書く。前後に説明文を付けない。
ディレクトリが無ければ作る。rikai はこのファイルの出現を待っている。