0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ハッシュが一致しても別の指示が出る――複数のChatGPT会話からCodexへのMCP連携で「最新1件」共有をやめた

0
Posted at

ChatGPTで作ったテスト環境向けの指示を、MCP経由でVS CodeのCodexへ渡そうとしたところ、別の会話で保存したログ調査の指示が表示されました。コピー後のハッシュ照合は通っています。

原因はコピーの破損ではなく、複数の会話で共有していた「最新1件」から対象を決めていたことでした。

ChatGPTの会話を複数並行し、MCP経由でCodexへ指示を渡している人向けに、対象の選択と内容の照合を分けた自作連携の例を紹介します。

MCPが保存する指示ファイルを「原本」、Codexへ渡すために内容を固定したファイルを「固定コピー」と呼びます。原本とコピーの内容が一致しても、それだけでは送りたかった指示かどうかは分かりません。

ハッシュが通ったのは、別の指示を正しくコピーしたから

以前は、すべての会話が共通のinstruction-record.jsonを更新し、自作VS Code拡張「Reporter」がそのファイルを読んでいました。

次の順序になると、取り違えが起こります。A・Bは説明用の識別子です。

  1. 会話Aが「テスト環境の確認」を保存する。
  2. VS Codeへ添付する前に、会話Bが「ログ調査」を保存する。
  3. 拡張が最新原本Bを読み、Bの固定コピーを作る。
  4. 原本BとコピーBのハッシュ照合が通る。
  5. Aを送りたかった人に、Bの指示が表示される。

図の緑は処理、橙は人の操作、青は検証、赤は取り違えや停止を示します。

ハッシュで確かめていたのは、読み取った原本とコピーが一致することです。その原本が利用者の希望した依頼かどうかは、照合の対象に含まれていませんでした。

全文確認で気づけば送信は止められますが、そのたびに選び直す手戻りが生じます。見落とせば別の作業を依頼するおそれもあります。並行する作業が増える運用で、この検出を毎回人の注意に任せる状態を変えました。

これはMCP固有の問題ではありません。複数の依頼元が更新する共有データを、読み取り時点の「最新」だけで選ぶ連携にも当てはまります。

指示をID別に保存し、送りたいものを選ぶ

ローカルMCPサーバーに、指示IDごとの保存先を追加しました。

data/instructions/<submission_id>.json

レコードには指示ID、本文、本文のSHA-256、保存日時などを持たせます。同じIDがすでにある場合は、内容が完全一致するときだけ再利用し、不一致は拒否します。通常の保存処理で別の内容へ上書きしないためです。

既存経路との互換性を保つため、最新原本も残しています。

data/instruction-record.json

保存はID別原本を先に確定し、その後に最新原本へ反映する順序です。Reporterは両方を列挙し、同じIDがある場合はレコード全体のハッシュ一致を要求して重複を除きます。不一致なら候補表示前に停止します。

候補が1件でも、人間が選ぶ操作を省略しません。人が送信先のCodex会話と指示全文を確認して送る運用に合わせ、対象の選択も人間が行う構成にしました。

一覧では作業名・保存日時・IDを対応させる

候補一覧には、依頼元、作業名、対象VS Code、保存日時、指示IDを表示します。

保存日時とIDで選ぶ指示候補一覧.png

選択中の行には「記事用スクリーンショット撮り直し」、その下には別の作業名が表示されています。同じ依頼元でも、作業名と保存日時・IDを組み合わせて区別できます。

この画像は候補一覧の表示例です。下段には作業名が「未取得」の過去の候補も残っています。選択中の指示は、ChatGPT側で作成するヘッダーの重複を取り除いたものです。

人間による選び間違いは残ります。同名の作業なら日時とIDも確かめ、添付前に全文を確認します。ここで減らしたのは、別の会話による更新で受渡し対象が黙って入れ替わる問題です。

選んだ後は、同じ内容から固定コピーを作る

選択と照合は別の役割です。選択では「どの依頼を送るか」を決め、再検証では「選んだときと同じ原本か」を確かめます。

選択した原本のpathと、読み取ったバイト列全体のSHA-256を保持します。受渡し作成時にそのpathから読み直し、レコード形式と本文ハッシュの整合、全体ハッシュの一致を検証します。

最小限の流れを擬似コードで示します。

候補を列挙する:
    原本を読み、レコード形式と本文ハッシュの整合を検証する
    pathと、読んだバイト列全体のSHA-256を候補に保持する
    依頼元・作業名・保存日時・指示IDを一覧へ表示する

人間が候補を選んだら:
    選んだ候補のpathと全体ハッシュを expected に保持する
    expected.path から原本のバイト列を読み直す
    読めない・形式不正・本文ハッシュ不一致なら停止する
    バイト列全体のSHA-256が expected の値と違えば停止する
    検証したバイト列から固定コピーと受渡し情報を作る
    人間へ指示全文を表示する
    確認された場合だけCodex入力欄へ添付する

実装では指示IDと本文ハッシュも個別に比較していますが、検証対象はレコード全体のハッシュと重なります。

再検証が特に必要なのは、選択後も更新される互換用の最新原本を選んだ場合です。ID別原本は通常の保存で上書きされませんが、消失や読取失敗の場合には同様に停止します。別の最新指示を代わりに使う処理は入れていません。

最新原本は保存のたびに更新されます。ただし、送りたい指示はID別原本から選べるため、最新原本に何が残るかだけで対象が決まることはありません。同時書込みや更新途中の停止時の挙動は、次の未確認事項に含めています。

確認できた範囲と制約

コード上では、ID別保存、候補の列挙と重複照合、選択後の再検証、不一致や読取失敗で停止する分岐を確認しました。関連する自動テストには過去の改修時に成功した記録があります。今回の記事編集では再実行していません。

人間の実操作では、過去の正常な受渡しで、一覧から指示を選び、Codexへ送り、結果の確認・承認後にChatGPT側で取得する往復を確認しています。今回掲載した画像は候補一覧の表示までを示すもので、選択中の指示の処理完了や承認済みを示す画像ではありません。

未確認なのは、同時書込みや更新途中の停止に対する保存の原子性、すべての更新タイミングでの動作、原本の長期蓄積管理です。読めない場合に停止することと、どの条件でも受渡しを継続できることは分けて評価します。

また、旧来の固定パスを直接読む経路には同じ問題が残り得ます。今回の対策が成立するのは、明示選択と選択後の照合を通る経路です。連携は利用中のCodex拡張の添付機能にも依存します。SHA-256による照合は暗号化や送信者認証を担いません。

内容が一致していることと、希望した対象であることは別の確認です。今回は、指示をIDで保存し、人が対象を選び、その選択を保持して受渡し時に照合することで、この二つを分けました。

関連記事

初期の接続と固定コピーによる受渡し構成はこちらにまとめています。

ChatGPTからVS CodeのCodexへコピペせずに指示を渡す――MCPで保存し、人間が確認して送信する構成

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?