何を見つけたか
cross-review と cross-refactoring の init が共有する、参加する CLI の確認
(plugins/ndf/scripts/lib/auth.py の probe_auth)は認証だけを確かめる。 そのため、
モデルを引けない CLI や更新トークンが失効した CLI も確認を通り、担当に当たるとラウンドを
1 つ潰して中断する。
観測はいずれも cross-review である。cross-refactoring の init も同じ確認を通るため、
同じ CLI を担当へ入れる(cross-refactoring での観測は無い)。
2026-09-07 に PR #460(cross-review)のラウンド 2 で観測した。init は次を出す。
✅ codex: codex login status
しかし実際の応答は 404 である。
$ tail -3 .cross_review/codex-review-pr460-err.log
warning: Falling back from WebSockets to HTTPS transport. unexpected status 404 Not Found:
The model `gpt-5.5` does not exist or you do not have access to it.
ERROR: unexpected status 404 Not Found: The model `gpt-5.5` does not exist or you do not have
access to it., url: https://chatgpt.com/backend-api/codex/responses
結果ファイルが残らないため NO_RESULT となり、同じラウンドで起動し直しても同じ結果に
なって final=error で中断する。
❌ 起動し直した後も結果が残りませんでした: codex。 実行環境の側の問題として中断します
モデルは利用者の設定が持つ。 ~/.codex/config.toml の model = "gpt-5.5" であり、
その利用者がそのモデルを引けるかは認証の成否と別である。
404 の文言は早期の致命検知にも一致しない。 monitor.py の _scan_early_fatal にこの行を渡すと
None(一致なし)が返る(実行結果は #619 にある)。そのため起動直後に止まらず、起動し直しを含めて 2 回分を失う。
同じ形の別の観測: 更新トークンの失効(2026-09-15)
codex login status が通っても、更新トークンが失効していると実行は 401 で落ちる。 PR #666 の cross-review の round 1 で観測した。init は ✅ codex: codex login status を出したが、codex は 15 秒で結果を残さず終わった。
$ tail -2 .cross_review/codex-review-pr666-err.log
ERROR: Your access token could not be refreshed because your refresh token was revoked. Please log out and sign in again.
同じ日に PR #661 のラウンド 1(ndf 10.10.1)でも同じ形を踏んだ。 init は 2026-09-15 11:00 UTC に 3 者すべてを通した。
✅ codex: codex login status
✅ agy: agy models
✅ kiro: kiro-cli whoami
同じ時刻に起動した codex の codex-review-pr661-err.log:
ERROR codex_login::auth::manager: Failed to refresh token: 401 Unauthorized: {
"error": { "message": "Your session has ended. Please log in again.", "code": "refresh_token_invalidated" } }
ERROR: Your access token could not be refreshed because your refresh token was revoked. Please log out and sign in again.
- 監視は
status=NO_RESULT / exit_code=3 / elapsed=0.0 を返した。進行側が err.log を開くまで、原因が認証であることは分からなかった
- 進行側は担当を手で差し替えて回避した(
rounds[-1].reviewers の書き換え)
/goal の下では、担当が実行できないと異常終了になる
どこで見つけたか
| 場所 |
記述 |
plugins/ndf/scripts/lib/auth.py の AUTH_PROBES (:19-26) |
認証の確認。CLI ごとに 1 コマンドを実行し、終了コードを見る(codex は codex login status、agy は agy models)。モデルを引く確認は無い。冒頭の説明(:1-9)は「cross-refactoring と cross-review の両方が同じ確認を行う」と書く |
plugins/ndf/skills/cross-review/scripts/state.py:2159 |
cross-review の init が auth.probe_auth を呼ぶ |
plugins/ndf/skills/cross-refactoring/scripts/refactor_lib/commands/setup.py:137 |
cross-refactoring の init が同じ auth.probe_auth を呼ぶ |
plugins/ndf/skills/cross-review/SKILL.md:128 の「前提」 |
「担当になる CLI は init が起動前に確かめ、通らない者は外して続ける」 |
plugins/ndf/skills/cross-refactoring/SKILL.md:149 の「前提」 |
「参加者の CLI がログイン済みである。init が認証状態を確認し」 |
「確かめる」の中身が、認証の成否だけになっている。
なぜこの変更の範囲外なのか
#446 / #440 / #441 は cross-refactoring の構造整理で、両 Skill が共有する起動前の確認は
対象に含まない。設計 Pull Request のレビューを回している最中に踏んだ。
直さないと何が起きるか
引けないモデルを設定している利用者は、その CLI が担当に当たるたびに 1 ラウンドを失う。
| 影響 |
中身 |
| ラウンドの消費 |
起動し直しを含めて 2 回分の待ちが発生し、そのラウンドの指摘は 0 件になる |
| 中断 |
final=error になり、収束したかどうかを判定できないまま最終スイープへ進む |
| 原因が見えない |
init は ✅ を出しているため、利用者は認証済みだと読む。原因は err.log を開くまで分からない |
回避には state を作り直すことになる。 輪番はラウンド番号から決まるため、final が
立った state のままでは同じ担当を引き直せない。
考えられる向き(決めるのは着手時)
- 認証の確認を、モデルを引く最小の応答まで含める(費用は 1 回の短い呼び出し)
- 引けない CLI を母集合から外して続ける(中断しない)
- 失敗の理由を
init の出力へ出す(err.log を開かずに分かる)
由来
issue #446
関連
何を見つけたか
cross-reviewとcross-refactoringのinitが共有する、参加する CLI の確認(
plugins/ndf/scripts/lib/auth.pyのprobe_auth)は認証だけを確かめる。 そのため、モデルを引けない CLI や更新トークンが失効した CLI も確認を通り、担当に当たるとラウンドを
1 つ潰して中断する。
観測はいずれも
cross-reviewである。cross-refactoringのinitも同じ確認を通るため、同じ CLI を担当へ入れる(
cross-refactoringでの観測は無い)。2026-09-07 に PR #460(
cross-review)のラウンド 2 で観測した。initは次を出す。✅ codex: codex login statusしかし実際の応答は 404 である。
結果ファイルが残らないため
NO_RESULTとなり、同じラウンドで起動し直しても同じ結果になって
final=errorで中断する。❌ 起動し直した後も結果が残りませんでした: codex。 実行環境の側の問題として中断しますモデルは利用者の設定が持つ。
~/.codex/config.tomlのmodel = "gpt-5.5"であり、その利用者がそのモデルを引けるかは認証の成否と別である。
404 の文言は早期の致命検知にも一致しない。
monitor.pyの_scan_early_fatalにこの行を渡すとNone(一致なし)が返る(実行結果は #619 にある)。そのため起動直後に止まらず、起動し直しを含めて 2 回分を失う。同じ形の別の観測: 更新トークンの失効(2026-09-15)
codex login statusが通っても、更新トークンが失効していると実行は 401 で落ちる。 PR #666 の cross-review の round 1 で観測した。initは✅ codex: codex login statusを出したが、codex は 15 秒で結果を残さず終わった。NO_RESULT(process exited but result.json missing)で、モデルの 404 と同じ出口(起動し直し →final=error)に入るinitで拾える_scan_early_fatalに一致しない。理由の区別の土台は cross-review: レビュー担当の CLI が利用上限に達すると NO_RESULT(missing)として起動し直し、上限であることが出ないまま error で終わる #619 の設計(PR Docs: 監視の結果・上限の順序・打ち切りの後に結果を失わない形の要求と設計(#662 #598 #537 #619 #584 #583) #666)にあるが、この文言は語彙に入れていない同じ日に PR #661 のラウンド 1(ndf 10.10.1)でも同じ形を踏んだ。
initは 2026-09-15 11:00 UTC に 3 者すべてを通した。同じ時刻に起動した codex の
codex-review-pr661-err.log:status=NO_RESULT / exit_code=3 / elapsed=0.0を返した。進行側がerr.logを開くまで、原因が認証であることは分からなかったrounds[-1].reviewersの書き換え)/goalの下では、担当が実行できないと異常終了になるどこで見つけたか
plugins/ndf/scripts/lib/auth.pyのAUTH_PROBES(:19-26)codex login status、agy はagy models)。モデルを引く確認は無い。冒頭の説明(:1-9)は「cross-refactoringとcross-reviewの両方が同じ確認を行う」と書くplugins/ndf/skills/cross-review/scripts/state.py:2159cross-reviewのinitがauth.probe_authを呼ぶplugins/ndf/skills/cross-refactoring/scripts/refactor_lib/commands/setup.py:137cross-refactoringのinitが同じauth.probe_authを呼ぶplugins/ndf/skills/cross-review/SKILL.md:128の「前提」initが起動前に確かめ、通らない者は外して続ける」plugins/ndf/skills/cross-refactoring/SKILL.md:149の「前提」initが認証状態を確認し」「確かめる」の中身が、認証の成否だけになっている。
なぜこの変更の範囲外なのか
#446 / #440 / #441 は
cross-refactoringの構造整理で、両 Skill が共有する起動前の確認は対象に含まない。設計 Pull Request のレビューを回している最中に踏んだ。
直さないと何が起きるか
引けないモデルを設定している利用者は、その CLI が担当に当たるたびに 1 ラウンドを失う。
final=errorになり、収束したかどうかを判定できないまま最終スイープへ進むinitは✅を出しているため、利用者は認証済みだと読む。原因はerr.logを開くまで分からない回避には state を作り直すことになる。 輪番はラウンド番号から決まるため、
finalが立った state のままでは同じ担当を引き直せない。
考えられる向き(決めるのは着手時)
initの出力へ出す(err.logを開かずに分かる)由来
issue #446
関連
err.logに理由を書いて終わっても、結果なし(missing)へ畳まれる。起動後の早期の致命検知の語彙(plugins/ndf/scripts/lib/monitor.py:178のEARLY_ERROR_FATAL)は cross-review: レビュー担当の CLI が利用上限に達すると NO_RESULT(missing)として起動し直し、上限であることが出ないまま error で終わる #619 が持つ。 404 と更新トークンの失効の文言を起動後に検知するのは cross-review: レビュー担当の CLI が利用上限に達すると NO_RESULT(missing)として起動し直し、上限であることが出ないまま error で終わる #619、起動の前に拾うのはこの課題であるplugins/ndf/scripts/lib/auth.pyのprobe_authとassignment.py)が「最小の呼び出しが通るか」で使える者を決め、割り当てがその一覧から担当を選ぶexternal-ai.sh check <runtime>を持つ。「使えるか」の確認は 基盤: 外部 CLI の起動・上限つきの待ち・回収を 1 本のスクリプトにする(external-ai.sh run) #852 のcheckと同じ probe にする(2 つ目の probe を作らない)。auth.probe_authを最小の呼び出しまで広げるなら、基盤: 外部 CLI の起動・上限つきの待ち・回収を 1 本のスクリプトにする(external-ai.sh run) #852 のcheckもそれを読む