# コードレビュー依頼：実機推論の待ち時間を縮める / 届かなかった分を次の刻みに足す / R を使った補正も巻き戻す（2026-10-30 依頼 35）

前提: 依頼 34 (コミット be68f74. 補正の r / R と「着いた」の判定) の続き。
過去のレビュー: docs/review_result_20261030_regrip_reach_codex.md ほか

対象 (`git diff HEAD -- pi05/` で差分。ほかのファイルの未コミットの差分は今回の対象外):
- `pi05/run_policy_client.py`（待ちの定数と引数 / gripper_cmd / apply_wait_args / run_correction の carry と R / main の b の問い / run_rewind の GRASP_HELD）
- `pi05/rewind_correct.py`（MODE_REGRIP / GRASP_HELD / correction_shortfall / correction_carry_used）
- `pi05/build_correction_episodes.py`（説明文だけ。regrip は TRAIN_MODES に入らないので step_keep_mask が既に除く）
- `pi05/test_rewind_correct.py`（16 件追加。計 62 件 OK。レビュー反映後 17 件・計 63 件。既存 46 件と git HEAD 比較のテスト test_unchanged_without_b_c も通る）

参照（変更していない）: `dynamic_tracking_limits/place/place_modules/j0_sweep_scan.py` の `_send_and_wait_arrival` / `visual_servo_pick.py` の `_daemon_request`・`daemon_set_gripper`・`daemon_send_angles` / Pi の daemon は `mecharm_daemon.py.pi_deployed_20261019_LOG352`（send_angles は wait 秒 sleep → 現在角を読み直し（動作中は最長約 3.7 秒）→ 応答。set_gripper は固定 2 秒 sleep → 指令 → wait 秒 sleep）/ docs/investigation_20261019_stageC_daemon_latency.md

## エイイチの判断（依頼 34 の未決への答え）
1. 待ち時間はもっと短くてよい（「time.sleep() を短縮しない」の決まりより優先）
2. 届いていないときは次の刻みに足りなかった分を足す
3. R を使った補正も b で巻き戻せるようにする
4. R の開け閉めのコマは学習データに入れない
5. 爪が開いているときの R は何もしない（そのまま）

## 仕様と実装
A. 待ち（本線と共有の定数は変えず run_policy_client.py の中で上書き。引数で前の値に戻せる）
| 待ち | 前 | 今 | 引数 |
|---|---|---|---|
| 送ったあと daemon が待つ（_send_and_wait_arrival の send_wait_sec・settle の再送・HOME） | 1.0 (SEND_WAIT_SEC) | 0.0 | --send-wait |
| 爪の開け閉めのあと Mac で待つ GRIPPER_SLEEP | 2.0 | 0.8 | --grip-wait |
| 開くとき daemon が待つ（daemon_set_gripper の wait） | 2.0 | 0.0 | --grip-open-wait |
| 止まるのを待つ目安 SETTLE_WAIT_SEC（補正の 1 刻み・settle） | 2.0 | 0.8 | --settle-wait |
- 送ったあとの待ちを 0.3 ではなく 0.0 にした理由: `_daemon_request` は wait > 0 のとき応答待ちの上限を wait + 3 秒にする。daemon は wait のあと現在角を読み直し、動作中は最長約 3.7 秒かかる（LOG352）。0.3 だと上限 3.3 秒で、読み直しより短くなりうる（今の 1.0 でも 4.0 秒 < 1.0 + 3.7）。0 なら上限は DAEMON_TIMEOUT_SEC 35 秒。この wait は daemon の「送信後の現在角」の記録を遅らせるだけで、着いたかは Mac 側の 3° の到着確認で見る（そのまま）
- 変えないもの: 到着確認のポーリング間隔 POLL_SLEEP 0.3 と読み取りの再試行（本線の定数で、関数に引数がない）/ daemon の set_gripper の固定 2 秒（Pi 側）/ SETTLE_POLL_SEC 0.2 / read_angles の 0.1 / カメラ待ちの 0.2
- 新しい停止条件・確認は足していない
B. 届いていないときの上乗せ（run_correction）
- 依頼 34 の判定（動かした関節だけ・刻みの半分・下限 0.5°）で「届いていない」とき、足りなかった量（動かした向きに測る。行き過ぎ・読めない・着いたら 0）を、同じ関節・同じ向きの次の 1 刻みに足す
- 上限はその刻みの大きさ（1 回で動く量は刻みの 2 倍まで）
- やめる: 届いた / + と - を切り替えた / ほかの関節を選んだ（選び直して戻っても足さない）/ 送りの判定 3° で未到達 → resync（実測から数え直すので足りない分は既に入っている）
- 足した目標も plan_correction_step（apply_limits と check_send_safe）をそのまま通す
- move 行に carry_deg。足したときはターミナルに「足りなかった 1.5° を足して送る (j1 を -3.5°)」
C. R を使った補正の巻き戻し
- R は grip_used を立てなくなった（代わりに regrip_used）。g を使った補正は grip_used=True のまま断る（今のまま）
- history の補正に regrip。外の b で直前が「R を使い g を使っていない補正」なら 1 文字で聞く: y → GRASP_HELD（閉じたまま逆にたどる）/ n → GRASP_DROPPED（その場で開いてから逆にたどる → 置き直しの Enter 待ち（wait））/ その他 → やめる
- run_rewind: GRASP_HELD は grasp なしと同じ traverse。finished は (grasp が None か HELD か, 開いた) を満たすとき
- R を使ったら開始時の開放を済ませた扱い（grip_opened = True。前は grip_used で同じことをしていた）
D. regrip のコマ
- R で開く直前に recorder.set_mode("regrip")、閉じ終わったら（GRIPPER_SLEEP のあと）"correct" に戻す。r は correct のまま
- build_correction_episodes は TRAIN_MODES = (model, correct) 以外を除くので regrip のコマは入らない

## チェック項目
A1. 待ちを縮めても、到着を確かめる前に次の目標を送る経路がないか（中継点・補正の 1 刻み・巻き戻し・HOME・settle）
A2. send_wait 0 で daemon・_daemon_request の応答待ちや再送 (_send_and_wait_arrival の RETRY) に悪影響がないか。0.3 より 0 の方が安全という判断は正しいか
A3. 爪の待ち 0.8 秒と開くときの daemon の wait 0 で、閉じ切る前・開き切る前に次の送信や撮影が走る危険（DAY228「close 直後の send_angles 沈黙」を含む）
A4. 引数で前の値に完全に戻せるか。グローバルを書き換える実装に問題がないか
B1. 足す量・上限・やめる条件が仕様どおりか。resync との二重計上がないか
B2. 足した目標が範囲チェックを必ず通るか
C1. R を使った補正の y / n の順番（n は開いてから戻る）。g を使った補正は今までどおり断るか
C2. b のあとの grip 変数・記録・history（blocked の積み方）に食い違いがないか
D1. regrip の印の付け方と、build_correction_episodes の除き方
E. 安全: send_coords 不使用・release_all_servos 不使用・範囲の値は不変

## レビュー結果のフォーマット
各項目 ✅ OK / ⚠️ 要注意 / ❌ NG（行番号と修正案）。最後に実機テストに進んで良いか・直すべき項目。
ファイルは変更しないでください (読み取りのみ)。
