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?

Codexの結果をChatGPTへ戻す転記を減らす――MCPと人間確認

0
Posted at

ブラウザーのChatGPTで設計を相談し、VS CodeのCodexで実装すると、作業結果をChatGPTへ戻すための転記が残ります。

この転記を減らすため、CodexがMCPで結果を未公開保存し、人間が確認した本文だけをChatGPTから読める構成を検証しました。テスト本文では、未公開保存、人間による確認・公開、新しいChatGPT Work会話での読取りまで成功しています。

手動で結果ファイルを用意する操作は減りました。ただし、同じ指示に結果が2件あり、一覧から対象を選べない場面もありました。本文のコピペを減らしても、どの結果を戻すかの指定は人間に残りました。

ChatGPTからCodexへの指示受渡しは、次の記事で扱っています。

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

結果の保存と公開を分ける

この記事でいうWorkは、ブラウザーで使うChatGPTのWork画面です。Reporterは、Locolisu AI Task Monitorで使う自作のVS Code拡張です。今回の受渡しでは、元指示と結果を表示し、人間が確認した結果をChatGPTから読める状態にします。MCP(Model Context Protocol)を通して、Codexによる保存とWorkによる読取りを行います。

今回の経路は、次の3段階です。

  1. Codex専用STDIO MCPが、結果を未公開領域のpendingへ保存する。
  2. VS CodeのReporterが元指示と結果を表示し、人間が確認したものだけをconfirmedへ保存する。
  3. ChatGPT Workが、指示IDと結果IDを指定して読み取る。

STDIO MCPは、標準入出力でCodexと通信するローカルのMCPサーバーです。

ここでの「公開」は、Work向けMCPから読み取れるようにすることです。インターネット上への一般公開ではありません。

また、保存するのはCodexがtoolへ明示的に渡した本文です。Codex画面の最終回答を自動取得する仕組みではありません。

手動draft方式では操作が増えた

最初に成立した結果返却の経路(手動draft方式)では、結果本文のファイルを用意し、draftを生成して、そのファイルを人間が選択・確認する必要がありました。

通信として往復できても、コピー&ペーストより操作が増えるなら、転記を減らす目的には合いません。

そこで、結果本文の保存をCodex専用MCPへ移しました。Codexが未公開結果を保存し、Reporterから人間が確認する構成です。

未公開保存だけを担当するMCP

このSTDIO MCPが提供するtoolは、save_unpublished_resultだけです。

保存要求には、次の4項目を渡します。

項目 用途
save_request_id 同じ保存要求の再試行を識別する
source_submission_id 対応する元指示を指定する
source_instruction_sha256 元指示本文の一致を確認する
result Workへ戻す結果本文

このMCPは外部接続用のトンネルへ公開せず、確認済み領域へ結果を公開するtoolも提供しません。Workからの結果読取りは、別のWork向けMCPが担当します。

元指示のIDと本文hashを照合する

保存処理では、添付時に保存された元指示の固定コピーを読み直します。次は、src/vscode-instance-reporter/unpublished_result.jsから、IDと本文hashの照合を抜粋した実コードです。

const source = validateInstructionRecord(await fs.readFile(sourcePath));

if (source.submission_id !== input.source_submission_id) {
  throw new Error("immutable sourceのsubmission IDが一致しません。");
}

if (source.instruction_sha256 !== input.source_instruction_sha256) {
  throw new Error("immutable sourceのinstruction SHA-256が一致しません。");
}

IDだけでなく本文のSHA-256も照合し、どの指示に対する結果かを確認します。

ただし、hashの一致は対応する本文の確認であり、結果の正しさや安全性を保証するものではありません。その判断は、人間による内容確認に残ります。

同じ保存要求の再試行を扱う

同じ入力を再試行する場合は、同じsave_request_idを使います。すでに保存されていれば内容を比較し、一致する場合だけ既存結果を再利用します。

同じ要求IDに異なる指示ID、指示本文hash、結果本文が指定された場合は拒否します。

新しい結果は、一時ディレクトリにJSONを書き終えてから、保存要求IDのディレクトリへ配置します。書込み途中の結果を確認候補として扱わないための処理です。

Reporterで元指示と結果を確認する

Reporter 0.1.6は、未公開結果に対応する元指示と結果本文を、読み取り専用の確認画面へ表示します。

人間が「確認して公開」を選んだ場合だけ、次のデータを保存します。

保存先 保存する内容
confirmed 確認済み結果、確認日時、対応元のhashなど
sources 対応する元指示の固定コピー

確認済みデータを別領域へ保存し、公開済み結果を未公開候補の一覧から除外します。

取消時に公開しない処理も実装されていますが、取消の実操作は未確認です。

