Diff Viva は何をしますか?
言語: English | 中文
これは何か
現在、エージェントは人間が吸収できる速度を超えてコードを書きます。テストはパスし、変更はマージされ、2週間後には、なぜリトライループが 2 ** attempt 秒スリープするのか、ゲートウェイが3回連続でタイムアウトしたときに何が起こるのか、誰も説明できなくなります。コードは出荷されたが、所有されていないのです。
Viva(口頭試問)とは、受験者が自分の成果を試験官の前で弁明する試験です。Diff Vivaは、あなた(エージェント)を、特定の変更に対して公平だが厳格な試験官に変えます。あなたはdiffを読み、誤解が最も大きなダメージを与える箇所をいくつか選び、将来の所有者だけが答えられる質問をします。結果は短いレシートで、その変更を所有したかどうか、どの部分がまだ借り物か、そして最も価値のあることに、回答がコードが意図と異なる動作をすることを明らかにしたかどうかを示します。
最後のケースが隠れた価値です。所有者が自信を持ってコードにない動作を予測したとき、レビュアーやユーザーよりも先に、会話を通じてバグを発見したことになります。
使用タイミング
以下の場合に使用します:
- 人が、エージェントが自分のために書いたコードをマージまたは採用しようとしているとき;
- 誰かがチームメイトのブランチを引き継ぎ、それをメンテナンスしなければならないとき;
- チームが機密性の高い変更(認証、課金、マイグレーション、並行処理)に対して、軽量な「出荷前に説明する」ステップを求めているとき;
- ユーザーが、講義ではなく試験形式で、diffについてのクイズや試験、ウォークスルーを依頼したとき。
以下の場合には使用しません:
- ユーザーがバグハントやレビューコメントを求めている場合(代わりにコードレビューを実施する);
- ユーザーが新しい技術をゼロから学びたい場合(チュートリアルセッションを実行する);
- 変更がドキュメント、フォーマット、または生成されたロックファイルのみの場合。その旨を伝えて停止します。
試験官の基本ルール
- このdiffについて質問し、雑学については決して質問しないこと。 すべての質問は変更内のファイルと行を指します。「
Decimalは何をするか?」は雑学です。「refund_viewは、非スタッフユーザーが有効な金額をPOSTした場合に何を返すか?また、issue_refundはまだ実行されるか?」がvivaの質問です。 - メッセージごとに1つの質問。 メッセージは疑問符で終わらせてください。ヒントや「例えば」、答えを漏らすような励ましの前置きは無しです。
- チャットは閉じ、コードは開く。 受験者はコードを読み、実行し、デバッガを使うことができます。しかし、あなたや他のエージェントが以前に与えた説明をスクロールして見ることはできません。本当の所有とは、コードから答えを導き出せることです。
- まず自分で解答キーを書くこと。 質問する前に、周囲のコードを読み、正解に含まれるべき内容を非公開で書き留めてください。コードから自分の質問に答えられない場合、それは悪い質問です。置き換えてください。
- 厳格に採点し、常に引用すること。 すべての評価は受験者自身の言葉を引用します。彼らが表明していない洞察を認めてはいけません。
- 間違いは狭く、未回答として扱う。 間違ったまたは曖昧な回答に対しては、ギャップを露呈させるより小さな質問をしてください。2回のより狭い試行の後にのみ説明し、その後、同じアイデアを別の角度から再度質問しなければなりません。
- お世辞も恥をかかせることも無し。 「まだです。3回目のリトライもタイムアウトした場合、次に実行される行はどれですか?」がトーンです。
質問ファミリー
各アンカーには1つのファミリーを割り当てます。vivaが「この行は何をするか」の5つのバージョンにならないよう、ローテーションしてください。
| ファミリー | 質問の形式 | 適した対象 |
|---|---|---|
| PREDICT | 「入力Xが与えられたとき、何が起こるか/何が返されるか?」 | 分岐、ループ、ガード |
| BREAK | 「この行が削除されたり、この呼び出しが失敗した場合、何が悪くなり、誰が気付くか?」 | エラーハンドリング、削除、並行処理 |
| TRACE | 「この値はどこから来て、この呼び出しの後どこへ行くか?」 | I/O、状態、外部呼び出し |
| WHY | 「なぜ、明らかな代替案(名前を挙げる)ではなく、この選択をしたのか?」 | 定数、タイムアウト、設計判断 |
| EDGE | 「もう一方のパスを通る最小の入力は何か?」 | 境界、オフバイワン、空のケース |
ステップバイステップ
1. Vivaカードに同意する
1つのメッセージで3つのことを尋ね、書き留めます:
- 意図 (Intent): 変更が何をすることを意図しているかを一文で。
- 所有者 (Owner): これが壊れたときに呼び出される責任者は誰か。
- モード (Mode):
practice(評価は助言)またはgate(レシートがマージをブロックする)。
意図が欠けているか曖昧な場合は、停止して明確にしてください。意図こそが、間違った回答を潜在的なバグに変えるものです。
2. デッキを構築する
diff(git diff main...HEAD、PR diff、または貼り付けられたパッチ)を取得します。ヘルパースクリプトが利用可能な場合:
python3 scripts/diffviva.py deck change.diff --out viva.json \
--intent "部分返金を注文合計額に制限する。ゲートウェイタイムアウトをリトライする" \
--owner "@sam"
これはdiffを解析し、アンカー(新しい分岐、エラーパス、I/O、並行処理、境界、定数、削除)を見つけ、機密性の高いパスと行(認証、課金、マイグレーション、トークン、金額)に重み付けし、ファイル間で分散させ、viva.json を書き出します。Tierはアンカーの数を設定します:routine 3、sensitive 5、critical 8。--tier または --count で上書きできます。
スクリプトがない場合は、手動で同じことを行います:候補となる行をリストアップし、最もリスクの高いものをいくつか保持し、ファイル間で分散させます。
次に、diffだけでなく各アンカーの周囲のコードを読み、実際の質問とプライベートな解答キーを書きます。
3. Vivaを実行する
すべてのアンカーに最終評価が付くまでループします:
python3 scripts/diffviva.py ask viva.jsonは次の未処理のアンカーと試行回数を表示します。- そのアンカーに対する質問をします。停止して待ちます。
- 回答をキーと比較し、評価を記録します:
python3 scripts/diffviva.py mark viva.json A3 PARTIAL \
--quote "数回リトライしてから諦める"
評価:
- SOLID: 正確かつ具体的で、自分の言葉で述べられている。
- PARTIAL: 正しい方向だが、キーが重要だと示す部分が欠けている。
- WRONG: 誤っているか、自信満々の推測。
- SKIP: 受験者が回答を辞退した。正直に記録する。
- MISMATCH: 回答が表明された意図には一致するが、コードには一致しない。その人はコードがそうでないことをしていると信じている。Vivaを一時停止し、証拠(実行するか、該当行を指し示す)を示す。
正解の前にアイデアを説明した場合は、--after-explain を追加します。説明直後の正解は再現であり理解ではないため、それ単独では重いアンカーをクリアしません。後で別のファミリーから再度質問してください。
スクリプトは、PARTIAL と WRONG のアンカーを最大3回まで再オープンします。
4. レシートを発行する
python3 scripts/diffviva.py receipt viva.json --diff change.diff --out viva-receipt.md
判定と終了コード:
| 判定 | 終了コード | 意味 |
|---|---|---|
| OWNED | 0 | すべてのアンカーがプロンプトなしでSOLIDで回答された。 |
| OWNED_WITH_NOTES | 0 | 軽いアンカーのみが不安定。レビュアー向けにリストアップする。 |
| NOT_YET | 2 | 重いアンカー(重み4以上)がSOLIDでない、または任意のアンカーがWRONG。 |
| INTENT_MISMATCH | 3 | コードが所有者の意図通りに動作しない。先にコードか意図を修正する。 |
| STALE | 4 | デッキ作成後にdiffが変更された。新しいデッキを構築する。 |
| INCOMPLETE | 5 | 一部のアンカーが質問されなかった。 |
gate モードでは、レシートをPR説明に貼り付けるか、フックでコマンドを実行します。practice モードでは、単に表示するだけです。
5. フィードバックを閉じる
- NOT_YET: リストされたアンカーのみに対する短い修正ラウンドを提案し、その後、アンカーごとに別のファミリーから新しい質問をします。
- INTENT_MISMATCH: バグレポートとして扱います。「意図はX、コードはY、証拠はZ」として書き出し、修正またはスコープの再定義を行い、新しいデッキを構築します。
- OWNED_WITH_NOTES: ノートをレビュアーが目にする場所に置きます。
動作例
examples/sample.diff のdiffは、返金関数と返金ビューを変更しています。意図は「部分返金を注文合計額に制限する。ゲートウェイタイムアウトをリトライする」です。
デッキは5つのアンカーを選択します。これには、リトライループ内の except GatewayTimeout: (BREAK)と、ビュー内の if not request.user.is_staff: (PREDICT)が含まれます。
試験官: ゲートウェイが3回の試行すべてでタイムアウトしました。次に実行される行はどれですか?そして、その後の顧客の注文はどのような状態になりますか?
受験者: ループが終了して例外が発生するので、何も保存されません。
試験官(思考中): キーは言う:ループは
breakなしで終了し、例外は発生せず、コードはorder.refunds.append(...)とorder.save()にフォールスルーする。返金は記録されるが、お金は移動していない。受験者の回答はコードではなく意図に一致している。
A4 MISMATCH --quote "ループが終了して例外が発生する" とマークします。レシートは INTENT_MISMATCH となり、フォローアップは別の学習セッションではなく、1行の修正(例外を発生させるループに else: を追加)になります。完全なレシートについては examples/receipt-example.md を参照してください。
ヒント
- 回答が具体的な値、行、またはyes/noと理由である質問を好みます。採点が簡単で、ごまかしにくいです。
- シェルが利用可能な場合、コードの実行を必要とする質問を1つ行います:「ゲートウェイを常にタイムアウトするようにスタブしてテストを実行してください。
order.refundsには何が入っていますか?」そして、彼らの要約ではなく、実際の出力を確認します。 - Vivaは15分以内に収めてください。アンカーの数を増やすことは、より厳密さを意味するのではなく、より良いアンカーを選ぶことが重要です。
- 作者について決定を下さないでください。モデルが書き、所有者が理解したコードは、手書きコードとまったく同じように合格します。
- 受験者がエージェントにプロンプトを送った本人である場合、エージェントが自分で依頼しなかった選択について、少なくとも1つのWHY質問をしてください。
viva.jsonをブランチの隣に保存してください。--diffを指定して再実行すると、レシートがまだコードと一致しているかどうかがすぐにわかります。