# コードレビュー結果：補正データの角度の作り直し・記録で daemon とのやりとりを残す（codex・2026-10-31 / 依頼 46）

- 実施: codex exec -s read-only --skip-git-repo-check（読み取りのみ）
- 依頼文: docs/review_request_20261031_gap_fill_recorder_rpc.md

**必須1件、推奨6件です。** Bの通常経路で指令や例外の型を変える不具合は見つかりませんでした。Aは説明どおりの実装ですが、生成した角度は実測の復元ではなく、一定速度を仮定した推定値です。

| 項目 | 判定 | 確認結果・修正案 |
|---|---|---|
| Podのtar再展開 | **必須** | [pod_prep_trim_corr.sh:37](/Users/shimazueiichi/r2r2r-scripts/pi05/openpi_addon/pod_prep_trim_corr.sh:37)は既存ディレクトリへ上書き展開します。同じ名前でtarを作り直し、エピソードや末尾フレームを減らすと、旧ファイルが残ります。変換が旧エピソードを混入させたり、画像枚数不一致で停止したりします。**空の一時ディレクトリに展開・検証してから切り替える**方式にしてください。同一tarの再実行は可能ですが、更新tarへの追従は安全ではありません。 |
| 指令・返事・例外・timeout引数 | 据え置き | [policy_recorder.py:87](/Users/shimazueiichi/r2r2r-scripts/pi05/policy_recorder.py:87)は引数をそのまま`orig`へ渡し、返事をそのまま返し、元の例外を裸の`raise`で再送出します。timeout計算自体は変更していません。観察関数の通常の例外も本体へ漏れません。 |
| 再接続・再帰ping | **推奨** | RLockなので再帰pingで自己デッドロックしません。ただし内側pingの`_notify_rpc`実行時には、**外側RPCのロックは保持されたまま**です。「必ず鍵の外」は成立しません。現状の`_on_rpc`はpingを無視するので実害は見当たりませんが、外側RPC終了まで通知を保留するか、この例外を明記してください。 |
| 観察による本体の遅延 | **推奨** | 観察は同期呼び出しです。CSVロック待ち・書き込み・flushが終わるまでRPCが呼び出し元へ戻らず、到着確認の残り時間に影響し得ます。「timeout引数は変えない」は成立しますが、「処理時間への影響なし」は保証できません。必要なら観察結果をキューへ渡し、書き込みを別処理にしてください。 |
| CSVの排他・stop・二重記録 | 据え置き | 書き込みとcloseは`csv_lock`で排他され、close後は書き込みを避けます。通知のスナップショットにstop前の関数が残っても、`stop_flag`で通常は除外されます。記録スレッド自身のget_anglesはスレッドオブジェクトの同一性で除外され、既存`_angle_loop`だけが記録します。 |
| stopと集計値の競合 | **推奨** | `_on_rpc`がstop判定を通過したあとでstopすると、行が書かれなくても`n_actual_main`／`n_sends`だけ増える場合があります。カウンター更新も書き込み成功と同じロック内に置くと、metaとの整合性を保てます。 |
| states.csvの読み手 | 据え置き | `build_demo_episodes.load_states`は`actual`／`gripper_cmd`だけを読み、補正側のstage読み込みは`stage`行だけを読みます。追加の`send_angles`／`rpc`は無視され、`actual note=main`は実測として採用されます。両builderは実測時刻をソートするため、通知順によるCSVの時刻逆転にも対応しています。 |
| Aの速度・閾値・補間 | 据え置き・条件付き | [fill_motion_gaps:135](/Users/shimazueiichi/r2r2r-scripts/pi05/build_correction_episodes.py:135)は指定どおりです。linearは従来の`np.interp`、speed20は最大移動関節30°/秒で進んで保持し、時間不足時はlinearになります。30°/秒は提示された実測集計に根拠がありますが、全関節の同時到着・加減速・動き始めの時刻までは確認できません。0.25秒は抜けの検出基準として使えますが、送信由来であることの証明にはなりません。 |
| 複数送信・送信以外の抜け | **推奨** | Aは送信記録を参照せず、すべての長い抜けを同じ方法で埋めます。往復する2送信をまたぐと、端点が同じなら途中の動作が消えます。記録停止中の移動も抜けの頭へ前倒しされます。静止した爪操作は問題ありません。曖昧な抜けの一覧をmetaに残し、該当区間をlinearへ戻す／除外する判断材料にしてください。 |
| 抜けと送信の対応付け | **推奨** | [match_gaps_to_sends:192](/Users/shimazueiichi/r2r2r-scripts/pi05/build_correction_episodes.py:192)は誤対応し得ます。例として、抜け①が`[1.0, 2.6]`、抜け②が`[2.7, 4.3]`、補正時刻が`2.5`なら両方の候補になり、先の①を選びます。複数送信が1抜けに入っても最初の補正だけが対応済みになります。チャンクも個数一致だけでは対応の証明になりません。候補の重複・複数送信を`ambiguous`として分け、到着誤差の集計から外すことを勧めます。学習配列自体への影響はありません。 |
| corr_v2設定・変換先・処理順 | 据え置き | corr_v1の既定マーカーがあれば書き込み前に停止し、corr_v2の同じsteps/initでは再追加しません。手順は設定追加→変換→正規化で妥当です。`set -euo pipefail`もあります。変換の`rmtree`は、このスクリプトの固定repo_idでは`HF_LEROBOT_HOME/local/mecharm_redblock_box_teach_v1_trim2_corr_v2`に限定され、trim2やcorr_v1は対象外です。 |
| テストの十分性 | 推奨 | Aの基本形とBの正常通信は確認しています。ただしBの「二重記録なし」の件数比較は弱く、二重でも通る場合があります。再帰ping中のロック状態、timeout・同一例外の再送出、観察関数の失敗、stopとの競合、無効角度、複数送信をまたぐ抜け、曖昧な対応付け、更新tar再展開を追加すると、今回の懸念を直接検証できます。 |

`correction_rows`は全correction行、`correction_moves`は未送信を含むmove行を数えており、コメントと一致します。`max_step_deg`は**除外・圧縮後の隣接state間の差**なので、元の時間軸における0.1秒あたりの変化とは限りません。

ファイル変更・実機操作はしていません。テストは一時ファイルやソケットを作るため実行せず、読み取りで確認しました。申告の全テスト成功・5本のlinear一致・実測速度集計は再検証していません。
