# codex レビュー結果 R1：lab_train.sh（2026-10-31 依頼 49）

依頼文: docs/review_request_20261031_lab_train.md（codex exec -s read-only）

**判定：必須修正あり。現状のまま今夜の無人学習へ投入することは勧めません。** 特に、Ubuntuで状態取得が壊れる点と、見張りが機能しなくても学習へ進む点が問題です。

指定ファイル・差分・過去レビューR1〜R3を確認しました。Shellの構文検査とPythonの構文解析は成功しました。書き込み・プロセス操作を伴うテストは実行していないため、105件・8件・93件の成功は申告結果として扱います。ファイル変更・実機・Pod・Hugging Faceの操作はしていません。

| 項目 | 判定 | 確認結果・修正案 |
|---|---|---|
| Ubuntuでのログ更新時刻取得 | **必須・P1** | [lab_lib.sh:251](/Users/shimazueiichi/r2r2r-scripts/lab_lib.sh:251)。`date -r "$L" +%s` はBSD/macOSの書き方です。UbuntuのGNU dateではログファイルを参照できず、続く算術展開が失敗してSTATUS行が出ません。正常終了も検出できず、最終的に上限でモデル未回収のまま削除する経路になります。Pod側は `stat -c %Y "$L"` を使い、取得失敗も明示的に扱ってください。 |
| 見張り不成立でも続行 | **必須・P1** | [lab_train.sh:500](/Users/shimazueiichi/r2r2r-scripts/lab_train.sh:500)。`run/pod/key` が揃わなくても警告だけで続行します。その後Macが停止すると削除する主体がなくなります。**見張り不成立は準備失敗として削除へ進む**必要があります。また鍵の「存在確認」は削除権限の確認ではありません。現在のコードだけではPod用鍵でDELETE可能とは確認できません。 |
| 見張りの削除失敗 | **必須・P1** | [lab_lib.sh:320](/Users/shimazueiichi/r2r2r-scripts/lab_lib.sh:320)。DELETEは1回だけで、CLIも失敗すると見張りが終了します。一時的な通信障害でもPodが残り続けます。各呼び出しに接続・処理時間の上限を設け、間隔を置いて再試行してください。`stop` 成功も削除完了ではなく、ディスク料金が残ります。 |
| 上限直前に正常終了した場合 | **必須・P1** | [lab_train.sh:557](/Users/shimazueiichi/r2r2r-scripts/lab_train.sh:557)。STATUS取得より先に上限判定します。例えば前回確認後に正常終了し、次の確認が5時間を超えると、成功済みモデルを回収せず削除します。上限到達時も最後に状態を取得し、正常完了なら回収へ進めてください。 |
| 一覧比較のエラーを一致扱い | **必須・P1** | [lab_train.sh:296](/Users/shimazueiichi/r2r2r-scripts/lab_train.sh:296)。`diff` の標準出力が空なら成功としており、一覧ファイルが読めない等の終了コード2も一致扱いになります。プロセス置換内の `lab_list_files` の失敗も直接確認できません。双方の一覧生成成功を確認してから、`diff` の**終了コード0だけ**を一致としてください。 |
| Pod作成〜見張り設置前のMac停止 | **必須・設計上の未充足** | [lab_train.sh:458](/Users/shimazueiichi/r2r2r-scripts/lab_train.sh:458)から497行。POSTがサーバー側で成功して応答が失われた場合や、SSH待機中にMacが停止した場合、Podに見張りがありません。「どの段階でもMac停止後に自動削除」を満たすには、作成時から働く仕組み、またはMac・当該Podと独立した期限監視が必要です。EXIT trapではこの区間を保証できません。 |
| テストの不足 | **必須・上記修正と併せて** | [test_lab_train.sh:46](/Users/shimazueiichi/r2r2r-scripts/test_lab_train.sh:46)。指定4ケースに加え、印なし終了・stall・削除失敗・既存保存先等はあります。ただしSTATUSは主に偽物で、実コマンド検証もMac上です。**Ubuntuでの状態取得、上限前完了／上限後確認、見張り不成立、DELETE一時失敗、比較処理の読取エラー**を追加してください。158行のINT直後TERM送信では、Ctrl-C単独の処理成功は証明できません。 |
| 回収中の見張り延長 | **推奨** | [lab_train.sh:335](/Users/shimazueiichi/r2r2r-scripts/lab_train.sh:335)。延長失敗でもアップロードへ進み、成功しても3時間固定です。従来期限や延長後期限を過ぎれば転送途中でも削除されます。延長失敗を明示し、転送処理に時間上限を設けるか、最大期限付きで定期更新してください。期限ファイルの更新は一時ファイルからの置換が堅実です。 |
| 見張りの鍵探索・秘匿 | **据え置き＋推奨** | [lab_lib.sh:307](/Users/shimazueiichi/r2r2r-scripts/lab_lib.sh:307)。環境変数→PID 1の環境→設定ファイルという探索と、curlヘッダーをFD経由で渡す構成は妥当です。明示的な鍵の出力はありません。ただしCLIの出力はそのままログへ入るため、「必ず秘匿」は未確認です。探索元の形式差・鍵なし・CLI失敗のテストを補ってください。 |
| `pgrep/pkill` の自己一致 | **据え置き・妥当** | [lab_lib.sh:203](/Users/shimazueiichi/r2r2r-scripts/lab_lib.sh:203)。wrapper・見張り・GPUの先頭固定パターンは `bash -c …` に一致しません。停止コマンドのtrain.pyも `[s]` 表記で、通常表記の起動コマンドとは分離されています。過去R1と同じ自己一致は見当たりません。 |
| `setsid nohup` とSSH終了 | **据え置き・構成は妥当** | [lab_lib.sh:224](/Users/shimazueiichi/r2r2r-scripts/lab_lib.sh:224)。背景プロセスの標準入出力・標準エラーをSSHから切り離しており、SSHを保持する構成ではありません。実際のUbuntu上での起動・切断試験は未実施です。 |
| 成功判定・tqdm・30分判定 | **据え置き＋推奨** | [lab_train.sh:566](/Users/shimazueiichi/r2r2r-scripts/lab_train.sh:566)。終了コード0・最終番号・metadataで成功を決め、tqdmやlossは表示用なので、表示の読み漏れ自体で成功判定は変わりません。一方、ログ無更新30分は長い初期化・保存も停止扱いにします。固定コミットの実ログで、CR・表示接頭辞・初期化・最終保存中の挙動を確認してください。 |
| HF非公開・上書き・除外 | **据え置き・通常経路は妥当** | [hf_upload_ckpt.py:79](/Users/shimazueiichi/r2r2r-scripts/pi05/openpi_addon/hf_upload_ckpt.py:79)。非公開で作成し、公開なら停止、既存一覧が違えばアップロードしません。`train_state/` の一覧除外とアップロード除外もあります。ただし名前・サイズ一致はバイト内容一致の証明ではなく、確認とアップロード間の並行更新防止もありません。単独運用という前提を明確にしてください。 |
| MacのHF認証 | **据え置き・要件どおり** | [lab_lib.sh:352](/Users/shimazueiichi/r2r2r-scripts/lab_lib.sh:352)。`HF_TOKEN_PATH` にファイルの場所を渡しています。既存の環境変数 `HF_TOKEN` が設定されている場合の影響も避けるなら、そのコマンドに限ってunsetしてください。 |
| KIOXIAの既存データ | **据え置き＋推奨** | [lab_train.sh:306](/Users/shimazueiichi/r2r2r-scripts/lab_train.sh:306)。既存の最終保存先には比較だけを行い、モデル回収での `rm -rf` は自分の一時フォルダ内です。datasets/runsを操作する追加処理もありません。ただし確認後に別実行が保存先を作ると、324行の `mv` がその中へ一時フォルダを入れ得ます。保存先単位の排他を加えると確実です。 |
| lab_start.shの回帰・名前衝突 | **据え置き・問題なし** | 3b〜3fは空白・改行を除き同じコマンドです。定数も同値です。`p2m-train-<Log>` と `p2m-<Log>`、`train/` と `pod/` は分離されており、同名判定への新たな衝突は見当たりません。 |

**今夜の投入前には、少なくとも必須項目の修正と、その失敗経路を通すテストが必要です。現状では「正常終了モデルの回収」と「Mac停止後のPod自動削除」の両方に未充足があります。**