src/vscode-instance-reporter/work_result_handoff.jsのconfirmAndPublishResultでは、確認処理がtrueを返した場合だけ公開処理へ進みます。次は関数全体の実コードです。confirmは人間の選択を返す確認処理で、beforePublishは公開直前の処理を受け取ります。

async function confirmAndPublishResult(
  snapshot,
  confirm,
  now = new Date(),
  beforePublish = async () => undefined,
) {
  const approved = await confirm(resultReviewText(snapshot));
  if (approved !== true) {
    return null;
  }
  await beforePublish();
  return publishResultSnapshot(snapshot, now);
}

publishResultSnapshotが、確認した元指示のコピーと結果を保存します。上の関数は、呼び出す順序と承認条件を担います。

この分離は、toolが提供する操作と確認手順によるものです。同じWindowsユーザーで動かしているため、OSのアクセス制御でCodexとReporterの権限を分離した構成とは扱いません。

2つのIDで読み取る理由

Workの読取りには、次の2つを指定します。

  • source_submission_id:どの指示に対する結果か
  • result_id:その指示に対する、どの結果か

validateConfirmedResultでは、結果本文のhash、対応する元指示のIDと本文hash、保存した元指示のコピー全体のhashなども検証します。

同じファイルのreadConfirmedResultは、結果IDで確認済みファイルを指定し、元指示IDとの対応も検証します。次は関数全体の実コードです。

async function readConfirmedResult(storageRoot, sourceSubmissionId, resultId) {
  if (typeof sourceSubmissionId !== "string" || !UUID_V4.test(sourceSubmissionId)) {
    throw new Error("source_submission_idがUUID v4形式ではありません。");
  }
  if (typeof resultId !== "string" || !UUID_V4.test(resultId)) {
    throw new Error("result_idがUUID v4形式ではありません。");
  }
  const record = await validateConfirmedResult(
    path.join(storageRoot, "confirmed", `${resultId}.json`),
    storageRoot,
  );
  if (record.source_submission_id !== sourceSubmissionId) {
    throw new Error("指定したresult_idはsource_submission_idに対応しません。");
  }
  return record;
}

掲載した3本のコードは実際の実装です。ID・hash照合は処理の一部の抜粋で、confirmAndPublishResultとreadConfirmedResultは関数全体です。依存関数や設定は含めていないため、単独実行用のサンプルではありません。

同じ指示に結果が2件あった

2026年10月4日の実確認では、同じsource_submission_idに対する公開結果が2件ありました。

その時点の一覧にはタイトルや本文のプレビューがなく、「自動受渡し確認」という本文名から対象を一意に選べませんでした。

一覧にない情報を使って選択させたWork側の指示が不適切でした。候補が一意に定まらない場合は選択を止め、対象の結果IDを明示する必要があります。

最新時刻も、意図した結果を示すとは限りません。そこで今回の本文読取りでは、両IDを指定し、対応が一致する結果だけを取得しました。

なお、両IDの一致は、指定した指示と結果の対応を検証するものです。人間が意図した結果IDを選べているかは、別に確認が必要です。

検証条件と結果

2026年10月4日、Reporter 0.1.6を導入したVS Codeと、新しいChatGPT Work会話でテスト本文を使って確認しました。

確認項目 結果 確認根拠
保存toolの利用確認 Codexでsave_unpublished_resultを検索し、呼び出せることを確認 tool検索・呼出し記録
元指示との対応 指示本文のSHA-256一致を確認 保存時の実行結果
未公開保存 テスト本文の保存に成功 保存結果
確認・公開 Reporter 0.1.6で成功 人間の実画面確認
Workでの読取り 両IDを指定し、保存した本文を取得 read_confirmed_resultの応答

省けた操作と残った負担

今回、省けたのは次の操作です。

  • 結果本文ファイルの手動作成
  • draft生成の依頼
  • draftファイルの選択

一方、次の作業は残っています。

  • Codexが保存toolを明示的に呼ぶこと
  • 人間による元指示と結果の確認・公開
  • 複数結果から対象IDを確認すること
  • Workへ両IDを渡すこと

実運用として確認が必要な範囲

今回確認したのは、テスト本文の保存・人間確認・公開・読取りまでです。取消、複数ウィンドウでの競合、PC再起動後の復旧、長時間運用、他リポジトリでの利用は実操作で未確認です。

Codexが返却手順に従って毎回保存toolを呼ぶか、日常の操作時間が短縮されるかも評価していません。

まとめ

結果の未公開保存、人間による内容確認・公開、両IDを指定したWorkでの読取りまで成立しました。

同じ指示に複数結果がある場合、対応する指示の確認だけでは戻す結果を選べません。対象を識別する情報と、指示・結果の対応を検証する処理の両方が必要です。

今回省けた操作と残ったID受渡しを含め、日常の転記負担が減るかは継続運用で評価する段階です。

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?