# フィジカルAI研究室を作る Log#36 | ロボットアームの学習データに、成否を付ける判定の画面を作った

- 記録: LOG512（フィジカルAI研究室）
- 公開: 2026/11/15
- 記事のページ: https://pixelstomotors.com/record/mecharm-270-demo-data-half-motion-interpolated
- サイト: Pixels to Motors（ADAPT DESIGN / 島津 栄一） https://pixelstomotors.com/
- 要約: 小型ロボットアーム mechArm 270 で π0.5 を動かした記録176回に、成否とだれが付けたかを付ける判定の画面を作り、成功率59.8%を基準にした。お手本の動きの半分ほどは、実測でなく直線で補った値だった。

> AI が読むための記事の全文です（コード・実行ログを含む）。引用するときは上の「記事のページ」の住所を使ってください。

---

**小型ロボットアーム mechArm 270 で Physical Intelligence の π0.5 を実機で動かした記録176回に、成功か失敗かと「だれが付けた判定か」を付ける判定の画面を作り、全部に印を付けた。成功率は59.8%（55/92）で、学習し直したあとに比べる基準になった。** AI が先に判定を付け、人が録画と関節のグラフを見て確かめて確定する形です。同じ作業の中で、学習に使っていたお手本（アームを動かした記録）の角度を1コマずつ数え、アームが動いた量の半分ほどが実測ではなく、前後の実測を直線で結んで補った値だったことも分かりました。手で教えたお手本では動いた量の56〜59%が角度を読めない1秒の待ちの中にあり、推論を人が直して作った補正のお手本では、学習に使った本のコマの41〜46%が補った値でした。

この回の作業で、次のことが変わりました。

- 推論の記録176回すべてに、成功・失敗と「だれが付けた判定か」が入った。人が画面で見て確定したのは25回で、画面の直しを挟みながら約40分（22:49〜23:29）。いまの成功率59.8%（55/92）が、学習し直したあとに比べる基準になった
- これから作る補正のお手本には、1コマずつ「実測」「補った値」の印が残る。値そのものは1つも変えていない（既存の14データセット・95本を作り直して、すべて一致することを確かめた）
- 手で教えたお手本の角度が0.32秒おきにしか読めていない原因が、記録の作りだと分かった。アームの動きを変えずに読み取りを増やす案があり、撮り直せば補った値は減る見込み（実機ではまだ確かめていない）

きっかけは、ものづくり太郎チャンネルの動画 [【予言的中？】製造現場のAI活用はどこまで来たか？](https://www.youtube.com/watch?v=GmwphgG7cG4) です。エアリオンの河村さんが、フィジカルAI の学習データは量より質が問われるようになると話し、その例として「ちゃんとラベリングしてデータの質を記録してますか？」と問いかけていました。どんな動きか、いつの記録か、成功したときのデータか失敗したときのデータか。そうした印（ラベル）を付けて仕分けておくことが大事だ、という話です。手元のデータで、この問いに答えられるかを確かめました。

答えは半分だけ「はい」でした。日付・動き・外した理由は、ファイルに残っていました。ところが推論の記録176回のうち108回には成功か失敗かの印がなく、付いている印も人が付けたのか AI が付けたのか分かりませんでした。さらに、学習に入れている角度のかなりの部分が、測った値ではなく、間を直線で埋めた値でした。

| やったこと | なぜ | 結果 |
|---|---|---|
| 手元のデータのラベルを数えた | 動画の問いに答えられるかを見る | 日付・動き・外した理由はあった。推論の記録は108回に成否がなく、だれが付けたかも分からなかった |
| 判定の画面を作り、176回を確定した（依頼183〜195・198） | 大きな仕組みは作らず、成否を付ける画面を1枚だけ作る | AI が先に判定し、人が確かめて確定。176回すべてに印が付き、成功率は59.8% |
| 補ったコマに印を付け、既存のお手本を数えた（依頼196） | 補った値がどれだけ入っているかを測る | 学習に使った補正のお手本は、コマの41〜46%が補った値 |
| 手教示の読み取りが0.32秒おきの原因を調べた（依頼197） | 手で教えたお手本にも補った値が多かった | 原因は記録の作り。動いた量の56〜59%が、角度を読まない1秒の待ちの中にあった |

試しの記録と、この回に使った材料（依頼文・報告・差分・データ・画面の写し）は KIOXIA の `lab/Log36/` に入れています。

GPU を買うか借りるかの判断は、Runpod で実際に借りて学習させた費用をもとに、別のページにまとめています。この回で測ったお手本も、その借り方で学習させてきたものです。

[ロボットAIの学習用GPU、買うか借りるか](https://pixelstomotors.com/gpu-buy-or-rent)

[図解: LOG512_data_quality.html](https://pixelstomotors.com/embeds/LOG512_data_quality.html)


## 作業ログ ― 動画の問いから、推論176回のラベルとお手本の補った値を数えるまで

ここから下は作業の記録です。依頼文・報告・コードの差分・データは全量で載せます。効果を書いた所のうち、数字で書いたものは測った値、「見込み」と書いたものはまだ確かめていない値です。

この回で何度も出てくる言葉を先に言い換えておきます。

- π0.5：[Physical Intelligence](https://www.pi.website/blog/pi05) が公開しているロボット用の AI。上カメラの画像と関節の角度を見て、次の動きを出す
- お手本：π0.5 に学ばせるための、アームを動かした記録。画像と関節の角度が0.1秒ごとに並ぶ。手で教えた要所を再生して撮ったもの（手教示）と、推論を人がゲームパッドで直して成功させたもの（補正）の2種類がある
- ラベル：記録1本ごとに付ける印。この回では、成功したか・失敗したか、つかめたか（pick）・箱に置けたか（place）、だれが付けたか
- 推論の記録：π0.5 を実機で動かした1回分の記録。KIOXIA の `runs/pi05_policy/{名前}/` に入る
- 補った値：アームの角度が読めなかった間を、前後の実測の角度を直線で結んで埋めた値。0.1秒ごとのコマに並べ直すときに作る
- 依頼箱：Claude Code への依頼をファイルで置いておく Mac のフォルダ。置くと見張り係が順に Claude Code に渡し、結果を書き戻す
- [Claude Code](https://www.anthropic.com/claude-code)：Anthropic の、コードを書いて動かす AI。この回のコードはすべて依頼箱から Claude Code が書いた


## 動画で挙がったラベルの項目と、手元のデータを突き合わせた

動画の画面の録画（10分55秒）から字幕を切り出して読み、ラベルについて話している所を拾いました。挙がっていたのは、どんな動作をしたか、日付、タスクが成功したときのデータか失敗したときのデータか、そして、AI が自動でラベルを付けて点数を付け、人の判断と AI でブレを確かめて記録すること、の4つです。

そのうえで、KIOXIA の `r2r2r-data/` を Mac 連携の shell で数えました。

| 動画の項目 | 手元にあるか | どこにあるか |
|---|---|---|
| 日付 | ある | すべての記録の名前に日時が入っている |
| どんな動きか | ある | タスクの文、1コマごとの「モデル／人の補正」の区別（`step_modes`）、爪の指令 |
| 成功／失敗 | ある（抜けが多い） | 台帳の pick/place の判定（813行）、お手本の `human_verdict`、推論の記録の `outcome` |
| 点数 | 一部ある | 把持の深さ（閉じて1秒後のはみ出しの画素数）で浅い本を外している。1コマで一番大きく動いた角度（`max_step_deg`） |
| 外した理由 | ある | データセットの `index.json` に、外した本と理由 |
| 人＋AI の確認 | ある（区別できない） | AI（VLM）の判定の列と、判定の列 |

弱いところを数で並べると、こうなりました。

| 弱いところ | 数 |
|---|---|
| 推論の記録のうち成否の印がない回 | 176回のうち108回（結果のファイルがない97回・`outcome` が null の11回） |
| 台帳の自信度（`pick_confidence`）が固定に近い | 813行のうち397行が 0.82 |
| 台帳の pick の判定と AI の判定の一致 | 464件のうち413件。人が確かめたかどうかを区別する列がない |
| 台帳の空欄と unknown | pick は空欄152・unknown 27、place は空欄268・unknown 57。試しの行（`run_0042_test`）と dry-run の行も残っている |
| ずれが分かっているラベル | `scripted_v1` の爪を開く印が約2秒（約20コマ）早い。注記だけで未補正 |
| 補った値に1コマごとの印がない | `episode.npz` は `t`・`t_orig`・`state`・`actions` だけ |
| 同じ元の記録の使い回し | 19データセット・375本の元は82回。1回の記録が最大14のデータセットに入っている |
| 種類 | 作業は1つ（赤いブロックを白い箱へ）、物も場所も1つ。画像は 384×216 |


## 大きなプラットフォームは作らず、判定の画面を1枚だけ作る

動画の中では、エアリオンが作っているフィジカルAI の開発基盤（動画では Physical AI Studio、画面には Physical AI Canvas と出ていた）が紹介されていました。センサー・ロボット・記録の部品を線でつないでデータ集めを組み、記録の一覧で自動のラベルと点数を見られるものです。エアリオンは矢崎総業にこの基盤を提供すると[報じられています](https://itbusinesstoday.com/ja/tech/ai/airion-yazaki-team-up-on-autonomous-physical-ai/)。

同じものが要るかを考え、要らないと判断しました。理由は3つです。

- その基盤は、Python やターミナルを使わない現場の人が組むためのもの。こちらは Claude Code で組めるので、そこは足りている
- 困っているのは仕組みがないことではなく、印が付いていない回が多いこと。これは画面1枚で片付く
- MASTER の設備と作業の決まりでは、実測された詰まりを解く物だけを足す。詰まりは「108回に成否がない」とはっきりしている

ただ、画面の作りから1つ取り入れたい考えがありました。記録を独立した部品にして、映像と状態を同じ時計でそろえていたことです。こちらの弱いところ（爪の印が2秒早い・角度が1.6秒抜ける）は、どちらも時刻のそろえ方から来ています。

作る画面は、1回ずつ録画と関節のグラフと AI の判定を並べ、人がキーで成功・失敗を付けるものにしました。AI が先に判定を付け、人が確かめて直す形です。動画で言っていた「人の判断と AI でブレを確かめる」に当たります。判定の置き場所は新しいファイルなので、MASTER の保存先テーブルに次の行を足してから実装しました。

```text
| フィジカルAI研究室の推論の記録の成功/失敗の判定（AI の先回り判定と人の確定。追記のみ・元の記録は読むだけ） | `runs/pi05_policy_verdicts_v1.csv` |
```

- ねらい：成否の印がない108回をなくし、だれが付けた印かをデータから分かるようにする
- 変わったこと：判定は新しいファイルに追記だけで残し、1行ごとに `labeler`（記録したときの入力・AI・人・人が AI を直した・決まり）を持つ。元の記録は書き換えない
- 見込める効果：成功率を、学習し直した前と後で同じ数え方で比べられる。測った結果は下の「176回の判定を終えた結果」


## 依頼183：推論の記録に成否を付ける判定の画面を作る

依頼箱は11月14日20:19に始め、20:53に終えました（34分）。AI の先回り判定は、`vlm_judge` と同じ Claude API（claude-sonnet-4-6）で付けています。録画の最後には人がブロックを箱から出している所が写ることがあるので、最後の待ちと HOME へ戻る間のコマは使わないようにしていました。


### 依頼183 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 120
---
# 依頼183：推論の記録に成功/失敗を付ける判定の画面を作る

実機は動かさない（記録を読むだけ）。フィジカルAI研究室のデータ集めや補正の道具として作る。

## なぜ
runs/pi05_policy/ の推論の記録 176 回のうち、成功/失敗の印があるのは 68 回（成功 41・失敗 27）だけ。残り 108 回には印がない（2026-11-14 に数えた）。
- 94 回は {run_stem}.json も recording/ もなく、frames/ と log.jsonl だけ（10 月の記録）
- 3 回は recording/ はあるが {run_stem}.json がない
- 11 回は {run_stem}.json の outcome が null
もうひとつ、今ある判定は誰が付けたか（人か AI か）がデータから分からない。
エイイチの決め（2026-11-14）：大きなプラットフォームは作らず、判定のための画面を 1 枚だけ作る。AI が先に判定を付け、人が確かめて直す。

## 守ること
- 元の記録（runs/pi05_policy/ の中身・台帳・datasets/）は読むだけ。上書き・移動・削除しない
- 判定は新しいファイル 1 本に追記だけで残す（既存の行は書き換えない。同じ run_stem に後から行を足したら、いちばん新しい行が正）
- 書き込むときは ensure_ssd_mounted() 相当のマウント確認を入れる。KIOXIA がなければ止めて報告する（ローカルに逃がさない）
- 画面で alert / confirm などのダイアログは使わない

## 判定の置き場所（保存先テーブルに行を足してから実装する）
/Volumes/KIOXIA/r2r2r-data/runs/pi05_policy_verdicts_v1.csv
列：
| 列 | 中身 |
|---|---|
| labeled_at | 判定した時刻（ISO8601） |
| run_stem | 記録の名前 |
| pick | yes / no / unknown |
| place | yes / no / unknown |
| outcome | success / failure / unknown / not_judgeable（映像が足りず判定できない） |
| labeler | run_input（記録したときの入力を写したもの） / ai / human（AI と同じ判定を人が確かめた） / human_fixed_ai（人が AI と違う判定にした） / human_only（AI の判定なしで人が付けた） |
| ai_outcome | AI の判定（参考。人の行にも写しておく） |
| ai_reason | AI の判定の理由 |
| evidence | 判定に使った素材（top.mp4 / frames / both） |
| note | 人のひとこと（空でよい） |

決まり：AI だけの行（labeler=ai）は「まだ確定していない」扱い。確定は人の行。handover の台帳の outcome_source（VLM 単独で確定しない）と同じ考え方。

## やること
1. 今ある判定の写し：{run_stem}.json に outcome があり null でない 68 回を、labeler=run_input の行として書く（json は書き換えない）
2. AI の先回り判定：印のない 108 回に、AI（今の vlm_judge と同じ Claude API）で成功/失敗を付けて labeler=ai の行を書く。素材は recording/top.mp4 があれば最後のほうのコマ、なければ frames/ の最後の数枚。素材が足りなければ not_judgeable にする。API が使えないときは飛ばして、何回分を飛ばしたか報告に書く
3. 判定の画面（pi05/verdict_viewer/ に置く。Mac で python3 一発で立ち上がり、ブラウザで localhost を開く形）
   - 左に記録の一覧。既定は「人の確定がまだの回」だけ。絞り込みで全部・失敗だけ・AI と人が違う回も見られる
   - 右に 1 回分：top.mp4 の再生（なければ frames/ のコマ送り）、関節 6 本と爪のグラフ（recording/states.csv、なければ log.jsonl の state）、AI の判定と理由、今の確定の判定
   - キーで判定：y 成功 / n 失敗 / u 分からない / x 判定できない、←→ で前後の回。押したらその場で 1 行追記して次の回へ進む
   - pick と place を分けて付けたいときは、画面のボタンで別々に選べるようにする（キーは outcome だけでよい）
4. 確かめ：テスト（追記だけで既存行を変えないこと、マウントがないと止まること、最新行が正になること）。画面を実際に立ち上げ、1 回分の判定が CSV に入るところまで確かめ、画面の写し（png）を報告に添える
5. codex にレビューを頼み、変えたファイルだけを指定して commit（git add . と git clean は使わない）

## 報告に書くこと
- 写した判定の数（success / failure / unknown）と、AI が付けた数（success / failure / unknown / not_judgeable / 飛ばした）
- 画面の起動コマンド（エイイチが打つ 1 行）
- 画面の写し
- 決めてほしいことがあれば
- 最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼183 で Claude Code が返した報告

```text
# 結果：20261114_183_推論の記録に成功と失敗を付ける判定の画面を作る

- 状態：完了
- 始めた時刻：2026-11-14 20:19
- 終わった時刻：2026-11-14 20:53（34分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 6f23d901-7e95-4c8d-ba56-63a99a700e3e`

## Claude Code の報告

やったこと
- 依頼に従い、実装の前に MASTER の保存先テーブルへ判定ファイル `runs/pi05_policy_verdicts_v1.csv` の行を足しました。更新履歴にも 1 行足しています。直す前の写しは `MASTER_old_20261114.md` です。
- `pi05/verdict_viewer/` を新しく作りました。
  - 判定ファイルへは追記だけで書き、同じ回はいちばん新しい行が正です。
  - 書く前に KIOXIA のマウントを確かめ、なければ止めます（ローカルには書きません）。
  - 元の記録・台帳・datasets は読むだけで、その中には書きません。
- 今ある判定の写し（labeler=run_input）と、AI の先回り判定（labeler=ai）を判定ファイルに書きました。
  - AI は vlm_judge と同じ Claude API（claude-sonnet-4-6）を使いました。
  - 素材は、top.mp4 があれば方策が動いていた区間の後ろ寄りの 6 コマ、なければ frames/ の最後を含む 6 枚です。
  - 録画の最後は、人がブロックを箱から出しているところが写っていることがあります。そのため、最後の待ちと HOME へ戻る間のコマは使っていません。
- 画面では次のことができます。
  - 左の一覧の絞り込み（既定は人の確定がまだの回。ほかに全部・失敗だけ・AI と人が違う回）
  - top.mp4 の再生（なければ frames/ のコマ送り）
  - 関節 6 本と爪のグラフ
  - AI の判定と理由、今の判定、その回の行の一覧を見る
  - y/n/u/x で 1 行追記して次の回へ進む、←→ で前後の回へ移る
  - pick と place はボタンで別々に選ぶ
  - ダイアログは使っていません。
- codex のレビューを 7 回受けました。必須の指摘は 1 回目から順に 5・3・1・1・1・0・0 件で、すべて直しました。7 回目は推奨 1 件だけで、それも直しました。
  - 主な直しは、読み込み中に違う回へ書かない、キーの押しっぱなしで続けて書かない、応答が届かずに押し直しても 2 回書かない、書きかけの行がある CSV には足さない、人が確定した回に AI の行を足さない、の 5 つです。
- commit は d595d07 です（5 ファイルを個別に add）。

結果
- 写した判定：68 回（success 41 / failure 27 / unknown 0）
- AI が付けた判定：108 回（success 14 / failure 17 / unknown 0 / not_judgeable 77 / 飛ばした 0）
  - 1 回目は、AI の答えを読めなかった 1 回を飛ばしました。流し直して埋めたので、最後に飛ばした回は 0 です。
  - not_judgeable 77 回の内訳は、素材がなく API を呼ばなかった回が 35 回、AI が判定できないとした回が 42 回です。
- 判定ファイルは 176 行・176 回です。
- テストは 31 件すべて通りました。追記で既存の行が変わらないこと、マウントがないと止まること、最新の行が正になることを確かめています。
- 画面は実際に立ち上げ、ブラウザで y を押して 1 回分の判定が CSV に入るところまで確かめました。
  - 書いた先は /tmp の写しの CSV です。人が付けていない「人の行」を本物のファイルに残さないためです。
  - 入った行は pi05_20261114_182327・success・labeler=human・pick yes / place yes です。
- 画面の起動コマンド：
  `python3 ~/r2r2r-scripts/pi05/verdict_viewer/server.py`
  ブラウザで http://localhost:8765/ が開きます。
- 画面の写し：
  - `claude_code_reports/20261114_183_screen_before.png`（判定する前）
  - `claude_code_reports/20261114_183_screen_after_y.png`（y で追記したあと）

範囲の外で気づいたこと（変えていません）：`~/.anthropic_key` は「export ANTHROPIC_API_KEY=...」の形で書かれています。そのため、環境変数がないときは今の vlm_judge.judge() は鍵を正しく読めず、401 で失敗します。今回のスクリプトはこの形も読めるようにしました。

変えたファイル
- `pi05/verdict_viewer/verdicts.py`・`seed_verdicts.py`・`server.py`・`index.html`・`test_verdicts.py`（新しく作成・commit 済み）
- MASTER.md（保存先テーブルに 1 行と更新履歴に 1 行。直す前の写しは MASTER_old_20261114.md）
- KIOXIA の `runs/pi05_policy_verdicts_v1.csv`（新しく作成・176 行）
- 報告：`claude_code_reports/20261114_183.txt` と画面の写し 2 枚
- 作業メモ：`logs/20261114_2052.md`
- AI のログ：`logs/verdict_seed_ai_20261114.txt`
- 報告・作業メモ・ログと画面の写しは commit していません。

決めてほしいこと
1. 記録したときの入力（run_input）の 68 回を人の確定に数えるか。誰が付けたか分からないので、今は数えていません。そのため既定の一覧には 176 回すべてが出ます。
2. アームを動かしていない回（送ったチャンク 0）が 51 回あります。AI は 44 回を not_judgeable、7 回を failure としました。成功率に入れるか外すか。
3. frames/ だけの回は、最後の画像が最後のチャンクを送る前に撮られています。そのため AI は 42 回を not_judgeable としました。これを人が画面で確かめる形でよいか。
4. 本物の判定ファイルには、まだ人の行がありません。人の判定はエイイチが画面で付けてください。

判定：止めた（決めてほしいことあり）
```

### 依頼183 のコードの差分（コミット d595d07）

```diff
commit d595d07752aa7e4a8fcd6155afa7bb52e21a8e65
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 20:52:50 2026 +0900

    推論の記録に成功/失敗を付ける判定の画面を作る (依頼 183). pi05/verdict_viewer/ を足す. 判定は KIOXIA の runs/pi05_policy_verdicts_v1.csv (MASTER の保存先テーブルに行を足した) に追記だけで残し, 同じ run_stem はいちばん新しい行が正・labeler=ai は未確定. verdicts.py (列・追記・読み. 書く前に KIOXIA のマウントを確かめ, なければ止める. 追記の前に今のファイルを確かめる (改行・見出し・列の数・閉じていない引用符). シンボリックリンク・元の記録と datasets の中には書かない. 記録の外へ出るリンクは読まない), seed_verdicts.py (--run-input で {run_stem}.json の outcome を labeler=run_input として写す. --ai で印のない回を vlm_judge と同じモデルで判定. 素材は top.mp4 の方策が動いていた区間の後ろ寄り 6 コマ, なければ frames/ の最後を含む 6 枚. 2 枚未満は not_judgeable. API が使えない回は飛ばす. 人の行がある回には足さない (ロックの中で確かめる)), server.py + index.html (python3 一発で localhost:8765. 左に一覧 (既定は人の確定がまだの回・全部・失敗だけ・AI と人が違う回), 右に top.mp4 か frames/ のコマ送り・関節 6 本と爪のグラフ・AI の判定と理由・今の判定・この回の行. y/n/u/x で 1 行追記して次へ, ←→ で前後, pick/place はボタン. 読み込み中・押しっぱなしは書かない. 操作ごとの op_id で応答が届かず押し直しても 2 回書かない. ダイアログは使わない). テスト test_verdicts 31 (依頼 183. codex 7 回)
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html       | 329 ++++++++++++++++++++++++++++++
 pi05/verdict_viewer/seed_verdicts.py | 300 +++++++++++++++++++++++++++
 pi05/verdict_viewer/server.py        | 322 +++++++++++++++++++++++++++++
 pi05/verdict_viewer/test_verdicts.py | 378 +++++++++++++++++++++++++++++++++++
 pi05/verdict_viewer/verdicts.py      | 251 +++++++++++++++++++++++
 5 files changed, 1580 insertions(+)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
new file mode 100644
index 0000000..461bab8
--- /dev/null
+++ b/pi05/verdict_viewer/index.html
@@ -0,0 +1,329 @@
+<!doctype html>
+<html lang="ja">
+<head>
+<meta charset="utf-8">
+<title>推論の記録の判定</title>
+<style>
+  :root {
+    --surface-1: #fcfcfb; --surface-2: #f3f2ee; --border: #dddcd5;
+    --text-primary: #1f1f1d; --text-secondary: #55554f; --text-muted: #8a8a82;
+    --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100; --s5: #e87ba4; --s6: #008300;
+    --grip: #55554f;
+    --ok: #006300; --bad: #b42318; --warn: #8a5a00; --accent: #2a78d6;
+  }
+  * { box-sizing: border-box; }
+  body { margin: 0; font: 13px/1.5 -apple-system, "Hiragino Sans", sans-serif; color: var(--text-primary);
+         background: var(--surface-1); height: 100vh; display: flex; }
+  #side { width: 300px; border-right: 1px solid var(--border); display: flex; flex-direction: column; background: var(--surface-2); }
+  #side header { padding: 10px; border-bottom: 1px solid var(--border); }
+  #side h1 { font-size: 14px; margin: 0 0 6px; }
+  #filter { width: 100%; font-size: 13px; padding: 3px; }
+  #count { color: var(--text-secondary); margin-top: 4px; font-size: 12px; }
+  #list { overflow-y: auto; flex: 1; }
+  .item { padding: 5px 10px; border-bottom: 1px solid var(--border); cursor: pointer; display: flex; justify-content: space-between; gap: 6px; }
+  .item:hover { background: #ebeae4; }
+  .item.sel { background: #dbe8f8; }
+  .item .stem { font-family: ui-monospace, Menlo, monospace; font-size: 12px; }
+  .item .sub { color: var(--text-muted); font-size: 11px; }
+  .tag { font-size: 11px; padding: 0 5px; border-radius: 3px; border: 1px solid var(--border); white-space: nowrap; align-self: center; }
+  .tag.success { color: var(--ok); border-color: var(--ok); }
+  .tag.failure { color: var(--bad); border-color: var(--bad); }
+  .tag.unknown, .tag.not_judgeable { color: var(--warn); border-color: var(--warn); }
+  .tag.ai { border-style: dashed; }
+  #main { flex: 1; overflow-y: auto; padding: 12px 16px; }
+  #title { font-family: ui-monospace, Menlo, monospace; font-size: 15px; font-weight: 600; }
+  #meta { color: var(--text-secondary); font-size: 12px; margin-bottom: 8px; }
+  #top { display: flex; gap: 16px; align-items: flex-start; }
+  #media { width: 640px; flex: none; }
+  #media video, #media img { width: 640px; background: #000; display: block; }
+  #framebar { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
+  #framebar input { flex: 1; }
+  #panel { flex: 1; min-width: 300px; }
+  .box { border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; margin-bottom: 10px; background: #fff; }
+  .box h3 { margin: 0 0 4px; font-size: 12px; color: var(--text-secondary); font-weight: 600; }
+  .big { font-size: 16px; font-weight: 600; }
+  .row { display: flex; gap: 6px; align-items: center; margin: 4px 0; flex-wrap: wrap; }
+  .row .lbl { width: 46px; color: var(--text-secondary); }
+  button { font: inherit; padding: 3px 9px; border: 1px solid var(--border); border-radius: 4px; background: #fff; cursor: pointer; }
+  button.on { background: var(--accent); color: #fff; border-color: var(--accent); }
+  button.key { min-width: 110px; }
+  kbd { font: 11px ui-monospace, Menlo, monospace; border: 1px solid var(--border); border-bottom-width: 2px; border-radius: 3px; padding: 0 4px; background: var(--surface-2); }
+  #note { width: 100%; padding: 4px; font: inherit; }
+  #status { min-height: 20px; margin: 4px 0; font-size: 12px; }
+  #status.err { color: var(--bad); font-weight: 600; }
+  #status.ok { color: var(--ok); }
+  #chart { margin-top: 10px; position: relative; }
+  #chart svg text { font-size: 11px; fill: var(--text-secondary); }
+  #legend { display: flex; gap: 12px; flex-wrap: wrap; font-size: 12px; color: var(--text-secondary); margin: 4px 0; }
+  #legend span::before { content: ""; display: inline-block; width: 14px; height: 2px; vertical-align: middle; margin-right: 4px; background: var(--c); }
+  #tip { position: absolute; pointer-events: none; background: #fff; border: 1px solid var(--border); border-radius: 4px;
+         padding: 4px 6px; font-size: 11px; display: none; box-shadow: 0 1px 3px rgba(0,0,0,.12); white-space: nowrap; }
+  #tip i { display: inline-block; width: 10px; height: 2px; vertical-align: middle; margin-right: 4px; }
+  table.hist { border-collapse: collapse; font-size: 11px; width: 100%; }
+  table.hist td, table.hist th { border-bottom: 1px solid var(--border); padding: 2px 4px; text-align: left; vertical-align: top; }
+  .muted { color: var(--text-muted); }
+</style>
+</head>
+<body>
+<div id="side">
+  <header>
+    <h1>推論の記録の判定</h1>
+    <select id="filter">
+      <option value="todo">人の確定がまだの回</option>
+      <option value="all">全部</option>
+      <option value="failure">失敗だけ (今の判定)</option>
+      <option value="diff">AI と人が違う回</option>
+    </select>
+    <div id="count"></div>
+  </header>
+  <div id="list"></div>
+</div>
+<div id="main">
+  <div id="title">—</div>
+  <div id="meta"></div>
+  <div id="top">
+    <div id="media"></div>
+    <div id="panel">
+      <div class="box">
+        <h3>判定する (キー)</h3>
+        <div class="row">
+          <button class="key" data-oc="success"><kbd>y</kbd> 成功</button>
+          <button class="key" data-oc="failure"><kbd>n</kbd> 失敗</button>
+          <button class="key" data-oc="unknown"><kbd>u</kbd> 分からない</button>
+          <button class="key" data-oc="not_judgeable"><kbd>x</kbd> 判定できない</button>
+        </div>
+        <div class="row"><span class="lbl">pick</span>
+          <button data-pp="pick" data-v="yes">yes</button><button data-pp="pick" data-v="no">no</button><button data-pp="pick" data-v="unknown">unknown</button>
+          <span class="muted">選ばなければ 成功→yes / ほか→unknown</span></div>
+        <div class="row"><span class="lbl">place</span>
+          <button data-pp="place" data-v="yes">yes</button><button data-pp="place" data-v="no">no</button><button data-pp="place" data-v="unknown">unknown</button></div>
+        <div class="row"><input id="note" placeholder="ひとこと (空でよい・入力中はキーで判定しない)"></div>
+        <div id="status"></div>
+        <div class="muted"><kbd>←</kbd> <kbd>→</kbd> 前後の回 ・ <kbd>,</kbd> <kbd>.</kbd> コマ送り / 動画は <kbd>space</kbd> で再生</div>
+      </div>
+      <div class="box"><h3>AI の判定 (未確定)</h3><div id="ai"></div></div>
+      <div class="box"><h3>今の判定 (いちばん新しい行)</h3><div id="cur"></div></div>
+      <div class="box"><h3>この回の行 (古い順)</h3><div id="hist"></div></div>
+    </div>
+  </div>
+  <div id="chart"></div>
+</div>
+<script>
+const OC_JA = {success: "成功", failure: "失敗", unknown: "分からない", not_judgeable: "判定できない", "": "なし"};
+const LB_JA = {run_input: "記録時の入力", ai: "AI", human: "人 (AI と同じ)", human_fixed_ai: "人 (AI を直した)", human_only: "人 (AI なし)", "": ""};
+const COLORS = ["--s1", "--s2", "--s3", "--s4", "--s5", "--s6"].map(v => getComputedStyle(document.documentElement).getPropertyValue(v).trim());
+const pendingOps = {};  // run_stem → 書けたか分からない操作 (回ごとに残す. codex 6 回目 R1)
+let selSeq = 0;  // 応答が届かなかった操作. 同じ中身で押し直したら同じ op_id で送る (codex 2 回目 R2)
+let runs = [], view = [], cur = null, detail = null, pp = {pick: null, place: null}, frameIdx = 0, busy = false, loading = false;
+
+const $ = s => document.querySelector(s);
+const esc = s => String(s ?? "").replace(/[&<>"]/g, c => ({"&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;"}[c]));
+function status(msg, kind) { const el = $("#status"); el.textContent = msg; el.className = kind || ""; }
+function tag(oc, ai) { return oc ? `<span class="tag ${oc} ${ai ? "ai" : ""}">${ai ? "AI " : ""}${OC_JA[oc]}</span>` : `<span class="tag">印なし</span>`; }
+
+function applyFilter() {
+  const f = $("#filter").value;
+  view = runs.filter(r => f === "all" ? true : f === "todo" ? !r.confirmed : f === "failure" ? r.outcome === "failure"
+                          : (r.ai_outcome && r.human_outcome && r.ai_outcome !== r.human_outcome));
+  $("#count").textContent = `${view.length} 回 / 全 ${runs.length} 回 (人の確定済み ${runs.filter(r => r.confirmed).length})`;
+  $("#list").innerHTML = view.map(r => `<div class="item ${cur === r.run_stem ? "sel" : ""}" data-stem="${r.run_stem}">
+      <div><div class="stem">${r.run_stem.replace("pi05_", "")}</div>
+      <div class="sub">${r.has_mp4 ? "top.mp4" : r.n_frames ? "frames " + r.n_frames : "素材なし"} ・ ${LB_JA[r.labeler] || "—"}</div></div>
+      ${tag(r.outcome, r.labeler === "ai")}</div>`).join("");
+  document.querySelectorAll(".item").forEach(el => el.onclick = () => select(el.dataset.stem));
+}
+
+async function loadRuns() {
+  const res = await fetch("/api/runs"); const j = await res.json();
+  if (!res.ok || !Array.isArray(j.runs)) throw new Error(j.error || "一覧を読めません");  // 今の一覧は残す (codex 4 回目 R1)
+  runs = j.runs;
+  applyFilter();
+}
+
+async function select(stem) {
+  const seq = ++selSeq;  // いちばん新しい選択の応答だけ使う (codex 5 回目 R2・6 回目 R3)
+  if (!stem) {  // 空の一覧: 前の回の表示と状態を残さない (codex 7 回目 R1)
+    cur = null; detail = null; chartGeom = null; loading = false; pp = {pick: null, place: null}; markPP(); $("#note").value = "";
+    $("#title").textContent = "この絞り込みに残っている回はありません"; $("#meta").textContent = "";
+    $("#media").innerHTML = $("#chart").innerHTML = $("#ai").innerHTML = $("#cur").innerHTML = $("#hist").innerHTML = "";
+    return true;
+  }
+  // 読み込みが終わるまでは判定を受け付けない (前の回を見ながら次の回に書かない. codex R1)
+  cur = stem; detail = null; loading = true; pp = {pick: null, place: null}; frameIdx = 0; $("#note").value = "";
+  const po = pendingOps[stem];
+  if (po) {
+    // 書けたか分からない操作の回に戻ったら, そのときの入力を戻す (同じキーで同じ op_id になる. codex 5 回目 R1)
+    pp = {pick: po.payload.pick, place: po.payload.place}; $("#note").value = po.payload.note;
+  }
+  $("#title").textContent = stem + " (読み込み中)"; $("#media").innerHTML = ""; $("#chart").innerHTML = "";
+  $("#ai").innerHTML = $("#cur").innerHTML = $("#hist").innerHTML = "";
+  applyFilter(); markPP();
+  document.querySelector(`.item[data-stem="${stem}"]`)?.scrollIntoView({block: "nearest"});
+  let d;
+  try { const res = await fetch("/api/run/" + stem); d = await res.json(); if (!res.ok) throw new Error(d.error); }
+  catch (e) { if (seq === selSeq) { $("#title").textContent = stem; status("この回を読めませんでした: " + e.message + " ・ 一覧でもう一度選んでください", "err"); } return false; }
+  if (seq !== selSeq || d.run_stem !== cur) return false;
+  detail = d; loading = false;
+  $("#title").textContent = stem;
+  $("#meta").textContent = `送ったチャンク ${detail.executed_chunks} ・ 終わり方 ${detail.end_reason || "記録なし"} ・ ${detail.model || ""}`;
+  renderMedia(); renderInfo(); renderChart();
+  return true;
+}
+
+function renderMedia() {
+  const m = $("#media");
+  if (detail.has_mp4) {
+    m.innerHTML = `<video id="vid" controls muted preload="metadata" src="/media/${detail.run_stem}/top.mp4"></video><div class="muted">recording/top.mp4</div>`;
+    const v = $("#vid");
+    v.onerror = () => { if (detail.frames.length) { status("top.mp4 を再生できないので frames/ を出します", "err"); detail.has_mp4 = false; renderMedia(); } else status("top.mp4 を再生できません (frames/ もなし)", "err"); };
+    v.ontimeupdate = () => cursor(v.currentTime);
+  } else if (detail.frames.length) {
+    const n = detail.frames.length;
+    m.innerHTML = `<img id="frm"><div id="framebar"><button id="fp">‹</button><input id="fr" type="range" min="0" max="${n - 1}" value="${frameIdx}"><button id="fn">›</button><span id="fl"></span></div><div class="muted">frames/ (各チャンクの前に撮った入力画像)</div>`;
+    $("#fp").onclick = () => stepFrame(-1); $("#fn").onclick = () => stepFrame(1);
+    $("#fr").oninput = e => { frameIdx = +e.target.value; showFrame(); };
+    showFrame();
+  } else {
+    m.innerHTML = `<div class="box">映像がありません (top.mp4 も frames/ もない)</div>`;
+  }
+}
+function showFrame() {
+  const n = detail.frames.length; frameIdx = Math.max(0, Math.min(n - 1, frameIdx));
+  $("#frm").src = `/media/${detail.run_stem}/frames/${detail.frames[frameIdx]}`;
+  $("#fr").value = frameIdx; $("#fl").textContent = `${frameIdx + 1} / ${n}`;
+}
+function stepFrame(d) { if (detail && !detail.has_mp4 && detail.frames.length && $("#frm")) { frameIdx += d; showFrame(); } }
+
+function renderInfo() {
+  const a = detail.ai, l = detail.latest;
+  $("#ai").innerHTML = a ? `<div class="big">${OC_JA[a.outcome]}</div><div>pick ${a.pick} / place ${a.place} ・ 素材 ${a.evidence || "なし"}</div><div class="muted">${esc(a.ai_reason)}</div>` : `<span class="muted">AI の判定はありません</span>`;
+  $("#cur").innerHTML = l ? `<div class="big">${OC_JA[l.outcome]} <span class="muted" style="font-size:12px">${LB_JA[l.labeler]}</span></div><div>pick ${l.pick} / place ${l.place} ・ ${esc(l.labeled_at)}</div>${l.note ? `<div class="muted">${esc(l.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
+  $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>pick/place</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${OC_JA[r.outcome]}</td><td>${r.pick}/${r.place}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
+}
+
+// ---- 関節と爪のグラフ (関節は 1 本の軸・爪は下に別の帯. 2 つの縦軸は使わない) ----
+let chartGeom = null;
+function renderChart() {
+  const s = detail.states, el = $("#chart");
+  if (!s.t.length) { el.innerHTML = `<div class="muted">関節の記録がありません (recording/states.csv も log.jsonl の state もない)</div>`; chartGeom = null; return; }
+  const W = Math.max(700, el.clientWidth || 900), H = 240, GH = 44, L = 44, R = 12, T = 8, gap = 22;
+  const tmax = Math.max(s.t[s.t.length - 1], ...(s.grip.map(g => g[0]))) || 1;
+  let lo = Infinity, hi = -Infinity;
+  s.joints.forEach(js => js.forEach(v => { lo = Math.min(lo, v); hi = Math.max(hi, v); }));
+  const pad = (hi - lo) * 0.06 || 5; lo -= pad; hi += pad;
+  const x = t => L + (W - L - R) * t / tmax, y = v => T + (H - T - 18) * (hi - v) / (hi - lo);
+  const gy0 = H + gap, gy = v => gy0 + GH - 6 - (GH - 12) * Math.max(0, Math.min(1, v));
+  const ticks = []; const step = niceStep((hi - lo) / 5);
+  for (let v = Math.ceil(lo / step) * step; v <= hi; v += step) ticks.push(v);
+  const tstep = niceStep(tmax / 8); const tt = []; for (let v = 0; v <= tmax; v += tstep) tt.push(v);
+  let svg = `<svg width="${W}" height="${gy0 + GH + 20}" id="csvg">`;
+  ticks.forEach(v => svg += `<line x1="${L}" x2="${W - R}" y1="${y(v)}" y2="${y(v)}" stroke="#ecebe6"/><text x="${L - 6}" y="${y(v) + 4}" text-anchor="end">${+v.toFixed(1)}°</text>`);
+  tt.forEach(v => svg += `<text x="${x(v)}" y="${gy0 + GH + 14}" text-anchor="middle">${+v.toFixed(0)}s</text>`);
+  s.stages.forEach(([t, st]) => svg += `<line x1="${x(t)}" x2="${x(t)}" y1="${T}" y2="${gy0 + GH}" stroke="#d6d5ce" stroke-dasharray="2,3"/>`);
+  for (let j = 0; j < 6; j++) {
+    const d = s.t.map((t, i) => `${i ? "L" : "M"}${x(t).toFixed(1)},${y(s.joints[i][j]).toFixed(1)}`).join("");
+    svg += `<path d="${d}" fill="none" stroke="${COLORS[j]}" stroke-width="2" stroke-linejoin="round"/>`;
+  }
+  svg += `<rect x="${L}" y="${gy0}" width="${W - L - R}" height="${GH}" fill="none" stroke="#ecebe6"/>`;
+  svg += `<text x="${L - 6}" y="${gy(1) + 4}" text-anchor="end">閉</text><text x="${L - 6}" y="${gy(0) + 4}" text-anchor="end">開</text>`;
+  if (s.grip.length) {
+    let d = `M${x(0)},${gy(s.grip[0][1])}`, pv = s.grip[0][1];
+    s.grip.forEach(([t, v]) => { d += `L${x(t).toFixed(1)},${gy(pv)}L${x(t).toFixed(1)},${gy(v)}`; pv = v; });
+    d += `L${x(tmax)},${gy(pv)}`;
+    svg += `<path d="${d}" fill="none" stroke="var(--grip)" stroke-width="2"/>`;
+  }
+  svg += `<line id="cx" x1="0" x2="0" y1="${T}" y2="${gy0 + GH}" stroke="#1f1f1d" stroke-width="1" style="display:none"/>`;
+  svg += `<line id="vx" x1="0" x2="0" y1="${T}" y2="${gy0 + GH}" stroke="var(--s1)" stroke-width="1" style="display:none"/>`;
+  svg += `<rect id="hit" x="${L}" y="0" width="${W - L - R}" height="${gy0 + GH}" fill="transparent"/></svg>`;
+  el.innerHTML = `<div id="legend">${COLORS.map((c, j) => `<span style="--c:${c}">j${j}</span>`).join("")}<span style="--c:var(--grip)">爪 (下の帯・${esc(s.grip_label)})</span><span class="muted">${esc(s.source)}</span></div>${svg}<div id="tip"></div>`;
+  chartGeom = {x, tmax, L, W, R};
+  const hit = $("#hit"), tip = $("#tip"), cx = $("#cx");
+  hit.onmousemove = e => {
+    const r = hit.getBoundingClientRect(), t = (e.clientX - r.left) / r.width * tmax;
+    let i = 0; for (let k = 0; k < s.t.length; k++) { if (s.t[k] <= t) i = k; else break; }
+    let g = null; s.grip.forEach(([gt, v]) => { if (gt <= t) g = v; });
+    cx.setAttribute("x1", x(s.t[i])); cx.setAttribute("x2", x(s.t[i])); cx.style.display = "";
+    tip.innerHTML = `<b>${s.t[i].toFixed(1)} 秒</b><br>` + s.joints[i].map((v, j) => `<i style="background:${COLORS[j]}"></i>j${j} ${v.toFixed(1)}°`).join("<br>") + (g === null ? "" : `<br>爪 ${g}`);
+    tip.style.display = "block";
+    const left = e.clientX - el.getBoundingClientRect().left + 14;
+    tip.style.left = Math.min(left, W - 120) + "px"; tip.style.top = "30px";
+  };
+  hit.onmouseleave = () => { tip.style.display = "none"; cx.style.display = "none"; };
+}
+function niceStep(raw) { const p = Math.pow(10, Math.floor(Math.log10(raw || 1))); const n = raw / p; return (n < 1.5 ? 1 : n < 3 ? 2 : n < 7 ? 5 : 10) * p; }
+function cursor(vt) {
+  if (!chartGeom || !detail.video_t || !detail.video_t.length) return;
+  const v = $("#vid"); const n = detail.video_t.length;
+  const i = Math.max(0, Math.min(n - 1, Math.round(vt / (v.duration || 1) * (n - 1))));
+  const xx = chartGeom.x(detail.video_t[i]); const l = $("#vx"); if (!l) return;
+  l.setAttribute("x1", xx); l.setAttribute("x2", xx); l.style.display = "";
+}
+
+function markPP() {
+  document.querySelectorAll("[data-pp]").forEach(b => b.classList.toggle("on", pp[b.dataset.pp] === b.dataset.v));
+}
+document.querySelectorAll("[data-pp]").forEach(b => b.onclick = () => {
+  const k = b.dataset.pp; pp[k] = pp[k] === b.dataset.v ? null : b.dataset.v; markPP(); b.blur();
+});
+document.querySelectorAll("[data-oc]").forEach(b => b.onclick = () => { b.blur(); save(b.dataset.oc); });
+
+async function save(outcome) {
+  if (!cur || busy || loading || !detail || detail.run_stem !== cur) return;
+  busy = true; const stem = cur;
+  const payload = {run_stem: stem, outcome, pick: pp.pick, place: pp.place, note: $("#note").value};
+  const key = JSON.stringify(payload);
+  const prev = pendingOps[stem];
+  const opId = prev && prev.key === key ? prev.opId
+             : stem + ":" + Date.now() + ":" + Math.random().toString(36).slice(2);
+  pendingOps[stem] = {key, opId, payload};
+  const seqAtSave = selSeq;
+  let saved = false;
+  const posBefore = view.findIndex(r => r.run_stem === stem);
+  try {
+    const res = await fetch("/api/verdict", {method: "POST", headers: {"Content-Type": "application/json"},
+      body: JSON.stringify(Object.assign({op_id: opId}, payload))});
+    const j = await res.json();
+    if (!res.ok) { delete pendingOps[stem]; status("書けませんでした: " + j.error, "err"); return; }
+    saved = true;
+    status(`${stem} を「${OC_JA[outcome]}」で追記しました (${LB_JA[j.row.labeler]}・pick ${j.row.pick} / place ${j.row.place})`, "ok");
+    await loadRuns();
+    // 同じ位置 (確定で一覧から消えたらそこに来た次の回) へ進む
+    let next;
+    const still = view.findIndex(r => r.run_stem === stem);
+    if (still >= 0) next = view[still + 1] || view[still];
+    else next = view[Math.min(posBefore, view.length - 1)];
+    // 画面を進め終えてから消す (読み直しや次の回の読み込みに失敗して押し直しても同じ op_id. codex 3 回目 R1・4 回目 R2)
+    if (selSeq !== seqAtSave) { delete pendingOps[stem]; return; }  // 保存中に人が別の回を選んでいたら動かさない (codex 6 回目 R2)
+    if (await select(next ? next.run_stem : null)) delete pendingOps[stem];
+  } catch (e) {
+    if (saved) { status(`${stem} は書けています. 一覧の読み直しに失敗しました: ${e} ・ 押し直しても 2 回は書きません`, "err"); return; }
+    // 書けたのに応答が届かなかったこともある. 同じ回・同じ判定で押し直すと同じ op_id で送るので,
+    // サーバーは 2 回書かない (codex R7. 別の回を判定してから戻っても pendingOps に残る)
+    status("書けたか確かめられませんでした: " + e + " ・ 同じキーで押し直すと 2 回は書きません", "err");
+  }
+  finally { busy = false; }
+}
+
+function move(d) {
+  const i = view.findIndex(r => r.run_stem === cur);
+  const n = view[i < 0 ? 0 : Math.max(0, Math.min(view.length - 1, i + d))];
+  if (n) { status(""); select(n.run_stem); }
+}
+
+document.addEventListener("keydown", e => {
+  if (e.target.tagName === "INPUT" && e.target.type !== "range") { if (e.key === "Escape") e.target.blur(); return; }
+  if (e.metaKey || e.ctrlKey || e.altKey) return;
+  if (e.repeat && "ynux".includes(e.key)) return;  // 押しっぱなしで次の回まで書かない (codex R5)
+  const k = e.key;
+  if (k === "y") save("success"); else if (k === "n") save("failure");
+  else if (k === "u") save("unknown"); else if (k === "x") save("not_judgeable");
+  else if (k === "ArrowRight") { e.preventDefault(); move(1); } else if (k === "ArrowLeft") { e.preventDefault(); move(-1); }
+  else if (k === ".") stepFrame(1); else if (k === ",") stepFrame(-1);
+  else if (k === " " && $("#vid")) { e.preventDefault(); const v = $("#vid"); v.paused ? v.play() : v.pause(); }
+});
+$("#filter").onchange = () => { applyFilter(); if (!view.find(r => r.run_stem === cur)) select(view[0]?.run_stem); };
+window.onresize = () => detail && renderChart();
+loadRuns().then(() => select(view[0]?.run_stem)).catch(e => status("一覧を読めませんでした: " + e.message + " ・ KIOXIA をつないで読み直してください", "err"));
+</script>
+</body>
+</html>
diff --git a/pi05/verdict_viewer/seed_verdicts.py b/pi05/verdict_viewer/seed_verdicts.py
new file mode 100644
index 0000000..9deec01
--- /dev/null
+++ b/pi05/verdict_viewer/seed_verdicts.py
@@ -0,0 +1,300 @@
+#!/usr/bin/env python3
+"""推論の記録の判定ファイルに, 今ある判定の写しと AI の先回り判定を足す (依頼 183).
+
+  python3 pi05/verdict_viewer/seed_verdicts.py --run-input      # {run_stem}.json の outcome を写す (labeler=run_input)
+  python3 pi05/verdict_viewer/seed_verdicts.py --ai             # 印のない回を AI が判定 (labeler=ai)
+  python3 pi05/verdict_viewer/seed_verdicts.py --ai --dry-run   # API を呼ばずに素材だけ数える
+
+- 元の記録は読むだけ. 判定ファイルには追記だけ (verdicts.append_rows)
+- すでに同じ種類の行がある回は足さない (何度流しても同じ行が増えない)
+- AI の素材: recording/top.mp4 があれば, 推論が動いていた区間 (top_frame_log.csv の mode が wait / home
+  でないコマ) の終わりまでから 6 コマ (後ろ寄り). なければ frames/ (各チャンクの入力画像) から最後を含む 6 枚.
+  2 枚に満たなければ API を呼ばずに not_judgeable
+  (終わりの wait / home では人がブロックを箱から出していることがあるので, そこは使わない)
+- API は今の vlm_judge (dynamic_tracking_limits/place/place_modules/vlm_judge.py) と同じモデル・キーの読み方.
+  使えない (キーがない・通信やクレジットのエラー) 回は行を書かずに飛ばし, 最後に数を出す
+"""
+import argparse
+import base64
+import csv
+import json
+import os
+import sys
+import time
+import urllib.error
+import urllib.request
+from collections import Counter
+from pathlib import Path
+
+HERE = Path(__file__).resolve().parent
+sys.path.insert(0, str(HERE))
+sys.path.insert(0, str(HERE.parent.parent / "dynamic_tracking_limits" / "place" / "place_modules"))
+import verdicts as V  # noqa: E402
+import vlm_judge  # noqa: E402
+
+N_IMAGES = 6
+MIN_IMAGES = 2
+MP4_FRACTIONS = (0.3, 0.5, 0.65, 0.8, 0.9, 1.0)
+MP4_WIDTH = 960
+API_TIMEOUT_SEC = 90.0
+API_MAX_TOKENS = 600
+
+PROMPT = """画像は mechArm 270 (ロボットアーム) の作業台を真上から見たもので, 時間の順に並んでいる ({n} 枚・{source}).
+課題は「赤いブロックをつかみ, 白い箱の中に置く」(put the red block in the white box). AI の方策が動かしている.
+{source_note}
+この回について, 次を判定してください.
+- pick: 赤いブロックを爪でつかんで持ち上げられたか (yes / no / unknown)
+- place: 最後に赤いブロックが白い箱の中にあるか (yes / no / unknown)
+- outcome: success (最後に赤いブロックが白い箱の中にある) / failure (箱の中にない・つかめていない・落とした) /
+  unknown (画像はあるが判別できない) / not_judgeable (画像が終わりまで写っておらず判定できない)
+以下の JSON だけで返答してください. 前置きや後置きの説明は一切含めないこと.
+{{"pick": "yes|no|unknown", "place": "yes|no|unknown", "outcome": "success|failure|unknown|not_judgeable", "reason": "日本語で 1〜2 文の短い理由"}}"""
+
+NOTE_MP4 = ("上カメラの録画から, 方策が動いていた区間の後ろ寄りのコマを選んだ. 最後の 1 枚は方策が止まる直前. "
+            "人の手が写ることがある (補正や置き直し).")
+NOTE_FRAMES = ("各画像は方策に渡した入力画像で, チャンク (動きのひとまとまり) を送る前に撮ったもの. "
+               "最後の 1 枚は最後のチャンクを送る前なので, その後の動きは写っていない. "
+               "赤いブロックが写っていない画像があってもよい (爪の中や箱の中にあることがある).")
+
+
+def mp4_active_end(run_dir, n_frames):
+    """top_frame_log.csv で mode が wait / home でない最後のコマ. 読めなければ最後のコマ."""
+    p = V.safe_file(run_dir, "recording", "top_frame_log.csv")
+    last = None
+    try:
+        if p is None:
+            raise FileNotFoundError
+        with open(p, newline="") as f:
+            for r in csv.DictReader(f):
+                if r.get("mode") not in ("wait", "home"):
+                    last = int(r["frame_idx"])
+    except Exception:
+        last = None
+    if last is None:
+        return n_frames - 1
+    return max(0, min(last, n_frames - 1))
+
+
+def mp4_images(run_dir):
+    import cv2
+    cap = cv2.VideoCapture(str(Path(run_dir) / "recording" / "top.mp4"))
+    try:
+        n = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+        if n <= 0:
+            return [], {}
+        end = mp4_active_end(run_dir, n)
+        idxs = sorted(set(int(round(end * fr)) for fr in MP4_FRACTIONS))
+        out = []
+        for i in idxs:
+            cap.set(cv2.CAP_PROP_POS_FRAMES, i)
+            ok, img = cap.read()
+            if not ok or img is None:
+                continue
+            h, w = img.shape[:2]
+            if w > MP4_WIDTH:
+                img = cv2.resize(img, (MP4_WIDTH, int(h * MP4_WIDTH / w)))
+            ok, buf = cv2.imencode(".jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 85])
+            if ok:
+                out.append(buf.tobytes())
+        return out, {"mp4_frames": n, "active_end": end, "picked": idxs}
+    finally:
+        cap.release()
+
+
+def frames_images(run_dir):
+    names = V.frame_files(run_dir)
+    if not names:
+        return [], {}
+    if len(names) <= N_IMAGES:
+        pick = names
+    else:
+        step = (len(names) - 1) / (N_IMAGES - 1)
+        pick = [names[int(round(i * step))] for i in range(N_IMAGES)]
+    out = [(Path(run_dir) / "frames" / nm).read_bytes() for nm in pick]
+    return out, {"frames": len(names), "picked": pick}
+
+
+def material(run_dir):
+    """(evidence, 画像の bytes のリスト, メモ). 素材が足りなければ evidence='' で画像は空."""
+    if V.has_top_mp4(run_dir):
+        imgs, info = mp4_images(run_dir)
+        if len(imgs) >= MIN_IMAGES:
+            return "top.mp4", imgs, info
+    imgs, info = frames_images(run_dir)
+    if len(imgs) >= MIN_IMAGES:
+        return "frames", imgs, info
+    return "", [], info
+
+
+def api_key():
+    k = os.environ.get("ANTHROPIC_API_KEY")
+    if not k:
+        p = os.path.expanduser("~/.anthropic_key")
+        if os.path.isfile(p):
+            k = open(p).read().strip()
+            # 「export ANTHROPIC_API_KEY=...」の形で置かれていることがある (2026-11-14 に確かめた)
+            if k.startswith("export "):
+                k = k[len("export "):].strip()
+            if k.startswith("ANTHROPIC_API_KEY="):
+                k = k[len("ANTHROPIC_API_KEY="):].strip()
+            k = k.strip("'\"")
+    return k or None
+
+
+class ApiUnavailable(RuntimeError):
+    pass
+
+
+def call_api(key, imgs, evidence):
+    source = "上カメラの録画 top.mp4 のコマ" if evidence == "top.mp4" else "frames/ の入力画像"
+    note = NOTE_MP4 if evidence == "top.mp4" else NOTE_FRAMES
+    content = [{"type": "image", "source": {"type": "base64", "media_type": "image/jpeg",
+                                            "data": base64.b64encode(b).decode("ascii")}} for b in imgs]
+    content.append({"type": "text", "text": PROMPT.format(n=len(imgs), source=source, source_note=note)})
+    payload = {"model": vlm_judge.VLM_MODEL, "max_tokens": API_MAX_TOKENS,
+               "messages": [{"role": "user", "content": content}]}
+    req = urllib.request.Request(vlm_judge.VLM_API_URL, data=json.dumps(payload).encode("utf-8"),
+                                 headers={"x-api-key": key, "anthropic-version": vlm_judge.VLM_ANTHROPIC_VERSION,
+                                          "content-type": "application/json"}, method="POST")
+    last_err = ""
+    for attempt in range(3):
+        try:
+            with urllib.request.urlopen(req, timeout=API_TIMEOUT_SEC) as resp:
+                body = json.loads(resp.read().decode("utf-8"))
+            text = "".join(c.get("text", "") for c in body.get("content", []) if c.get("type") == "text")
+            return vlm_judge._parse_json_from_text(text), text
+        except urllib.error.HTTPError as e:
+            last_err = f"http_{e.code}"
+            if e.code in (429, 500, 502, 503, 504, 529):
+                time.sleep(5 * (attempt + 1))
+                continue
+            raise ApiUnavailable(last_err)
+        except Exception as e:
+            last_err = type(e).__name__
+            time.sleep(3)
+    raise ApiUnavailable(last_err)
+
+
+def ai_row(run_stem, parsed, evidence, n_exec):
+    def pv(v):
+        return v if v in V.PICK_PLACE else "unknown"
+    oc = parsed.get("outcome") if isinstance(parsed, dict) else None
+    oc = oc if oc in V.OUTCOMES else "unknown"
+    reason = str(parsed.get("reason", "")).replace("\n", " ").strip() if isinstance(parsed, dict) else ""
+    return {"labeled_at": V.now_iso(), "run_stem": run_stem,
+            "pick": pv(parsed.get("pick")), "place": pv(parsed.get("place")), "outcome": oc, "labeler": "ai",
+            "ai_outcome": oc, "ai_reason": f"[送ったチャンク {n_exec}] {reason}", "evidence": evidence, "note": ""}
+
+
+def do_run_input(csv_path, runs_dir, dry_run):
+    have = V.latest_by_stem(V.read_rows(csv_path), labelers=("run_input",) + V.HUMAN_LABELERS)
+    rows = []
+    for stem in V.list_run_stems(runs_dir):
+        if stem in have:
+            continue
+        r = V.run_input_row(stem, V.read_run_json(Path(runs_dir) / stem))
+        if r:
+            rows.append(r)
+    c = Counter(r["outcome"] for r in rows)
+    print(f"[COPY ] 写す行 {len(rows)} (success {c['success']} / failure {c['failure']} / unknown {c['unknown']})"
+          + (" ※ dry-run なので書いていません" if dry_run else ""))
+    if not dry_run:
+        written = V.append_rows(rows, csv_path, skip_if_labeled_by=("run_input",) + V.HUMAN_LABELERS,
+                                 forbid_dirs=(runs_dir,))
+        if len(written) != len(rows):
+            print(f"[COPY ] 書くまでの間に人か写しの行が足されていた {len(rows) - len(written)} 回は足さなかった")
+    return c
+
+
+def do_ai(csv_path, runs_dir, dry_run, limit, only):
+    rows = V.read_rows(csv_path)
+    marked = set(V.latest_by_stem(rows, labelers=("run_input",)))
+    have_ai = set(V.latest_by_stem(rows, labelers=("ai",)))
+    human = set(V.latest_by_stem(rows, labelers=V.HUMAN_LABELERS))  # 人が確定した回には AI の行を足さない (codex R2)
+    targets = []
+    for stem in V.list_run_stems(runs_dir):
+        j = V.read_run_json(Path(runs_dir) / stem)
+        if j and j.get("outcome") not in (None, ""):
+            continue  # 印がある回は写しの対象
+        if stem in marked or stem in have_ai or stem in human:
+            continue
+        if only and stem not in only:
+            continue
+        targets.append(stem)
+    if limit:
+        targets = targets[:limit]
+    key = None if dry_run else api_key()
+    counts = Counter()
+    print(f"[AI   ] 対象 {len(targets)} 回 (モデル {vlm_judge.VLM_MODEL})")
+    for i, stem in enumerate(targets, 1):
+        rd = Path(runs_dir) / stem
+        n_exec = V.executed_chunks(V.read_log(rd))
+        evidence, imgs, info = material(rd)
+        if not imgs:
+            row = {"labeled_at": V.now_iso(), "run_stem": stem, "pick": "unknown", "place": "unknown",
+                   "outcome": "not_judgeable", "labeler": "ai", "ai_outcome": "not_judgeable",
+                   "ai_reason": f"[送ったチャンク {n_exec}] 素材が足りない (top.mp4 なし・frames/ {len(V.frame_files(rd))} 枚). API は呼んでいない",
+                   "evidence": "", "note": ""}
+        elif dry_run:
+            print(f"  {i:3d} {stem} {evidence} {len(imgs)} 枚 送ったチャンク {n_exec}")
+            counts["dry_run"] += 1
+            continue
+        elif not key:
+            counts["skipped"] += 1
+            print(f"  {i:3d} {stem} 飛ばした (API キーがない)")
+            continue
+        else:
+            try:
+                parsed, text = call_api(key, imgs, evidence)
+            except ApiUnavailable as e:
+                counts["skipped"] += 1
+                print(f"  {i:3d} {stem} 飛ばした (API: {e})")
+                continue
+            if not isinstance(parsed, dict):
+                counts["skipped"] += 1
+                print(f"  {i:3d} {stem} 飛ばした (答えを読めない: {text[:80]!r})")
+                continue
+            row = ai_row(stem, parsed, evidence, n_exec)
+        if dry_run:
+            print(f"  {i:3d} {stem} not_judgeable (素材なし) 送ったチャンク {n_exec}")
+            counts["not_judgeable"] += 1
+            continue
+        # 1 回ずつ書く (途中で止まっても済んだ回は残る). API を待つ間に人が確定していたら足さない
+        if not V.append_rows([row], csv_path, skip_if_labeled_by=("ai", "run_input") + V.HUMAN_LABELERS,
+                            forbid_dirs=(runs_dir,)):
+            counts["skipped_human"] += 1
+            print(f"  {i:3d} {stem} 足さなかった (待つ間に人か写しの行が足されていた)")
+            continue
+        counts[row["outcome"]] += 1
+        print(f"  {i:3d} {stem} {row['outcome']:13s} pick={row['pick']} place={row['place']} {evidence or '-'}  {row['ai_reason'][:70]}")
+    print("[AI   ] " + " / ".join(f"{k} {counts[k]}" for k in
+                                  ("success", "failure", "unknown", "not_judgeable", "skipped", "skipped_human", "dry_run") if counts[k] or k not in ("dry_run", "skipped_human")))
+    return counts
+
+
+def main():
+    ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
+    ap.add_argument("--run-input", action="store_true", help="{run_stem}.json の outcome を写す")
+    ap.add_argument("--ai", action="store_true", help="印のない回を AI が判定する")
+    ap.add_argument("--dry-run", action="store_true", help="書かない・API を呼ばない")
+    ap.add_argument("--limit", type=int, default=0, help="AI の対象を先頭から N 回まで")
+    ap.add_argument("--stems", nargs="*", default=None, help="AI の対象をこの run_stem だけにする")
+    ap.add_argument("--runs-dir", default=str(V.RUNS_DIR))
+    a = ap.parse_args()
+    if not (a.run_input or a.ai):
+        ap.error("--run-input か --ai を付けてください")
+    try:
+        csv_path = V.VERDICTS_CSV  # 書き先は保存先テーブルの 1 か所だけ (codex R3. テストは関数に渡す)
+        V.ensure_ssd_mounted(csv_path)
+        if a.run_input:
+            do_run_input(csv_path, a.runs_dir, a.dry_run)
+        if a.ai:
+            do_ai(csv_path, a.runs_dir, a.dry_run, a.limit, set(a.stems) if a.stems else None)
+    except (V.NotMounted, V.BrokenCsv) as e:
+        print(f"[ABORT] {e}")
+        return 2
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/pi05/verdict_viewer/server.py b/pi05/verdict_viewer/server.py
new file mode 100644
index 0000000..7e67f1e
--- /dev/null
+++ b/pi05/verdict_viewer/server.py
@@ -0,0 +1,322 @@
+#!/usr/bin/env python3
+"""推論の記録に成功/失敗を付ける判定の画面 (依頼 183).
+
+  python3 pi05/verdict_viewer/server.py            # http://localhost:8765/ をブラウザで開く
+  python3 pi05/verdict_viewer/server.py --no-open  # ブラウザを開かない
+
+- 元の記録 (runs/pi05_policy/) は読むだけ. 判定は pi05_policy_verdicts_v1.csv に 1 行ずつ追記するだけ
+- 書く前に KIOXIA のマウントを確かめ, なければ書かずに画面へエラーを返す
+- localhost だけで待ち受ける
+"""
+import argparse
+import csv
+import json
+import mimetypes
+import re
+import sys
+import threading
+import webbrowser
+from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
+from pathlib import Path
+from urllib.parse import unquote, urlparse
+
+HERE = Path(__file__).resolve().parent
+sys.path.insert(0, str(HERE))
+import verdicts as V  # noqa: E402
+
+STEM_RE = re.compile(r"^pi05_[0-9_]+$")
+FRAME_RE = re.compile(r"^[0-9A-Za-z_]+\.jpg$")
+MAX_STATE_POINTS = 1500
+
+
+def state_series(run_dir):
+    """関節 6 本と爪の時系列. recording/states.csv があればそれ, なければ log.jsonl の state."""
+    rd = Path(run_dir)
+    p = V.safe_file(rd, "recording", "states.csv")
+    t, joints, grip = [], [], []
+    stages = []
+    if p is not None:
+        t0 = None
+        with open(p, newline="") as f:
+            for r in csv.DictReader(f):
+                try:
+                    ts = float(r["ts"])
+                except (TypeError, ValueError):
+                    continue
+                t0 = ts if t0 is None else t0
+                ev = r.get("event_type")
+                if ev == "actual":
+                    try:
+                        joints.append([float(r[f"j{i}"]) for i in range(6)])
+                    except (TypeError, ValueError):
+                        continue
+                    t.append(round(ts - t0, 3))
+                elif ev == "gripper_cmd" and r.get("gripper_state") not in (None, ""):
+                    try:
+                        grip.append([round(ts - t0, 3), float(r["gripper_state"])])
+                    except ValueError:
+                        pass
+                elif ev == "stage":
+                    stages.append([round(ts - t0, 3), r.get("stage", "")])
+        if len(t) > MAX_STATE_POINTS:
+            k = len(t) / MAX_STATE_POINTS
+            idx = sorted(set(int(i * k) for i in range(MAX_STATE_POINTS)) | {len(t) - 1})
+            t = [t[i] for i in idx]
+            joints = [joints[i] for i in idx]
+        return {"source": "recording/states.csv", "t": t, "joints": joints, "grip": grip,
+                "grip_label": "爪の命令 (0 開 / 1 閉)", "stages": stages, "t0": t0}
+    t0 = None
+    for x in V.read_log(rd):
+        if "chunk" not in x or "state" not in x:
+            continue
+        try:
+            st = json.loads(x["state"]) if isinstance(x["state"], str) else x["state"]
+            ts = float(x["t"])
+        except Exception:
+            continue
+        if not isinstance(st, list) or len(st) < 6:
+            continue
+        t0 = ts if t0 is None else t0
+        t.append(round(ts - t0, 3))
+        joints.append([float(v) for v in st[:6]])
+        if len(st) >= 7:
+            grip.append([round(ts - t0, 3), float(st[6])])
+    return {"source": "log.jsonl の state (推論の前に読んだ値)", "t": t, "joints": joints, "grip": grip,
+            "grip_label": "state の爪 (7 番目の値)", "stages": [], "t0": t0}
+
+
+def video_times(run_dir, t0):
+    """top.mp4 の各コマの時刻 (states の始まりからの秒). 再生位置のしるしに使う."""
+    p = V.safe_file(run_dir, "recording", "top_frame_log.csv")
+    if t0 is None or p is None:
+        return None
+    out = []
+    try:
+        with open(p, newline="") as f:
+            for r in csv.DictReader(f):
+                out.append(round(float(r["capture_ts"]) - t0, 3))
+    except Exception:
+        return None
+    return out
+
+
+class App:
+    def __init__(self, runs_dir, csv_path):
+        self.runs_dir = Path(runs_dir)
+        self.csv_path = Path(csv_path)
+        self.lock = threading.Lock()
+        self.done_ops = {}  # 画面の 1 回の操作 (op_id) → 書いた行. 応答が届かず押し直しても 2 回書かない (codex R7)
+
+    def runs_summary(self):
+        rows = V.read_rows(self.csv_path)
+        latest = V.latest_by_stem(rows)
+        ai = V.latest_by_stem(rows, labelers=("ai",))
+        human = V.latest_by_stem(rows, labelers=V.HUMAN_LABELERS)
+        out = []
+        for stem in V.list_run_stems(self.runs_dir):
+            rd = self.runs_dir / stem
+            lt, a, h = latest.get(stem), ai.get(stem), human.get(stem)
+            out.append({
+                "run_stem": stem,
+                "has_mp4": V.has_top_mp4(rd),
+                "n_frames": len(V.frame_files(rd)),
+                "outcome": lt["outcome"] if lt else "",
+                "labeler": lt["labeler"] if lt else "",
+                "ai_outcome": a["outcome"] if a else "",
+                "human_outcome": h["outcome"] if h else "",
+                "confirmed": bool(lt and lt["labeler"] in V.HUMAN_LABELERS),
+            })
+        return out
+
+    def run_detail(self, stem):
+        rd = self.runs_dir / stem
+        rows = [r for r in V.read_rows(self.csv_path) if r["run_stem"] == stem]
+        ai = [r for r in rows if r["labeler"] == "ai"]
+        j = V.read_run_json(rd)
+        log = V.read_log(rd)
+        st = state_series(rd)
+        return {
+            "run_stem": stem,
+            "has_mp4": V.has_top_mp4(rd),
+            "frames": V.frame_files(rd),
+            "states": st,
+            "video_t": video_times(rd, st.get("t0")) if V.has_top_mp4(rd) else None,
+            "ai": ai[-1] if ai else None,
+            "latest": rows[-1] if rows else None,
+            "history": rows,
+            "executed_chunks": V.executed_chunks(log),
+            "end_reason": (j or {}).get("end_reason", ""),
+            "model": next((x.get("model") for x in log if x.get("type") == "model"), "")
+                     or ((j or {}).get("args") or {}).get("model", ""),
+        }
+
+    def add_verdict(self, body):
+        stem = body.get("run_stem", "")
+        if (not STEM_RE.match(stem) or not (self.runs_dir / stem).is_dir()
+                or not V.within(self.runs_dir, self.runs_dir / stem)):
+            raise ValueError(f"run_stem がありません: {stem!r}")
+        outcome = body.get("outcome")
+        if outcome not in V.OUTCOMES:
+            raise ValueError(f"outcome が正しくありません: {outcome!r}")
+        rd = self.runs_dir / stem
+        op_id = str(body.get("op_id") or "")
+        with self.lock:
+            if op_id and op_id in self.done_ops:
+                print(f"[SAVE ] {stem} 同じ操作の送り直し. 書いていない (op_id {op_id})")
+                return self.done_ops[op_id]
+            ai = V.latest_by_stem(V.read_rows(self.csv_path), labelers=("ai",)).get(stem)
+            default = "yes" if outcome == "success" else "unknown"
+            pick = body.get("pick") or default
+            place = body.get("place") or default
+            row = {"labeled_at": V.now_iso(), "run_stem": stem, "pick": pick, "place": place,
+                   "outcome": outcome, "labeler": V.human_labeler_for(outcome, ai),
+                   "ai_outcome": ai["outcome"] if ai else "", "ai_reason": ai["ai_reason"] if ai else "",
+                   "evidence": "top.mp4" if V.has_top_mp4(rd) else ("frames" if V.frame_files(rd) else ""),
+                   "note": str(body.get("note", "")).replace("\n", " ").strip()}
+            written = V.append_rows([row], self.csv_path, forbid_dirs=(self.runs_dir,))[0]
+            if op_id:
+                self.done_ops[op_id] = written
+            print(f"[SAVE ] {written['run_stem']} {written['outcome']} pick={written['pick']} "
+                  f"place={written['place']} labeler={written['labeler']}")
+            return written
+
+
+def make_handler(app):
+    class H(BaseHTTPRequestHandler):
+        def log_message(self, fmt, *args):
+            pass
+
+        def _send(self, code, data, ctype="application/json; charset=utf-8", extra=None):
+            if not isinstance(data, (bytes, bytearray)):
+                data = json.dumps(data, ensure_ascii=False).encode("utf-8")
+            self.send_response(code)
+            self.send_header("Content-Type", ctype)
+            self.send_header("Content-Length", str(len(data)))
+            self.send_header("Cache-Control", "no-store")
+            for k, v in (extra or {}).items():
+                self.send_header(k, v)
+            self.end_headers()
+            if self.command != "HEAD":
+                self.wfile.write(data)
+
+        def _file(self, stem, *rel):
+            # リンクでその回の記録の外へ出ない (codex R6・3 回目 R2)
+            path = V.safe_file(app.runs_dir / stem, *rel) if V.within(app.runs_dir, app.runs_dir / stem) else None
+            if path is None:
+                return self._send(404, {"error": "not found"})
+            size = path.stat().st_size
+            ctype = mimetypes.guess_type(str(path))[0] or "application/octet-stream"
+            rng = self.headers.get("Range")
+            start, end = 0, size - 1
+            if rng:
+                m = re.match(r"bytes=(\d*)-(\d*)", rng)
+                if m:
+                    if m.group(1):
+                        start = int(m.group(1))
+                        if m.group(2):
+                            end = min(int(m.group(2)), size - 1)
+                    elif m.group(2):
+                        start = max(0, size - int(m.group(2)))
+                if start > end or start >= size:
+                    self.send_response(416)
+                    self.send_header("Content-Range", f"bytes */{size}")
+                    self.end_headers()
+                    return
+            length = end - start + 1
+            self.send_response(206 if rng else 200)
+            self.send_header("Content-Type", ctype)
+            self.send_header("Accept-Ranges", "bytes")
+            self.send_header("Content-Length", str(length))
+            if rng:
+                self.send_header("Content-Range", f"bytes {start}-{end}/{size}")
+            self.end_headers()
+            if self.command == "HEAD":
+                return
+            with open(path, "rb") as f:
+                f.seek(start)
+                left = length
+                while left > 0:
+                    chunk = f.read(min(1 << 20, left))
+                    if not chunk:
+                        break
+                    try:
+                        self.wfile.write(chunk)
+                    except (BrokenPipeError, ConnectionResetError):
+                        return
+                    left -= len(chunk)
+
+        def do_HEAD(self):
+            self.do_GET()
+
+        def do_GET(self):
+            u = urlparse(self.path)
+            parts = [unquote(p) for p in u.path.split("/") if p]
+            try:
+                if not parts:
+                    return self._send(200, (HERE / "index.html").read_bytes(), "text/html; charset=utf-8")
+                if parts == ["api", "runs"]:
+                    return self._send(200, {"runs": app.runs_summary(), "csv": str(app.csv_path)})
+                if (len(parts) == 3 and parts[:2] == ["api", "run"] and STEM_RE.match(parts[2])
+                        and (app.runs_dir / parts[2]).is_dir() and V.within(app.runs_dir, app.runs_dir / parts[2])):
+                    return self._send(200, app.run_detail(parts[2]))
+                if len(parts) == 3 and parts[0] == "media" and STEM_RE.match(parts[1]) and parts[2] == "top.mp4":
+                    return self._file(parts[1], "recording", "top.mp4")
+                if (len(parts) == 4 and parts[0] == "media" and STEM_RE.match(parts[1]) and parts[2] == "frames"
+                        and FRAME_RE.match(parts[3])):
+                    return self._file(parts[1], "frames", parts[3])
+                return self._send(404, {"error": "not found"})
+            except Exception as e:  # 画面に理由を返す
+                return self._send(500, {"error": f"{type(e).__name__}: {e}"})
+
+        def do_POST(self):
+            if urlparse(self.path).path != "/api/verdict":
+                return self._send(404, {"error": "not found"})
+            try:
+                n = int(self.headers.get("Content-Length") or 0)
+                body = json.loads(self.rfile.read(n).decode("utf-8") or "{}")
+                row = app.add_verdict(body)
+                return self._send(200, {"ok": True, "row": row})
+            except (V.NotMounted, V.BrokenCsv) as e:
+                print(f"[ABORT] {e}")
+                return self._send(503, {"error": str(e)})
+            except ValueError as e:
+                return self._send(400, {"error": str(e)})
+            except Exception as e:
+                return self._send(500, {"error": f"{type(e).__name__}: {e}"})
+    return H
+
+
+def main():
+    ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
+    ap.add_argument("--port", type=int, default=8765)
+    ap.add_argument("--no-open", action="store_true", help="ブラウザを開かない")
+    ap.add_argument("--runs-dir", default=str(V.RUNS_DIR))
+    ap.add_argument("--test-csv", default=None,
+                    help="画面の確かめ用. 判定を保存先テーブルの CSV でなくこのファイルに書く (ふだんは付けない)")
+    a = ap.parse_args()
+    if not Path(a.runs_dir).is_dir():
+        print(f"[ABORT] 記録のフォルダがありません ({a.runs_dir}). KIOXIA をつないでください")
+        return 2
+    csv_path = Path(a.test_csv) if a.test_csv else V.VERDICTS_CSV
+    if a.test_csv and V.within(a.runs_dir, csv_path):
+        print(f"[ABORT] --test-csv が記録のフォルダの中です ({csv_path}). 元の記録には書きません")
+        return 2
+    if a.test_csv:
+        print(f"[TEST ] 確かめ用: 判定は {csv_path} に書きます (保存先テーブルの CSV には書きません)")
+    app = App(a.runs_dir, csv_path)
+    srv = ThreadingHTTPServer(("127.0.0.1", a.port), make_handler(app))
+    url = f"http://localhost:{a.port}/"
+    print(f"[VIEW ] {url}  (判定は {csv_path} に追記. Ctrl-C で終わる)")
+    if not a.no_open:
+        threading.Timer(0.5, lambda: webbrowser.open(url)).start()
+    try:
+        srv.serve_forever()
+    except KeyboardInterrupt:
+        pass
+    finally:
+        srv.server_close()
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/pi05/verdict_viewer/test_verdicts.py b/pi05/verdict_viewer/test_verdicts.py
new file mode 100644
index 0000000..07519a9
--- /dev/null
+++ b/pi05/verdict_viewer/test_verdicts.py
@@ -0,0 +1,378 @@
+#!/usr/bin/env python3
+"""判定ファイルと判定の画面のテスト (依頼 183). KIOXIA にも API にも触らない (一時フォルダだけ).
+
+  python3 pi05/verdict_viewer/test_verdicts.py
+"""
+import json
+import os
+import sys
+import tempfile
+import threading
+import unittest
+import urllib.error
+import urllib.request
+from pathlib import Path
+from unittest import mock
+
+HERE = Path(__file__).resolve().parent
+sys.path.insert(0, str(HERE))
+import verdicts as V  # noqa: E402
+import seed_verdicts as S  # noqa: E402
+import server  # noqa: E402
+
+
+def row(stem, outcome, labeler, **kw):
+    r = {"run_stem": stem, "pick": "unknown", "place": "unknown", "outcome": outcome, "labeler": labeler}
+    r.update(kw)
+    return r
+
+
+def make_runs(root):
+    """偽の記録: a = json に success, b = json の outcome null, c = frames と log.jsonl だけ, d = 何もない."""
+    root = Path(root)
+    for stem in ("pi05_20261001_000001", "pi05_20261001_000002", "pi05_20261001_000003", "pi05_20261001_000004"):
+        (root / stem).mkdir(parents=True)
+    a = root / "pi05_20261001_000001"
+    (a / f"{a.name}.json").write_text(json.dumps({"outcome": "success", "ended_at": "2026-10-01T00:00:10",
+        "judgments": {"pick": {"verdict": "yes"}, "place": {"verdict": "yes"}}}))
+    b = root / "pi05_20261001_000002"
+    (b / f"{b.name}.json").write_text(json.dumps({"outcome": None}))
+    c = root / "pi05_20261001_000003"
+    (c / "frames").mkdir()
+    for i in range(3):
+        (c / "frames" / f"{i:04d}.jpg").write_bytes(b"\xff\xd8\xff\xd9")
+    (c / "frames" / "._0000.jpg").write_bytes(b"x")
+    (c / "log.jsonl").write_text("\n".join(json.dumps({"chunk": str(i), "t": str(100 + i), "executed": "True",
+        "state": json.dumps([i, 1, 2, 3, 4, -30, 0 if i < 2 else 1])}) for i in range(3)) + "\n")
+    return root
+
+
+class TestAppend(unittest.TestCase):
+    def setUp(self):
+        self.tmp = tempfile.TemporaryDirectory()
+        self.csv = Path(self.tmp.name) / "v.csv"
+
+    def tearDown(self):
+        self.tmp.cleanup()
+
+    def test_append_only_keeps_existing_bytes(self):
+        V.append_rows([row("pi05_1", "success", "run_input"), row("pi05_2", "failure", "ai")], self.csv)
+        before = self.csv.read_bytes()
+        V.append_rows([row("pi05_1", "failure", "human_only")], self.csv)
+        after = self.csv.read_bytes()
+        self.assertTrue(after.startswith(before), "既存の行が変わった")
+        self.assertEqual(after.count(b"labeled_at,"), 1, "見出しが 2 回書かれた")
+        self.assertEqual(len(V.read_rows(self.csv)), 3)
+
+    def test_header_columns(self):
+        V.append_rows([row("pi05_1", "success", "ai")], self.csv)
+        self.assertEqual(self.csv.read_text().splitlines()[0].split(","), V.COLUMNS)
+
+    def test_latest_row_wins(self):
+        V.append_rows([row("pi05_1", "success", "ai"), row("pi05_2", "failure", "ai")], self.csv)
+        V.append_rows([row("pi05_1", "failure", "human_fixed_ai")], self.csv)
+        V.append_rows([row("pi05_1", "unknown", "human_only")], self.csv)
+        lat = V.latest_by_stem(V.read_rows(self.csv))
+        self.assertEqual(lat["pi05_1"]["outcome"], "unknown")
+        self.assertEqual(lat["pi05_2"]["outcome"], "failure")
+        self.assertEqual(V.latest_by_stem(V.read_rows(self.csv), labelers=("ai",))["pi05_1"]["outcome"], "success")
+
+    def test_bad_values_write_nothing(self):
+        V.append_rows([row("pi05_1", "success", "ai")], self.csv)
+        before = self.csv.read_bytes()
+        for bad in (row("pi05_1", "great", "ai"), row("pi05_1", "success", "robot"),
+                    row("", "success", "ai"), row("pi05_1", "success", "ai", pick="maybe")):
+            with self.assertRaises(ValueError):
+                V.append_rows([row("pi05_9", "success", "ai"), bad], self.csv)
+        self.assertEqual(self.csv.read_bytes(), before, "まちがった行のときに途中まで書いた")
+
+    def test_comma_and_newline_in_reason(self):
+        V.append_rows([row("pi05_1", "failure", "ai", ai_reason='箱の外, "落とした"\n2 行目')], self.csv)
+        self.assertEqual(V.read_rows(self.csv)[0]["ai_reason"], '箱の外, "落とした"\n2 行目')
+
+    def test_broken_file_stops(self):
+        V.append_rows([row("pi05_1", "success", "ai")], self.csv)
+        with open(self.csv, "ab") as f:
+            f.write(b"2026,pi05_2,yes")  # 書きかけ (改行なし)
+        before = self.csv.read_bytes()
+        with self.assertRaises(V.BrokenCsv):
+            V.append_rows([row("pi05_3", "success", "ai")], self.csv)
+        self.assertEqual(self.csv.read_bytes(), before)
+        other = Path(self.tmp.name) / "other.csv"
+        other.write_text("a,b\n1,2\n")
+        with self.assertRaises(V.BrokenCsv):
+            V.append_rows([row("pi05_3", "success", "ai")], other)
+        self.assertEqual(other.read_text(), "a,b\n1,2\n")
+
+    def test_unclosed_quote_stops(self):
+        V.append_rows([row("pi05_1", "success", "ai")], self.csv)
+        with open(self.csv, "ab") as f:
+            f.write(b'2026,pi05_2,yes,yes,success,ai,,,,"unfinished\n')
+        before = self.csv.read_bytes()
+        with self.assertRaises(V.BrokenCsv):
+            V.append_rows([row("pi05_3", "success", "ai")], self.csv)
+        self.assertEqual(self.csv.read_bytes(), before)
+
+    def test_long_note_is_cut(self):
+        V.append_rows([row("pi05_1", "success", "human_only", note="あ" * 200000, ai_reason="い" * 200000)], self.csv)
+        r = V.read_rows(self.csv)[0]
+        self.assertEqual(len(r["note"]), V.MAX_NOTE + 1)
+        self.assertEqual(len(r["ai_reason"]), V.MAX_REASON + 1)
+        V.append_rows([row("pi05_2", "success", "ai")], self.csv)
+
+    def test_forbid_dirs(self):
+        d = Path(self.tmp.name) / "myruns"
+        d.mkdir()
+        with self.assertRaises(V.BrokenCsv):
+            V.append_rows([row("pi05_1", "success", "ai")], d / "v.csv", forbid_dirs=(d,))
+        self.assertFalse((d / "v.csv").exists())
+
+    def test_refuses_symlink_and_record_dirs(self):
+        real = Path(self.tmp.name) / "real.csv"
+        V.append_rows([row("pi05_1", "success", "ai")], real)
+        link = Path(self.tmp.name) / "link.csv"
+        link.symlink_to(real)
+        with self.assertRaises(V.BrokenCsv):
+            V.append_rows([row("pi05_2", "success", "ai")], link)
+        runs = Path(self.tmp.name) / "runs"
+        (runs / "pi05_1").mkdir(parents=True)
+        with mock.patch.object(V, "RUNS_DIR", runs):
+            with self.assertRaises(V.BrokenCsv):
+                V.append_rows([row("pi05_2", "success", "ai")], runs / "pi05_1" / "x.csv")
+        with self.assertRaises(V.BrokenCsv):
+            V.append_rows([row("pi05_2", "success", "ai")], Path(self.tmp.name) / "x.json")
+        self.assertEqual(len(V.read_rows(real)), 1)
+
+    def test_skip_if_labeled_by(self):
+        V.append_rows([row("pi05_1", "failure", "human_only")], self.csv)
+        out = V.append_rows([row("pi05_1", "success", "ai"), row("pi05_2", "success", "ai")], self.csv,
+                            skip_if_labeled_by=V.HUMAN_LABELERS)
+        self.assertEqual([r["run_stem"] for r in out], ["pi05_2"])
+        self.assertEqual(V.latest_by_stem(V.read_rows(self.csv))["pi05_1"]["labeler"], "human_only")
+
+
+class TestMount(unittest.TestCase):
+    def test_not_mounted_stops_and_writes_nothing(self):
+        target = V.KIOXIA_MOUNT / "r2r2r-data" / "runs" / "pi05_policy_verdicts_v1_TEST_never.csv"
+        with mock.patch.object(V.os.path, "ismount", lambda p: False), \
+                mock.patch("builtins.open", side_effect=AssertionError("open してはいけない")):
+            with self.assertRaises(V.NotMounted):
+                V.append_rows([row("pi05_1", "success", "ai")], target)
+
+    def test_mounted_check_only_for_kioxia(self):
+        with mock.patch.object(V.os.path, "ismount", lambda p: False):
+            V.ensure_ssd_mounted("/tmp/whatever.csv")  # KIOXIA の外は確かめない (テスト用)
+
+    def test_seed_aborts_without_mount(self):
+        with mock.patch.object(V.os.path, "ismount", lambda p: False), \
+                mock.patch.object(sys, "argv", ["seed", "--run-input"]):
+            self.assertEqual(S.main(), 2)
+
+    def test_server_returns_503_without_mount(self):
+        with tempfile.TemporaryDirectory() as d:
+            runs = make_runs(Path(d) / "runs")
+            app = server.App(runs, V.KIOXIA_MOUNT / "r2r2r-data" / "runs" / "never_TEST.csv")
+            with mock.patch.object(V.os.path, "ismount", lambda p: False):
+                with self.assertRaises(V.NotMounted):
+                    app.add_verdict({"run_stem": "pi05_20261001_000003", "outcome": "success"})
+
+
+class TestLabeler(unittest.TestCase):
+    def test_labeler(self):
+        self.assertEqual(V.human_labeler_for("success", None), "human_only")
+        self.assertEqual(V.human_labeler_for("success", {"outcome": "success"}), "human")
+        self.assertEqual(V.human_labeler_for("failure", {"outcome": "success"}), "human_fixed_ai")
+
+
+class TestSeed(unittest.TestCase):
+    def setUp(self):
+        self.tmp = tempfile.TemporaryDirectory()
+        self.runs = make_runs(Path(self.tmp.name) / "runs")
+        self.csv = Path(self.tmp.name) / "v.csv"
+
+    def tearDown(self):
+        self.tmp.cleanup()
+
+    def test_run_input_copy_once(self):
+        c = S.do_run_input(self.csv, self.runs, dry_run=False)
+        self.assertEqual(c["success"], 1)
+        rows = V.read_rows(self.csv)
+        self.assertEqual([(r["run_stem"], r["outcome"], r["labeler"], r["pick"]) for r in rows],
+                         [("pi05_20261001_000001", "success", "run_input", "yes")])
+        S.do_run_input(self.csv, self.runs, dry_run=False)
+        self.assertEqual(len(V.read_rows(self.csv)), 1, "2 回流したら行が増えた")
+
+    def test_ai_targets_and_not_judgeable(self):
+        calls = []
+
+        def fake_api(key, imgs, evidence):
+            calls.append((len(imgs), evidence))
+            return {"pick": "yes", "place": "no", "outcome": "failure", "reason": "箱の外"}, ""
+        S.do_run_input(self.csv, self.runs, dry_run=False)
+        with mock.patch.object(S, "api_key", lambda: "k"), mock.patch.object(S, "call_api", fake_api):
+            c = S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only=None)
+        self.assertEqual(calls, [(3, "frames")])  # c だけ API を呼ぶ (frames 3 枚・._ は除く)
+        self.assertEqual(c["failure"], 1)
+        self.assertEqual(c["not_judgeable"], 2)  # b (null・素材なし) と d (何もない)
+        ai = V.latest_by_stem(V.read_rows(self.csv), labelers=("ai",))
+        self.assertNotIn("pi05_20261001_000001", ai)
+        self.assertEqual(ai["pi05_20261001_000003"]["ai_reason"], "[送ったチャンク 3] 箱の外")
+        n = len(V.read_rows(self.csv))
+        with mock.patch.object(S, "api_key", lambda: "k"), mock.patch.object(S, "call_api", fake_api):
+            S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only=None)
+        self.assertEqual(len(V.read_rows(self.csv)), n, "AI の行が 2 回書かれた")
+
+    def test_ai_skips_when_api_unavailable(self):
+        def boom(*a):
+            raise S.ApiUnavailable("http_401")
+        with mock.patch.object(S, "api_key", lambda: "k"), mock.patch.object(S, "call_api", boom):
+            c = S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only=None)
+        self.assertEqual(c["skipped"], 1)
+        self.assertNotIn("pi05_20261001_000003", V.latest_by_stem(V.read_rows(self.csv)))
+
+    def test_seed_never_adds_after_human(self):
+        V.append_rows([row("pi05_20261001_000003", "success", "human_only"),
+                       row("pi05_20261001_000001", "failure", "human_only")], self.csv)
+        with mock.patch.object(S, "api_key", lambda: "k"), \
+                mock.patch.object(S, "call_api", lambda *a: ({"outcome": "failure"}, "")):
+            S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only=None)
+        S.do_run_input(self.csv, self.runs, dry_run=False)
+        lat = V.latest_by_stem(V.read_rows(self.csv))
+        self.assertEqual(lat["pi05_20261001_000003"]["labeler"], "human_only")
+        self.assertEqual(lat["pi05_20261001_000001"]["labeler"], "human_only")
+
+    def test_seed_rechecks_inside_lock(self):
+        # API を待つ間に人が確定した → AI の行は足さない
+        def api_then_human(*a):
+            V.append_rows([row("pi05_20261001_000003", "failure", "human_only")], self.csv)
+            return {"outcome": "success"}, ""
+        with mock.patch.object(S, "api_key", lambda: "k"), mock.patch.object(S, "call_api", api_then_human):
+            c = S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only={"pi05_20261001_000003"})
+        self.assertEqual(c["skipped_human"], 1)
+        self.assertEqual(V.latest_by_stem(V.read_rows(self.csv))["pi05_20261001_000003"]["labeler"], "human_only")
+
+    def test_symlinked_side_files_are_ignored(self):
+        outside = Path(self.tmp.name) / "outside.jsonl"
+        outside.write_text(json.dumps({"chunk": "0", "executed": "True"}) + "\n")
+        rd = self.runs / "pi05_20261001_000004"
+        (rd / "log.jsonl").symlink_to(outside)
+        (rd / f"{rd.name}.json").symlink_to(outside)
+        self.assertEqual(V.read_log(rd), [])
+        self.assertIsNone(V.read_run_json(rd))
+
+    def test_server_refuses_csv_inside_runs_dir(self):
+        app = server.App(self.runs, self.runs / "pi05_20261001_000003" / "v.csv")
+        with self.assertRaises(V.BrokenCsv):
+            app.add_verdict({"run_stem": "pi05_20261001_000003", "outcome": "success"})
+        self.assertFalse((self.runs / "pi05_20261001_000003" / "v.csv").exists())
+
+    def test_symlinked_run_and_frames_are_ignored(self):
+        outside = Path(self.tmp.name) / "outside"
+        (outside / "frames").mkdir(parents=True)
+        (outside / "frames" / "0000.jpg").write_bytes(b"secret")
+        (self.runs / "pi05_20261001_000099").symlink_to(outside)
+        (self.runs / "pi05_20261001_000003" / "frames" / "0009.jpg").symlink_to(outside / "frames" / "0000.jpg")
+        self.assertNotIn("pi05_20261001_000099", V.list_run_stems(self.runs))
+        self.assertNotIn("0009.jpg", V.frame_files(self.runs / "pi05_20261001_000003"))
+
+    def test_api_key_export_line(self):
+        with tempfile.TemporaryDirectory() as d:
+            p = Path(d) / ".anthropic_key"
+            p.write_text("export ANTHROPIC_API_KEY='sk-test'\n")
+            with mock.patch.dict(os.environ, {"HOME": d}, clear=False), \
+                    mock.patch.dict(os.environ, {}, clear=False) as env:
+                env.pop("ANTHROPIC_API_KEY", None)
+                self.assertEqual(S.api_key(), "sk-test")
+
+
+class TestServer(unittest.TestCase):
+    def setUp(self):
+        self.tmp = tempfile.TemporaryDirectory()
+        self.runs = make_runs(Path(self.tmp.name) / "runs")
+        self.csv = Path(self.tmp.name) / "v.csv"
+        V.append_rows([row("pi05_20261001_000003", "success", "ai", ai_reason="入っている", evidence="frames")], self.csv)
+        self.app = server.App(self.runs, self.csv)
+        self.srv = server.ThreadingHTTPServer(("127.0.0.1", 0), server.make_handler(self.app))
+        threading.Thread(target=self.srv.serve_forever, daemon=True).start()
+        self.base = f"http://127.0.0.1:{self.srv.server_address[1]}"
+
+    def tearDown(self):
+        self.srv.shutdown()
+        self.srv.server_close()
+        self.tmp.cleanup()
+
+    def get(self, path):
+        with urllib.request.urlopen(self.base + path) as r:
+            return json.loads(r.read())
+
+    def post(self, body):
+        req = urllib.request.Request(self.base + "/api/verdict", data=json.dumps(body).encode(),
+                                     headers={"Content-Type": "application/json"}, method="POST")
+        try:
+            with urllib.request.urlopen(req) as r:
+                return r.status, json.loads(r.read())
+        except urllib.error.HTTPError as e:
+            return e.code, json.loads(e.read())
+
+    def test_list_and_detail(self):
+        runs = {r["run_stem"]: r for r in self.get("/api/runs")["runs"]}
+        self.assertEqual(len(runs), 4)
+        self.assertEqual(runs["pi05_20261001_000003"]["ai_outcome"], "success")
+        self.assertFalse(runs["pi05_20261001_000003"]["confirmed"])
+        d = self.get("/api/run/pi05_20261001_000003")
+        self.assertEqual(d["frames"], ["0000.jpg", "0001.jpg", "0002.jpg"])
+        self.assertEqual(len(d["states"]["joints"]), 3)
+        self.assertEqual(d["states"]["grip"][-1][1], 1.0)
+        self.assertEqual(d["executed_chunks"], 3)
+
+    def test_post_appends_and_labeler(self):
+        before = self.csv.read_bytes()
+        st, j = self.post({"run_stem": "pi05_20261001_000003", "outcome": "failure", "place": "no", "note": "箱の縁"})
+        self.assertEqual(st, 200)
+        self.assertTrue(self.csv.read_bytes().startswith(before))
+        last = V.read_rows(self.csv)[-1]
+        self.assertEqual((last["labeler"], last["outcome"], last["pick"], last["place"], last["ai_outcome"], last["ai_reason"],
+                          last["evidence"], last["note"]),
+                         ("human_fixed_ai", "failure", "unknown", "no", "success", "入っている", "frames", "箱の縁"))
+        st, j = self.post({"run_stem": "pi05_20261001_000003", "outcome": "success"})
+        self.assertEqual((j["row"]["labeler"], j["row"]["pick"], j["row"]["place"]), ("human", "yes", "yes"))
+        st, j = self.post({"run_stem": "pi05_20261001_000004", "outcome": "not_judgeable"})
+        self.assertEqual(j["row"]["labeler"], "human_only")
+        runs = {r["run_stem"]: r for r in self.get("/api/runs")["runs"]}
+        self.assertTrue(runs["pi05_20261001_000003"]["confirmed"])
+        self.assertEqual(runs["pi05_20261001_000003"]["outcome"], "success")
+
+    def test_same_op_id_writes_once(self):
+        n = len(V.read_rows(self.csv))
+        b = {"op_id": "abc", "run_stem": "pi05_20261001_000003", "outcome": "failure"}
+        self.assertEqual(self.post(b)[0], 200)
+        self.assertEqual(self.post(b)[0], 200)
+        self.assertEqual(len(V.read_rows(self.csv)), n + 1)
+
+    def test_media_link_to_other_run_is_refused(self):
+        other = self.runs / "pi05_20261001_000004" / "frames"
+        other.mkdir()
+        (other / "0000.jpg").write_bytes(b"other")
+        (self.runs / "pi05_20261001_000003" / "frames" / "0008.jpg").symlink_to(other / "0000.jpg")
+        with self.assertRaises(urllib.error.HTTPError) as cm:
+            urllib.request.urlopen(self.base + "/media/pi05_20261001_000003/frames/0008.jpg")
+        self.assertEqual(cm.exception.code, 404)
+
+    def test_post_rejects_bad(self):
+        n = len(V.read_rows(self.csv))
+        self.assertEqual(self.post({"run_stem": "pi05_20261001_000003", "outcome": "great"})[0], 400)
+        self.assertEqual(self.post({"run_stem": "../etc", "outcome": "success"})[0], 400)
+        self.assertEqual(self.post({"run_stem": "pi05_20990101_000000", "outcome": "success"})[0], 400)
+        self.assertEqual(len(V.read_rows(self.csv)), n)
+
+    def test_media_and_traversal(self):
+        with urllib.request.urlopen(self.base + "/media/pi05_20261001_000003/frames/0001.jpg") as r:
+            self.assertEqual(r.read(), b"\xff\xd8\xff\xd9")
+        for p in ("/media/pi05_20261001_000003/frames/..%2Flog.jsonl", "/media/..%2F..%2Fetc/top.mp4"):
+            with self.assertRaises(urllib.error.HTTPError) as cm:
+                urllib.request.urlopen(self.base + p)
+            self.assertEqual(cm.exception.code, 404)
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=1)
diff --git a/pi05/verdict_viewer/verdicts.py b/pi05/verdict_viewer/verdicts.py
new file mode 100644
index 0000000..652fce9
--- /dev/null
+++ b/pi05/verdict_viewer/verdicts.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python3
+"""推論の記録 (runs/pi05_policy/) の判定ファイルを読む・足す共通の部品 (依頼 183).
+
+判定ファイル: /Volumes/KIOXIA/r2r2r-data/runs/pi05_policy_verdicts_v1.csv (MASTER の保存先テーブル)
+  - 追記だけ. 既存の行は書き換えない. 同じ run_stem はいちばん新しい行 (ファイルの後ろの行) が正
+  - labeler=ai の行は未確定. 確定は人の行 (human / human_fixed_ai / human_only)
+  - 書く前に KIOXIA のマウントを確かめる. なければ止める (ローカルに逃がさない)
+元の記録 (runs/pi05_policy/ の中身) は読むだけ.
+"""
+import csv
+import fcntl
+import io
+import json
+import os
+import sys
+from datetime import datetime
+from pathlib import Path
+
+KIOXIA_MOUNT = Path("/Volumes/KIOXIA")
+DATA_ROOT = KIOXIA_MOUNT / "r2r2r-data"
+RUNS_DIR = DATA_ROOT / "runs" / "pi05_policy"
+VERDICTS_CSV = DATA_ROOT / "runs" / "pi05_policy_verdicts_v1.csv"
+
+COLUMNS = ["labeled_at", "run_stem", "pick", "place", "outcome", "labeler",
+           "ai_outcome", "ai_reason", "evidence", "note"]
+PICK_PLACE = ("yes", "no", "unknown")
+OUTCOMES = ("success", "failure", "unknown", "not_judgeable")
+LABELERS = ("run_input", "ai", "human", "human_fixed_ai", "human_only")
+HUMAN_LABELERS = ("human", "human_fixed_ai", "human_only")
+EVIDENCES = ("top.mp4", "frames", "both", "")
+MAX_NOTE = 500
+MAX_REASON = 2000
+
+
+class NotMounted(RuntimeError):
+    pass
+
+
+def ensure_ssd_mounted(csv_path=VERDICTS_CSV):
+    """KIOXIA の下に書くときはマウントを確かめる. なければ NotMounted (ローカルへは書かない).
+    テストで KIOXIA の外の一時ファイルに書くときは確かめない."""
+    p = Path(csv_path)
+    if str(p).startswith(str(KIOXIA_MOUNT) + os.sep) or p == KIOXIA_MOUNT:
+        if not os.path.ismount(str(KIOXIA_MOUNT)):
+            raise NotMounted(f"KIOXIA がマウントされていません ({KIOXIA_MOUNT}). 書かずに止めます")
+        if not p.parent.is_dir():
+            raise NotMounted(f"書き込み先のフォルダがありません ({p.parent}). 書かずに止めます")
+
+
+def now_iso():
+    return datetime.now().astimezone().isoformat(timespec="seconds")
+
+
+def validate_row(row):
+    r = {c: ("" if row.get(c) is None else str(row.get(c))) for c in COLUMNS}
+    # 長すぎる値は切る (csv の読み取りの上限を超えると以後読めなくなる. codex 3 回目 R3)
+    for c, n in (("note", MAX_NOTE), ("ai_reason", MAX_REASON)):
+        if len(r[c]) > n:
+            r[c] = r[c][:n] + "…"
+    if not r["run_stem"]:
+        raise ValueError("run_stem が空です")
+    if r["pick"] not in PICK_PLACE or r["place"] not in PICK_PLACE:
+        raise ValueError(f"pick / place は {PICK_PLACE} のどれか: {r['pick']!r} {r['place']!r}")
+    if r["outcome"] not in OUTCOMES:
+        raise ValueError(f"outcome は {OUTCOMES} のどれか: {r['outcome']!r}")
+    if r["labeler"] not in LABELERS:
+        raise ValueError(f"labeler は {LABELERS} のどれか: {r['labeler']!r}")
+    if r["ai_outcome"] not in OUTCOMES + ("",):
+        raise ValueError(f"ai_outcome は {OUTCOMES} のどれか か空: {r['ai_outcome']!r}")
+    if r["evidence"] not in EVIDENCES:
+        raise ValueError(f"evidence は {EVIDENCES} のどれか: {r['evidence']!r}")
+    if not r["labeled_at"]:
+        r["labeled_at"] = now_iso()
+    return r
+
+
+class BrokenCsv(RuntimeError):
+    pass
+
+
+def _check_existing(data):
+    """追記の前に今のファイルを確かめる. 見出しがちがう・最後が改行で終わらない・列の数がちがう行があれば止める
+    (そのまま足すと既存の最後の行に続けて書いてしまう. codex R4)."""
+    if not data:
+        return []
+    if not data.endswith(b"\n"):
+        raise BrokenCsv("判定ファイルの最後が改行で終わっていません (書きかけの行がある). 書かずに止めます")
+    try:  # strict: 閉じていない引用符も止める (codex 2 回目 R1)
+        rows = list(csv.reader(io.StringIO(data.decode("utf-8"), newline=""), strict=True))
+    except (csv.Error, UnicodeDecodeError) as e:
+        raise BrokenCsv(f"判定ファイルを読めません ({e}). 書かずに止めます")
+    if not rows or rows[0] != COLUMNS:
+        raise BrokenCsv("判定ファイルの見出しがちがいます. 書かずに止めます")
+    for i, r in enumerate(rows[1:], 2):
+        if len(r) != len(COLUMNS):
+            raise BrokenCsv(f"判定ファイルの {i} 行目の列の数が {len(r)} です ({len(COLUMNS)} のはず). 書かずに止めます")
+    return [dict(zip(COLUMNS, r)) for r in rows[1:]]
+
+
+def append_rows(rows, csv_path=VERDICTS_CSV, skip_if_labeled_by=None, forbid_dirs=()):
+    """行を末尾に足すだけ. 既存のバイトは触らない (追記モードで開く). 見出しはファイルが空のときだけ書く.
+    skip_if_labeled_by: この labeler の行がすでにある run_stem の行は足さない. 確かめはロックの中で行う
+    (seed が人の確定のあとに AI の行を足して未確定へ戻さないため. codex R2).
+    forbid_dirs: この中には書かない (使っている記録のフォルダ. codex 2 回目 R3). 書いた行を返す."""
+    rows = [validate_row(r) for r in rows]
+    ensure_ssd_mounted(csv_path)
+    if not rows:
+        return []
+    p = Path(csv_path)
+    if (p.suffix != ".csv" or within(RUNS_DIR, p) or within(DATA_ROOT / "datasets", p)
+            or any(within(d, p) for d in forbid_dirs)):
+        raise BrokenCsv(f"判定ファイルとして書けない場所です ({p}). 元の記録・datasets の中や .csv でないファイルには書きません")
+    if p.is_symlink():
+        raise BrokenCsv(f"判定ファイルがシンボリックリンクです ({p}). 書かずに止めます")
+    fd = os.open(str(p), os.O_RDWR | os.O_APPEND | os.O_CREAT | getattr(os, "O_NOFOLLOW", 0), 0o644)
+    with os.fdopen(fd, "r+b") as f:
+        fcntl.flock(f, fcntl.LOCK_EX)
+        try:
+            f.seek(0)
+            existing = _check_existing(f.read())
+            if skip_if_labeled_by:
+                done = {r["run_stem"] for r in existing if r.get("labeler") in skip_if_labeled_by}
+                rows = [r for r in rows if r["run_stem"] not in done]
+                if not rows:
+                    return []
+            buf = io.StringIO()
+            w = csv.DictWriter(buf, fieldnames=COLUMNS, lineterminator="\n")
+            if not existing and f.seek(0, os.SEEK_END) == 0:
+                w.writeheader()
+            for r in rows:
+                w.writerow(r)
+            f.write(buf.getvalue().encode("utf-8"))
+            f.flush()
+            os.fsync(f.fileno())
+        finally:
+            fcntl.flock(f, fcntl.LOCK_UN)
+    return rows
+
+
+def within(root, path):
+    """path がリンクをたどっても root の中にあるか (codex R6)."""
+    try:
+        Path(path).resolve().relative_to(Path(root).resolve())
+        return True
+    except (ValueError, OSError):
+        return False
+
+
+def read_rows(csv_path=VERDICTS_CSV):
+    p = Path(csv_path)
+    if not p.exists():
+        return []
+    with open(p, newline="", encoding="utf-8") as f:
+        return list(csv.DictReader(f))
+
+
+def latest_by_stem(rows, labelers=None):
+    """run_stem ごとにいちばん新しい行 (ファイルの後ろの行). labelers を渡すとその種類の行だけから選ぶ."""
+    out = {}
+    for r in rows:
+        if labelers is not None and r.get("labeler") not in labelers:
+            continue
+        out[r["run_stem"]] = r
+    return out
+
+
+def human_labeler_for(outcome, ai_row):
+    """人が付けたときの labeler. AI の行がなければ human_only, 同じなら human, 違えば human_fixed_ai."""
+    if not ai_row:
+        return "human_only"
+    return "human" if ai_row.get("outcome") == outcome else "human_fixed_ai"
+
+
+# ---- 元の記録を読む (読むだけ) ----
+
+def list_run_stems(runs_dir=RUNS_DIR):
+    return sorted(d.name for d in Path(runs_dir).iterdir()
+                  if d.is_dir() and d.name.startswith("pi05_") and within(runs_dir, d))
+
+
+def safe_file(run_dir, *rel):
+    """記録の中のファイル. リンクをたどって記録の外へ出るもの・ないものは None (codex 2 回目 R4)."""
+    p = Path(run_dir).joinpath(*rel)
+    return p if p.is_file() and within(run_dir, p) else None
+
+
+def read_run_json(run_dir):
+    p = safe_file(run_dir, f"{Path(run_dir).name}.json")
+    if p is None:
+        return None
+    try:
+        return json.loads(p.read_text(encoding="utf-8"))
+    except Exception:
+        return None
+
+
+def frame_files(run_dir):
+    d = Path(run_dir) / "frames"
+    if not d.is_dir():
+        return []
+    return sorted(f.name for f in d.iterdir()
+                  if f.suffix.lower() == ".jpg" and not f.name.startswith("._") and within(run_dir, f))
+
+
+def read_log(run_dir):
+    p = safe_file(run_dir, "log.jsonl")
+    out = []
+    if p is None:
+        return out
+    for line in p.read_text(encoding="utf-8", errors="replace").splitlines():
+        line = line.strip()
+        if not line:
+            continue
+        try:
+            out.append(json.loads(line))
+        except Exception:
+            pass
+    return out
+
+
+def executed_chunks(log):
+    return sum(1 for x in log if "chunk" in x and str(x.get("executed")) == "True")
+
+
+def has_top_mp4(run_dir):
+    return safe_file(run_dir, "recording", "top.mp4") is not None
+
+
+def run_input_row(run_stem, run_json):
+    """{run_stem}.json の outcome を写した行 (labeler=run_input). outcome がない / null なら None."""
+    if not run_json or run_json.get("outcome") in (None, ""):
+        return None
+    oc = run_json["outcome"]
+    if oc not in OUTCOMES:
+        oc = "unknown"
+    jd = run_json.get("judgments") or {}
+
+    def pv(k):
+        v = (jd.get(k) or {}).get("verdict")
+        return v if v in PICK_PLACE else "unknown"
+    return {"labeled_at": run_json.get("ended_at") or now_iso(), "run_stem": run_stem,
+            "pick": pv("pick"), "place": pv("place"), "outcome": oc, "labeler": "run_input",
+            "ai_outcome": "", "ai_reason": "", "evidence": "",
+            "note": "{run_stem}.json の outcome を写した (記録したときの入力)"}
+
+
+if __name__ == "__main__":
+    rows = read_rows()
+    lat = latest_by_stem(rows)
+    print(f"{VERDICTS_CSV}: {len(rows)} 行 / {len(lat)} 回")
+    sys.exit(0)
```

![最初の判定の画面。左に推論の記録の一覧、真ん中に録画と関節のグラフ、右に判定のボタンと AI の判定が並ぶ](https://pixelstomotors.com/media/LOG512_01_verdict_viewer_first.png)

AI が「判定できない」とした77回のうち35回は、素材がなくて API を呼ばなかった回、42回は画像だけの古い回で最後の画像が最後の動きより前に撮られていた回でした。報告の「決めてほしいこと」には、次の3つを決めました。

- 記録したときの入力（推論を終えたときに人が y/n を打った判定）の68回は、人の確定に数える
- アームを動かしていない回（送ったチャンク0）は試行になっていないので、成功率から外す
- 画像だけの古い回で AI が判定できないとした回は、人が見ずに「判定できない」で確定する


## 依頼184：判定の画面を立ち上げてブラウザで開く

画面の立ち上げも依頼箱で行いました。次からはダブルクリックで立ち上がる `.command` も作っています。


### 依頼184 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 10
---
# 依頼184：判定の画面（依頼183）を立ち上げてブラウザで開く

コードは変えない。立ち上げるだけ。

## やること
1. すでに 8765 番で動いていれば立ち上げ直さない（lsof -i :8765 で確かめる）
2. 動いていなければ、この依頼が終わっても止まらないように裏で立ち上げる
   nohup setsid python3 ~/r2r2r-scripts/pi05/verdict_viewer/server.py > ~/r2r2r-scripts/logs/verdict_viewer_server.log 2>&1 &
   （setsid がなければ nohup と disown で）
3. curl で http://localhost:8765/ が 200 を返すことを確かめる
4. open http://localhost:8765/ で既定のブラウザに開く
5. 次から人がダブルクリックで立ち上げられるように、~/r2r2r-scripts/pi05/verdict_viewer/判定の画面を開く.command を作る（中身は 1 と 2 と 4 と同じ。chmod +x）。commit は不要
6. 報告の最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼184 で Claude Code が返した報告

```text
# 結果：20261114_184_判定の画面を立ち上げて開く

- 状態：完了
- 始めた時刻：2026-11-14 22:40
- 終わった時刻：2026-11-14 22:41（1分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 95cd7519-d774-42d2-a40f-cdce0f562ed1`

## Claude Code の報告

**やったこと**
- `lsof -i :8765` で調べたところ、8765 番では何も動いていなかったので、判定の画面のサーバーを立ち上げました。Mac には `setsid` がないため、`nohup` と `disown` を使っています。この依頼が終わっても止まらずに動き続けます。ログは `~/r2r2r-scripts/logs/verdict_viewer_server.log` に出ます。
- 依頼の手順と 1 点だけ変えました。`server.py` は何も付けないと立ち上げたときに自分でもブラウザを開きます。そのため `--no-open` を付けて、手順 4 の `open` だけで開くようにしました。こうしないとタブが 2 枚開きます。コードは変えていません。
- `open http://localhost:8765/` で既定のブラウザに開きました。
- `pi05/verdict_viewer/判定の画面を開く.command` を作り、`chmod +x` しました。commit はしていません。
  - 中身は手順 1・2・4 と同じで、`setsid` がない Mac では `nohup` と `disown` で立ち上げます。
  - 立ち上げたあと、最大 10 秒、200 が返るのを待ちます。返らなければログの最後の 20 行を出して止まります。
- 作業の記録を `~/r2r2r-scripts/logs/` に残しました。

**結果**
- `curl http://localhost:8765/` は 200 を返しました（プロセス番号 14361 で待ち受けています）。
- `open` は問題なく終わりました。
- `.command` は書き方の確認が通りました。すでに動いているときの流れも実行し、「すでに 8765 番で動いています」と出てブラウザを開き、問題なく終わりました。
- 動いていないときに `.command` から立ち上げる流れは、サーバーがすでに動いていたため試していません。

**変えたファイル**
- `pi05/verdict_viewer/判定の画面を開く.command`（新しく作成）
- `logs/verdict_viewer_server.log`（サーバーのログ）
- `logs/` の作業記録 1 件

**決めてほしいこと**
なし

判定：合格
```


## 依頼185：決めた3つを判定ファイルと画面に入れる


### 依頼185 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 60
---
# 依頼185：判定の決め 3 つを判定ファイルと画面に入れる

依頼183 の「決めてほしいこと」1〜3 へのエイイチの決め（2026-11-14）。実機は動かさない。元の記録は読むだけ、判定ファイルは追記だけ（依頼183 と同じ決まり）。画面（依頼184 で立ち上げたもの）が動いていたら、直したあとに立ち上げ直す。

## 決め
1. 記録したときの入力（labeler=run_input）の 68 回は、人の確定に数える。推論を終えたときにエイイチが y/n を打った判定のため。行は書き換えず、確定かどうかを決めるコードの側で run_input を人の確定として扱う
2. アームを動かしていない回（送ったチャンク 0。依頼183 の報告では 51 回）は、試行になっていないので成功率から外す。outcome に not_applicable を足し（受け渡しの台帳と同じ語）、labeler=rule の行を追記する
3. 画像だけ（frames/ のみ）で AI が not_judgeable とした回と、素材がなく API を呼ばなかった回は、人が見ずに not_judgeable で確定する。labeler=rule の行を追記する
- 2 と 3 の両方に当たる回は 2（not_applicable）にする
- 人の行（human / human_fixed_ai / human_only）がすでにある回には rule の行を足さない
- rule の行の note に「エイイチの決め 2026-11-14 依頼185」と、どの決めに当たったか（2 か 3）を書く

## やること
1. verdicts.py の語に not_applicable と labeler=rule を足す。確定の扱いは run_input・human・human_fixed_ai・human_only・rule
2. 2 と 3 の行を判定ファイルに追記する（送ったチャンクの数え方は log.jsonl から。数え方を報告に書く）
3. 画面：既定の一覧は「まだ確定していない回」。成功率（success / (success + failure)）を画面の上に出し、not_applicable・not_judgeable・unknown は分母に入れない
4. テスト（rule の行が人の行のある回に入らないこと・2 と 3 の重なりが 2 になること・成功率の分母）。変えたファイルだけを指定して commit（git add . と git clean は使わない）。codex のレビューは画面の数え方と追記の部分だけ 1 回でよい

## 報告に書くこと
- 2 に当たった回・3 に当たった回・重なった回の数
- エイイチが画面で見る回の数（まだ確定していない回）
- 今の成功率（確定した回だけ）
- 最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼185 で Claude Code が返した報告

```text
# 結果：20261114_185_判定の決め3つを判定ファイルと画面に入れる

- 状態：完了
- 始めた時刻：2026-11-14 22:41
- 終わった時刻：2026-11-14 22:45（4分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume dd730ac4-d733-4a65-8ff1-cd0b7d3b4ad8`

## Claude Code の報告

**やったこと**
- `verdicts.py` に outcome の `not_applicable` と、付けた人の種類 `labeler=rule` を足しました。確定の扱いは run_input・human・human_fixed_ai・human_only・rule の 5 つです。既存の行は書き換えず、確定かどうかを判断するコードの側で run_input を人の確定として数えています。確定したあとに AI の行が足されても、未確定には戻りません。
- `seed_verdicts.py` に `--rule` を足し、判定ファイルに rule の行を追記しました。2 と 3 の両方に当たる回は 2 にしています。確定の行(run_input・人・rule)がすでにある回には足しません。この確かめは書き込みのロックの中でも行います。note には「エイイチの決め 2026-11-14 依頼185」と、当たった決め(決め2 か 決め3)を書きました。
- 送ったチャンクの数え方：log.jsonl の chunk がある行のうち、executed が True の行の数です。log.jsonl がない回は 0 と数えます(今は該当なし)。
- AI が not_applicable を付けないようにし、確定した回には AI の行も足さないようにしました。
- 画面の既定の一覧を「まだ確定していない回」にしました。上には成功率(success / (success + failure))と、分母に入れない回の数(試行でない・判定できない・分からない)を出します。
- テストを足し、39 本すべて合格しました。足したのは、人の行がある回と run_input の回に rule の行が入らないこと、2 と 3 の重なりが 2 になること、成功率の分母、2 回流しても増えないことなどです。
- codex のレビューは画面の数え方と追記の部分に 1 回かけ、指摘はありませんでした。
- 画面(8765 番)は動いていたので、止めて立ち上げ直しました。新しい一覧と成功率が出ることを確かめています。
- commit は 31113c0 です。

**結果**
- 2 に当たった回(not_applicable)：51 回
- 3 に当たった回(not_judgeable)：33 回
- 両方に当たった回：44 回(すべて 2 として 51 回に入っています)
- 追記した rule の行：84 行。既存のバイトは変わっていません。もう一度流しても足す行は 0 でした。
- エイイチが画面で見る回(まだ確定していない回)：24 回(AI が成功とした 14 回、失敗とした 10 回)
- 今の成功率(確定した回だけ)：41 / 68 = 60.3%(確定 152 回のうち、not_applicable 51 回と not_judgeable 33 回は分母に入れていません)

**変えたファイル**
- `pi05/verdict_viewer/verdicts.py`
- `pi05/verdict_viewer/seed_verdicts.py`
- `pi05/verdict_viewer/server.py`
- `pi05/verdict_viewer/index.html`
- `pi05/verdict_viewer/test_verdicts.py`
- 判定ファイル `/Volumes/KIOXIA/r2r2r-data/runs/pi05_policy_verdicts_v1.csv`(追記だけ)
- 作業の記録 `logs/20261114_2245.md`(commit していません)

**決めてほしいこと**
- pi05_20261031_185246 は送ったチャンクが 0 なのに、記録したときの入力が success になっています。決め 1 で run_input は人の確定に数えるため、rule の行(not_applicable)は足していません。今は成功率の分子と分母に入っています。そのまま success とするか、not_applicable にするかを決めてください。not_applicable にすると、成功率は 40 / 67 = 59.7% になります。
- 依頼183 の報告にあった 51 回と、今回送ったチャンクを数えた 52 回の差は、この 1 回です。

判定：止めた（決めてほしいことあり）
```

### 依頼185 のコードの差分（コミット 31113c0）

```diff
commit 31113c0d27bfb195a1577d5becde7f61f89520f0
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 22:45:17 2026 +0900

    判定の決め 3 つを判定ファイルと画面に入れる (依頼 185・エイイチの決め 2026-11-14). verdicts.py に outcome=not_applicable と labeler=rule を足し, 確定の扱いを run_input・human・human_fixed_ai・human_only・rule にする (CONFIRMED_LABELERS. 行は書き換えない). current_by_stem (確定の行があればそれ. 後ろの AI の行で未確定へ戻らない)・success_rate (確定した回の success / (success + failure). not_applicable・not_judgeable・unknown は分母に入れない)・rule_row (決め 2: 送ったチャンク 0 → not_applicable. 決め 3: AI が frames/ だけ・素材なしで not_judgeable → not_judgeable. 両方なら 2. note に「エイイチの決め 2026-11-14 依頼185」と決めの番号). seed_verdicts.py に --rule (送ったチャンクは log.jsonl の chunk の行で executed が True の数. 確定の行がある回には足さない・ロックの中でも確かめる). AI は not_applicable を付けない・確定した回に AI の行を足さない. 画面: 既定の一覧を「まだ確定していない回」に, 上に成功率と分母に入れない数. 判定ファイルに rule 84 行 (決め 2 51・決め 3 33・重なり 44) を追記. 未確定 24 回・成功率 41/68 = 60.3%. テスト test_verdicts 39 (依頼 185. codex 1 回・指摘なし)
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html       | 23 +++++++--
 pi05/verdict_viewer/seed_verdicts.py | 50 +++++++++++++++++--
 pi05/verdict_viewer/server.py        | 13 +++--
 pi05/verdict_viewer/test_verdicts.py | 97 ++++++++++++++++++++++++++++++++++++
 pi05/verdict_viewer/verdicts.py      | 50 +++++++++++++++++--
 5 files changed, 216 insertions(+), 17 deletions(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index 461bab8..f9008e1 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -18,6 +18,8 @@
   #side header { padding: 10px; border-bottom: 1px solid var(--border); }
   #side h1 { font-size: 14px; margin: 0 0 6px; }
   #filter { width: 100%; font-size: 13px; padding: 3px; }
+  #rate { margin-top: 6px; font-size: 13px; }
+  #rate b { font-size: 16px; }
   #count { color: var(--text-secondary); margin-top: 4px; font-size: 12px; }
   #list { overflow-y: auto; flex: 1; }
   .item { padding: 5px 10px; border-bottom: 1px solid var(--border); cursor: pointer; display: flex; justify-content: space-between; gap: 6px; }
@@ -28,7 +30,7 @@
   .tag { font-size: 11px; padding: 0 5px; border-radius: 3px; border: 1px solid var(--border); white-space: nowrap; align-self: center; }
   .tag.success { color: var(--ok); border-color: var(--ok); }
   .tag.failure { color: var(--bad); border-color: var(--bad); }
-  .tag.unknown, .tag.not_judgeable { color: var(--warn); border-color: var(--warn); }
+  .tag.unknown, .tag.not_judgeable, .tag.not_applicable { color: var(--warn); border-color: var(--warn); }
   .tag.ai { border-style: dashed; }
   #main { flex: 1; overflow-y: auto; padding: 12px 16px; }
   #title { font-family: ui-monospace, Menlo, monospace; font-size: 15px; font-weight: 600; }
@@ -69,11 +71,12 @@
   <header>
     <h1>推論の記録の判定</h1>
     <select id="filter">
-      <option value="todo">人の確定がまだの回</option>
+      <option value="todo">まだ確定していない回</option>
       <option value="all">全部</option>
       <option value="failure">失敗だけ (今の判定)</option>
       <option value="diff">AI と人が違う回</option>
     </select>
+    <div id="rate"></div>
     <div id="count"></div>
   </header>
   <div id="list"></div>
@@ -109,8 +112,8 @@
   <div id="chart"></div>
 </div>
 <script>
-const OC_JA = {success: "成功", failure: "失敗", unknown: "分からない", not_judgeable: "判定できない", "": "なし"};
-const LB_JA = {run_input: "記録時の入力", ai: "AI", human: "人 (AI と同じ)", human_fixed_ai: "人 (AI を直した)", human_only: "人 (AI なし)", "": ""};
+const OC_JA = {success: "成功", failure: "失敗", unknown: "分からない", not_judgeable: "判定できない", not_applicable: "試行でない", "": "なし"};
+const LB_JA = {run_input: "記録時の入力", ai: "AI", human: "人 (AI と同じ)", human_fixed_ai: "人 (AI を直した)", human_only: "人 (AI なし)", rule: "決め (依頼185)", "": ""};
 const COLORS = ["--s1", "--s2", "--s3", "--s4", "--s5", "--s6"].map(v => getComputedStyle(document.documentElement).getPropertyValue(v).trim());
 const pendingOps = {};  // run_stem → 書けたか分からない操作 (回ごとに残す. codex 6 回目 R1)
 let selSeq = 0;  // 応答が届かなかった操作. 同じ中身で押し直したら同じ op_id で送る (codex 2 回目 R2)
@@ -125,7 +128,7 @@ function applyFilter() {
   const f = $("#filter").value;
   view = runs.filter(r => f === "all" ? true : f === "todo" ? !r.confirmed : f === "failure" ? r.outcome === "failure"
                           : (r.ai_outcome && r.human_outcome && r.ai_outcome !== r.human_outcome));
-  $("#count").textContent = `${view.length} 回 / 全 ${runs.length} 回 (人の確定済み ${runs.filter(r => r.confirmed).length})`;
+  $("#count").textContent = `${view.length} 回 / 全 ${runs.length} 回 (確定済み ${runs.filter(r => r.confirmed).length})`;
   $("#list").innerHTML = view.map(r => `<div class="item ${cur === r.run_stem ? "sel" : ""}" data-stem="${r.run_stem}">
       <div><div class="stem">${r.run_stem.replace("pi05_", "")}</div>
       <div class="sub">${r.has_mp4 ? "top.mp4" : r.n_frames ? "frames " + r.n_frames : "素材なし"} ・ ${LB_JA[r.labeler] || "—"}</div></div>
@@ -133,10 +136,20 @@ function applyFilter() {
   document.querySelectorAll(".item").forEach(el => el.onclick = () => select(el.dataset.stem));
 }
 
+// 成功率は確定した回だけ. 分母は 成功 + 失敗 (試行でない・判定できない・分からない は入れない. 依頼 185)
+function renderRate(st) {
+  if (!st) { $("#rate").textContent = ""; return; }
+  const b = st.by_outcome || {};
+  const pct = st.rate === null ? "—" : (st.rate * 100).toFixed(1) + "%";
+  $("#rate").innerHTML = `成功率 <b>${pct}</b> (成功 ${st.success} / (成功 ${st.success} + 失敗 ${st.failure}))`
+    + `<div class="muted">分母に入れない: 試行でない ${b.not_applicable || 0} ・ 判定できない ${b.not_judgeable || 0} ・ 分からない ${b.unknown || 0} (確定 ${st.confirmed} 回のうち)</div>`;
+}
+
 async function loadRuns() {
   const res = await fetch("/api/runs"); const j = await res.json();
   if (!res.ok || !Array.isArray(j.runs)) throw new Error(j.error || "一覧を読めません");  // 今の一覧は残す (codex 4 回目 R1)
   runs = j.runs;
+  renderRate(j.stats);
   applyFilter();
 }
 
diff --git a/pi05/verdict_viewer/seed_verdicts.py b/pi05/verdict_viewer/seed_verdicts.py
index 9deec01..19dafb6 100644
--- a/pi05/verdict_viewer/seed_verdicts.py
+++ b/pi05/verdict_viewer/seed_verdicts.py
@@ -4,6 +4,7 @@
   python3 pi05/verdict_viewer/seed_verdicts.py --run-input      # {run_stem}.json の outcome を写す (labeler=run_input)
   python3 pi05/verdict_viewer/seed_verdicts.py --ai             # 印のない回を AI が判定 (labeler=ai)
   python3 pi05/verdict_viewer/seed_verdicts.py --ai --dry-run   # API を呼ばずに素材だけ数える
+  python3 pi05/verdict_viewer/seed_verdicts.py --rule           # エイイチの決め (依頼 185) の行を足す (labeler=rule)
 
 - 元の記録は読むだけ. 判定ファイルには追記だけ (verdicts.append_rows)
 - すでに同じ種類の行がある回は足さない (何度流しても同じ行が増えない)
@@ -13,6 +14,8 @@
   (終わりの wait / home では人がブロックを箱から出していることがあるので, そこは使わない)
 - API は今の vlm_judge (dynamic_tracking_limits/place/place_modules/vlm_judge.py) と同じモデル・キーの読み方.
   使えない (キーがない・通信やクレジットのエラー) 回は行を書かずに飛ばし, 最後に数を出す
+- --rule (依頼 185): 送ったチャンク 0 の回 → not_applicable (決め 2), AI が frames/ だけ・素材なしで
+  not_judgeable とした回 → not_judgeable (決め 3). 両方なら 2. 確定の行 (run_input・人・rule) がある回には足さない
 """
 import argparse
 import base64
@@ -179,7 +182,7 @@ def ai_row(run_stem, parsed, evidence, n_exec):
     def pv(v):
         return v if v in V.PICK_PLACE else "unknown"
     oc = parsed.get("outcome") if isinstance(parsed, dict) else None
-    oc = oc if oc in V.OUTCOMES else "unknown"
+    oc = oc if oc in V.AI_OUTCOMES else "unknown"
     reason = str(parsed.get("reason", "")).replace("\n", " ").strip() if isinstance(parsed, dict) else ""
     return {"labeled_at": V.now_iso(), "run_stem": run_stem,
             "pick": pv(parsed.get("pick")), "place": pv(parsed.get("place")), "outcome": oc, "labeler": "ai",
@@ -210,7 +213,7 @@ def do_ai(csv_path, runs_dir, dry_run, limit, only):
     rows = V.read_rows(csv_path)
     marked = set(V.latest_by_stem(rows, labelers=("run_input",)))
     have_ai = set(V.latest_by_stem(rows, labelers=("ai",)))
-    human = set(V.latest_by_stem(rows, labelers=V.HUMAN_LABELERS))  # 人が確定した回には AI の行を足さない (codex R2)
+    human = set(V.latest_by_stem(rows, labelers=V.CONFIRMED_LABELERS))  # 確定した回には AI の行を足さない (codex R2・依頼 185)
     targets = []
     for stem in V.list_run_stems(runs_dir):
         j = V.read_run_json(Path(runs_dir) / stem)
@@ -260,7 +263,7 @@ def do_ai(csv_path, runs_dir, dry_run, limit, only):
             counts["not_judgeable"] += 1
             continue
         # 1 回ずつ書く (途中で止まっても済んだ回は残る). API を待つ間に人が確定していたら足さない
-        if not V.append_rows([row], csv_path, skip_if_labeled_by=("ai", "run_input") + V.HUMAN_LABELERS,
+        if not V.append_rows([row], csv_path, skip_if_labeled_by=("ai",) + V.CONFIRMED_LABELERS,
                             forbid_dirs=(runs_dir,)):
             counts["skipped_human"] += 1
             print(f"  {i:3d} {stem} 足さなかった (待つ間に人か写しの行が足されていた)")
@@ -272,17 +275,52 @@ def do_ai(csv_path, runs_dir, dry_run, limit, only):
     return counts
 
 
+def do_rule(csv_path, runs_dir, dry_run):
+    """エイイチの決め (2026-11-14 依頼 185) の行を足す. 送ったチャンクは log.jsonl の chunk の行で executed が True の数."""
+    rows = V.read_rows(csv_path)
+    conf = V.latest_by_stem(rows, labelers=V.CONFIRMED_LABELERS)
+    ai = V.latest_by_stem(rows, labelers=("ai",))
+    out, counts = [], Counter()
+    for stem in V.list_run_stems(runs_dir):
+        rd = Path(runs_dir) / stem
+        n_exec = V.executed_chunks(V.read_log(rd))
+        a = ai.get(stem) or {}
+        hit2 = n_exec == 0
+        hit3 = a.get("outcome") == "not_judgeable" and a.get("evidence") in ("frames", "")
+        if stem in conf:
+            if hit2 or hit3:
+                counts[f"skip_{conf[stem]['labeler']}"] += 1
+                print(f"  {stem} 足さない (確定の行あり: {conf[stem]['labeler']} {conf[stem]['outcome']}・"
+                      f"送ったチャンク {n_exec})")
+            continue
+        r = V.rule_row(stem, n_exec, ai.get(stem))
+        if r is None:
+            continue
+        counts["rule2" if hit2 else "rule3"] += 1
+        counts["both"] += hit2 and hit3
+        out.append(r)
+    print(f"[RULE ] 足す行 {len(out)} (決め2 not_applicable {counts['rule2']} (うち 3 にも当たる {counts['both']}) / "
+          f"決め3 not_judgeable {counts['rule3']})" + (" ※ dry-run なので書いていません" if dry_run else ""))
+    if not dry_run and out:
+        written = V.append_rows(out, csv_path, skip_if_labeled_by=V.CONFIRMED_LABELERS, forbid_dirs=(runs_dir,))
+        if len(written) != len(out):
+            print(f"[RULE ] 書くまでの間に確定の行が足されていた {len(out) - len(written)} 回は足さなかった")
+        counts["written"] = len(written)
+    return counts
+
+
 def main():
     ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
     ap.add_argument("--run-input", action="store_true", help="{run_stem}.json の outcome を写す")
     ap.add_argument("--ai", action="store_true", help="印のない回を AI が判定する")
+    ap.add_argument("--rule", action="store_true", help="エイイチの決め (依頼 185) の行を足す")
     ap.add_argument("--dry-run", action="store_true", help="書かない・API を呼ばない")
     ap.add_argument("--limit", type=int, default=0, help="AI の対象を先頭から N 回まで")
     ap.add_argument("--stems", nargs="*", default=None, help="AI の対象をこの run_stem だけにする")
     ap.add_argument("--runs-dir", default=str(V.RUNS_DIR))
     a = ap.parse_args()
-    if not (a.run_input or a.ai):
-        ap.error("--run-input か --ai を付けてください")
+    if not (a.run_input or a.ai or a.rule):
+        ap.error("--run-input か --ai か --rule を付けてください")
     try:
         csv_path = V.VERDICTS_CSV  # 書き先は保存先テーブルの 1 か所だけ (codex R3. テストは関数に渡す)
         V.ensure_ssd_mounted(csv_path)
@@ -290,6 +328,8 @@ def main():
             do_run_input(csv_path, a.runs_dir, a.dry_run)
         if a.ai:
             do_ai(csv_path, a.runs_dir, a.dry_run, a.limit, set(a.stems) if a.stems else None)
+        if a.rule:
+            do_rule(csv_path, a.runs_dir, a.dry_run)
     except (V.NotMounted, V.BrokenCsv) as e:
         print(f"[ABORT] {e}")
         return 2
diff --git a/pi05/verdict_viewer/server.py b/pi05/verdict_viewer/server.py
index 7e67f1e..79e8055 100644
--- a/pi05/verdict_viewer/server.py
+++ b/pi05/verdict_viewer/server.py
@@ -109,7 +109,7 @@ class App:
 
     def runs_summary(self):
         rows = V.read_rows(self.csv_path)
-        latest = V.latest_by_stem(rows)
+        latest = V.current_by_stem(rows)  # 確定の行があればそれ (依頼 185)
         ai = V.latest_by_stem(rows, labelers=("ai",))
         human = V.latest_by_stem(rows, labelers=V.HUMAN_LABELERS)
         out = []
@@ -124,10 +124,15 @@ class App:
                 "labeler": lt["labeler"] if lt else "",
                 "ai_outcome": a["outcome"] if a else "",
                 "human_outcome": h["outcome"] if h else "",
-                "confirmed": bool(lt and lt["labeler"] in V.HUMAN_LABELERS),
+                "confirmed": bool(lt and lt["labeler"] in V.CONFIRMED_LABELERS),
             })
         return out
 
+    def stats(self):
+        """確定した回だけの成功率 (依頼 185). 記録のフォルダにある回だけ数える."""
+        stems = set(V.list_run_stems(self.runs_dir))
+        return V.success_rate([r for r in V.read_rows(self.csv_path) if r["run_stem"] in stems])
+
     def run_detail(self, stem):
         rd = self.runs_dir / stem
         rows = [r for r in V.read_rows(self.csv_path) if r["run_stem"] == stem]
@@ -142,7 +147,7 @@ class App:
             "states": st,
             "video_t": video_times(rd, st.get("t0")) if V.has_top_mp4(rd) else None,
             "ai": ai[-1] if ai else None,
-            "latest": rows[-1] if rows else None,
+            "latest": V.current_by_stem(rows).get(stem),
             "history": rows,
             "executed_chunks": V.executed_chunks(log),
             "end_reason": (j or {}).get("end_reason", ""),
@@ -255,7 +260,7 @@ def make_handler(app):
                 if not parts:
                     return self._send(200, (HERE / "index.html").read_bytes(), "text/html; charset=utf-8")
                 if parts == ["api", "runs"]:
-                    return self._send(200, {"runs": app.runs_summary(), "csv": str(app.csv_path)})
+                    return self._send(200, {"runs": app.runs_summary(), "stats": app.stats(), "csv": str(app.csv_path)})
                 if (len(parts) == 3 and parts[:2] == ["api", "run"] and STEM_RE.match(parts[2])
                         and (app.runs_dir / parts[2]).is_dir() and V.within(app.runs_dir, app.runs_dir / parts[2])):
                     return self._send(200, app.run_detail(parts[2]))
diff --git a/pi05/verdict_viewer/test_verdicts.py b/pi05/verdict_viewer/test_verdicts.py
index 07519a9..9985e43 100644
--- a/pi05/verdict_viewer/test_verdicts.py
+++ b/pi05/verdict_viewer/test_verdicts.py
@@ -374,5 +374,102 @@ class TestServer(unittest.TestCase):
             self.assertEqual(cm.exception.code, 404)
 
 
+class TestRule185(unittest.TestCase):
+    """エイイチの決め (2026-11-14 依頼 185): run_input も確定・送ったチャンク 0 → not_applicable・素材不足 → not_judgeable."""
+    def setUp(self):
+        self.tmp = tempfile.TemporaryDirectory()
+        self.runs = Path(self.tmp.name) / "runs"
+        self.csv = Path(self.tmp.name) / "v.csv"
+        # stem: (送ったチャンク, 先に入れる行)
+        self.case = {
+            "pi05_20261002_000001": (0, [row("pi05_20261002_000001", "not_judgeable", "ai", evidence="frames")]),  # 2 と 3 → 2
+            "pi05_20261002_000002": (2, [row("pi05_20261002_000002", "not_judgeable", "ai", evidence="frames")]),  # 3
+            "pi05_20261002_000003": (2, [row("pi05_20261002_000003", "not_judgeable", "ai", evidence="")]),        # 3 (素材なし)
+            "pi05_20261002_000004": (0, [row("pi05_20261002_000004", "failure", "ai", evidence="top.mp4")]),       # 2
+            "pi05_20261002_000005": (0, [row("pi05_20261002_000005", "not_judgeable", "ai", evidence="frames"),
+                                         row("pi05_20261002_000005", "failure", "human_fixed_ai")]),             # 人の行 → 足さない
+            "pi05_20261002_000006": (2, [row("pi05_20261002_000006", "not_judgeable", "ai", evidence=""),
+                                         row("pi05_20261002_000006", "success", "human_only")]),                 # 人の行 → 足さない
+            "pi05_20261002_000007": (0, [row("pi05_20261002_000007", "success", "run_input")]),                  # run_input → 足さない
+            "pi05_20261002_000008": (2, [row("pi05_20261002_000008", "not_judgeable", "ai", evidence="top.mp4")]),  # 当たらない
+            "pi05_20261002_000009": (3, [row("pi05_20261002_000009", "failure", "ai", evidence="frames")]),       # 当たらない
+        }
+        rows = []
+        for stem, (n, rs) in self.case.items():
+            d = self.runs / stem
+            d.mkdir(parents=True)
+            lines = [{"type": "model"}] + [{"chunk": str(i), "executed": "True"} for i in range(n)] + [{"chunk": "9", "executed": "False"}]
+            (d / "log.jsonl").write_text("\n".join(json.dumps(x) for x in lines) + "\n")
+            rows += rs
+        V.append_rows(rows, self.csv)
+
+    def tearDown(self):
+        self.tmp.cleanup()
+
+    def rule_rows(self):
+        return {r["run_stem"]: r for r in V.read_rows(self.csv) if r["labeler"] == "rule"}
+
+    def test_rule_rows(self):
+        c = S.do_rule(self.csv, self.runs, dry_run=False)
+        got = {k[-1]: v["outcome"] for k, v in self.rule_rows().items()}
+        self.assertEqual(got, {"1": "not_applicable", "2": "not_judgeable", "3": "not_judgeable", "4": "not_applicable"})
+        self.assertEqual((c["rule2"], c["rule3"], c["both"]), (2, 2, 1))
+        for r in self.rule_rows().values():
+            self.assertIn("エイイチの決め 2026-11-14 依頼185", r["note"])
+        self.assertIn("決め2", self.rule_rows()["pi05_20261002_000001"]["note"])
+        self.assertIn("決め3", self.rule_rows()["pi05_20261002_000002"]["note"])
+
+    def test_rule_never_after_human_or_run_input(self):
+        S.do_rule(self.csv, self.runs, dry_run=False)
+        for stem in ("pi05_20261002_000005", "pi05_20261002_000006", "pi05_20261002_000007"):
+            self.assertNotIn(stem, self.rule_rows())
+
+    def test_rule_twice_adds_nothing(self):
+        S.do_rule(self.csv, self.runs, dry_run=False)
+        before = self.csv.read_bytes()
+        S.do_rule(self.csv, self.runs, dry_run=False)
+        self.assertEqual(self.csv.read_bytes(), before)
+
+    def test_rule_rechecks_inside_lock(self):
+        # 一覧を読んだあとに人の行が足されたら, rule の行は足さない
+        real = V.read_rows
+        def late_human(p):
+            rows = real(p)
+            V.append_rows([row("pi05_20261002_000002", "failure", "human")], self.csv)
+            return rows
+        with mock.patch.object(V, "read_rows", side_effect=late_human):
+            S.do_rule(self.csv, self.runs, dry_run=False)
+        self.assertNotIn("pi05_20261002_000002", self.rule_rows())
+
+    def test_confirmed_and_success_rate(self):
+        S.do_rule(self.csv, self.runs, dry_run=False)
+        app = server.App(self.runs, self.csv)
+        conf = {r["run_stem"][-1]: r["confirmed"] for r in app.runs_summary()}
+        self.assertEqual(conf, {"1": True, "2": True, "3": True, "4": True, "5": True, "6": True, "7": True,
+                                "8": False, "9": False})
+        st = app.stats()
+        # 確定: success 2 (6・7) / failure 1 (5). not_applicable 2・not_judgeable 2 は分母に入れない. AI の行も入れない
+        self.assertEqual((st["success"], st["failure"], st["denominator"], st["confirmed"]), (2, 1, 3, 7))
+        self.assertAlmostEqual(st["rate"], 2 / 3)
+        self.assertEqual(st["by_outcome"]["not_applicable"], 2)
+
+    def test_success_rate_denominator(self):
+        rows = [row("a", "success", "human"), row("b", "failure", "run_input"), row("c", "unknown", "human"),
+                row("d", "not_judgeable", "rule"), row("e", "not_applicable", "rule"), row("f", "success", "ai"),
+                row("b", "success", "human_fixed_ai")]  # b は後ろの人の行が正
+        st = V.success_rate(rows)
+        self.assertEqual((st["success"], st["failure"], st["denominator"]), (2, 0, 2))
+        self.assertEqual(st["rate"], 1.0)
+        self.assertIsNone(V.success_rate([row("x", "not_applicable", "rule")])["rate"])
+
+    def test_ai_after_confirmed_does_not_unconfirm(self):
+        rows = [row("a", "not_applicable", "rule"), row("a", "failure", "ai")]
+        self.assertEqual(V.current_by_stem(rows)["a"]["labeler"], "rule")
+
+    def test_ai_cannot_write_not_applicable(self):
+        r = S.ai_row("pi05_x", {"outcome": "not_applicable", "pick": "no", "place": "no"}, "frames", 0)
+        self.assertEqual(r["outcome"], "unknown")
+
+
 if __name__ == "__main__":
     unittest.main(verbosity=1)
diff --git a/pi05/verdict_viewer/verdicts.py b/pi05/verdict_viewer/verdicts.py
index 652fce9..e88a95e 100644
--- a/pi05/verdict_viewer/verdicts.py
+++ b/pi05/verdict_viewer/verdicts.py
@@ -3,7 +3,10 @@
 
 判定ファイル: /Volumes/KIOXIA/r2r2r-data/runs/pi05_policy_verdicts_v1.csv (MASTER の保存先テーブル)
   - 追記だけ. 既存の行は書き換えない. 同じ run_stem はいちばん新しい行 (ファイルの後ろの行) が正
-  - labeler=ai の行は未確定. 確定は人の行 (human / human_fixed_ai / human_only)
+  - labeler=ai の行は未確定. 確定は run_input・人の行 (human / human_fixed_ai / human_only)・rule
+    (依頼 185. run_input は推論を終えたときにエイイチが y/n を打った判定なので人の確定に数える.
+     rule はエイイチの決めで機械的に付けた行: 送ったチャンク 0 → not_applicable, 素材が足りない → not_judgeable)
+  - 成功率は確定した回の success / (success + failure). not_applicable・not_judgeable・unknown は分母に入れない
   - 書く前に KIOXIA のマウントを確かめる. なければ止める (ローカルに逃がさない)
 元の記録 (runs/pi05_policy/ の中身) は読むだけ.
 """
@@ -24,9 +27,12 @@ VERDICTS_CSV = DATA_ROOT / "runs" / "pi05_policy_verdicts_v1.csv"
 COLUMNS = ["labeled_at", "run_stem", "pick", "place", "outcome", "labeler",
            "ai_outcome", "ai_reason", "evidence", "note"]
 PICK_PLACE = ("yes", "no", "unknown")
-OUTCOMES = ("success", "failure", "unknown", "not_judgeable")
-LABELERS = ("run_input", "ai", "human", "human_fixed_ai", "human_only")
+OUTCOMES = ("success", "failure", "unknown", "not_judgeable", "not_applicable")
+AI_OUTCOMES = ("success", "failure", "unknown", "not_judgeable")  # AI が付けてよい outcome (not_applicable は rule だけ)
+LABELERS = ("run_input", "ai", "human", "human_fixed_ai", "human_only", "rule")
 HUMAN_LABELERS = ("human", "human_fixed_ai", "human_only")
+CONFIRMED_LABELERS = ("run_input",) + HUMAN_LABELERS + ("rule",)  # 確定の扱い (依頼 185)
+RULE_NOTE = "エイイチの決め 2026-11-14 依頼185"
 EVIDENCES = ("top.mp4", "frames", "both", "")
 MAX_NOTE = 500
 MAX_REASON = 2000
@@ -164,6 +170,43 @@ def latest_by_stem(rows, labelers=None):
     return out
 
 
+def current_by_stem(rows):
+    """run_stem ごとの今の判定. 確定の行があればそのいちばん新しい行, なければいちばん新しい行 (AI など).
+    確定のあとに足された AI の行で未確定へ戻らない."""
+    out = latest_by_stem(rows)
+    out.update(latest_by_stem(rows, labelers=CONFIRMED_LABELERS))
+    return out
+
+
+def success_rate(rows):
+    """確定した回だけの成功率. 分母は success + failure (not_applicable・not_judgeable・unknown は入れない).
+    {"success", "failure", "denominator", "rate" (分母 0 なら None), "confirmed", "by_outcome"}."""
+    conf = latest_by_stem(rows, labelers=CONFIRMED_LABELERS)
+    by = {}
+    for r in conf.values():
+        by[r["outcome"]] = by.get(r["outcome"], 0) + 1
+    s, f = by.get("success", 0), by.get("failure", 0)
+    return {"success": s, "failure": f, "denominator": s + f, "rate": (s / (s + f)) if s + f else None,
+            "confirmed": len(conf), "by_outcome": by}
+
+
+def rule_row(run_stem, n_exec, ai_row):
+    """エイイチの決め (2026-11-14 依頼 185) に当たる回の labeler=rule の行. 当たらなければ None.
+    決め 2: 送ったチャンク 0 (アームを動かしていない) → not_applicable. 2 と 3 の両方に当たれば 2
+    決め 3: AI が frames/ だけで not_judgeable とした回・素材がなく API を呼ばなかった回 → not_judgeable"""
+    a = ai_row or {}
+    if n_exec == 0:
+        oc, note = "not_applicable", f"{RULE_NOTE} 決め2: 送ったチャンク 0 (アームを動かしていない・試行になっていない)"
+    elif a.get("outcome") == "not_judgeable" and a.get("evidence") in ("frames", ""):
+        src = "frames/ だけ" if a.get("evidence") == "frames" else "素材なし (API を呼んでいない)"
+        oc, note = "not_judgeable", f"{RULE_NOTE} 決め3: AI が not_judgeable ({src}). 人が見ずに確定"
+    else:
+        return None
+    return {"labeled_at": now_iso(), "run_stem": run_stem, "pick": "unknown", "place": "unknown",
+            "outcome": oc, "labeler": "rule", "ai_outcome": a.get("outcome", ""),
+            "ai_reason": a.get("ai_reason", ""), "evidence": a.get("evidence", ""), "note": note}
+
+
 def human_labeler_for(outcome, ai_row):
     """人が付けたときの labeler. AI の行がなければ human_only, 同じなら human, 違えば human_fixed_ai."""
     if not ai_row:
@@ -219,6 +262,7 @@ def read_log(run_dir):
 
 
 def executed_chunks(log):
+    """送ったチャンクの数: log.jsonl の chunk のある行のうち executed が True の行 (log.jsonl がなければ 0)."""
     return sum(1 for x in log if "chunk" in x and str(x.get("executed")) == "True")
```

報告の「決めてほしいこと」にあった1回（`pi05_20261031_185246`）は、アームを動かしていないのに記録したときの入力が成功になっていた回です。人の確定として残したまま、成功率の分子と分母に入っています。


## 依頼186〜191：判定の画面の見た目を、配膳ロボット ブラウザ版にそろえる

判定の画面は、サイトの [配膳ロボット ブラウザ版](https://pixelstomotors.com/sim/serving-robot-3d) にできるだけ合わせることにしました。色・字・ボタンの形を手本のページの CSS から写し、右に白い操作パネル、左に一覧を置く形です。


### 依頼186 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 60
---
# 依頼186：判定の画面（pi05/verdict_viewer）の見た目を、配膳ロボット ブラウザ版に合わせる

エイイチの指示（2026-11-14）：推論の記録の判定の画面のデザインを、なるべく https://pixelstomotors.com/sim/serving-robot-3d に合わせる。
変えるのは見た目（index.html の CSS と、必要なら要素の並び）だけ。判定の動き・キー・書き込み・数え方（依頼183・185）は変えない。依頼185 で入れたものも消さない。

## 手本
- 手本のページの CSS は curl https://pixelstomotors.com/sim/serving-robot-3d で取って、<style> の中を読む。値はそこから写す（自分で新しい色・大きさを決めない）
- 主なもの
  - 色：--ink #1d1d1b（字・選んだボタンの塗り）／--sub #6b6b66（小さい見出し・補足）／--line #d8d6d0（枠）／--bg #f2f1ee（下地）／パネルは白
  - 字：Noto Sans JP（400・600・700）、英数字と数字は Inter 600。Google Fonts の読み込みも手本と同じ
  - ボタン：白・1px の --line の枠・角丸 6px・padding 5px 9px。選んでいるものは --ink で塗って白い字（button.on と同じ）
  - 右の操作パネル：白・左に 1px の線・padding 16px・幅 320px（aside と同じ）。小さい見出しは 12px・--sub・太さ 600（h2 と同じ）
  - 数字：24px の Inter 600、単位は 12px で小さく、下に 11px の --sub の説明（.nums / .num と同じ 2 列）
  - 上に乗せる白い札：rgba(255,255,255,.92)・角丸 8px（#hud と同じ）
  - 暗い札：rgba(60,62,66,.86)・白い字・角丸 8px（#taskpanel と同じ）
  - 再生の帯（シークバー）：手本の #seek と同じ形（黒で済んだ所・つまみは白に黒い縁）

## 当てはめ方
- 右の操作パネル（aside の形）に上から：成功率と件数（.nums の形。成功率・確定した回・まだの回・成功・失敗）→ 判定する（y/n/u/x のボタン。pick/place は .seg の形のボタン）→ ひとこと → AI の判定（暗い札の形）→ この回の行
- 真ん中：動画（またはコマ送り）とグラフ。下地は --bg。上の左に回の名前・送ったチャンク・終わり方を白い札（#hud の形）で。回の名前は手本の時計（#clock）と同じ Inter 600 の大きめの字
- 左の一覧：白・右に 1px の線。選んでいる回は項目ごと --ink で塗って白い字にする（左に線だけ出す形はエイイチが嫌い。使わない）
- 成功/失敗の札：色の意味は 1 つだけにする。失敗だけを手本の「止まっている」と同じ赤 #d64545 で塗る。成功は白に --line の枠で色なし。AI だけ（未確定）は手本の待機中のロボットと同じ点線の枠（1px dashed #555）
- グラフの線の色（関節ごと）はデータの色なのでそのまま
- 角丸・枠・余白はこの画面の中で 1 種類にそろえる

## やらないこと
- 頼んでいない所の中身や並びを変えない。注記や飾りを足さない
- 青を既定の色にしない（手本で青はスタッフの印だけ）

## 確かめ
- 画面を立ち上げ直し（.command か、依頼184 と同じ立ち上げ方。8765 番で動いていれば止めてから）、直す前と直した後の画面の写しを撮って報告に添える
- 既存のテストが通ること
- 変えたファイルだけを指定して commit（git add . と git clean は使わない）
- 最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼186 で Claude Code が返した報告

```text
# 結果：20261114_186_判定の画面の見た目をブラウザ版のシミュレーションに合わせる

- 状態：完了
- 始めた時刻：2026-11-14 22:46
- 終わった時刻：2026-11-14 22:50（4分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 7de3aaa4-ea45-4560-8cf7-3109d6836f1b`

## Claude Code の報告

やったこと
- 手本のページ（pixelstomotors.com/sim/serving-robot-3d）を curl で取り、<style> の中の値をそのまま写しました。色、字（Noto Sans JP と Inter 600、Google Fonts の読み込みも手本と同じ）、ボタン、button.on、aside、h2、.nums/.num、#hud、#taskpanel、#seek です。
- 判定の画面を 3 列にしました。
  - 左の一覧：白で右に 1px の線。選んでいる回は項目ごと --ink で塗り、白い字にしました。
  - 真ん中：下地は --bg。上に白い札を置き、回の名前（Inter 600、28px）、送ったチャンク、終わり方を出しています。その下に映像とグラフです。コマ送りの帯は #seek と同じ形にしました（黒で済んだ所、つまみは白に黒い縁）。
  - 右の操作パネル（320px）：上から順に、成功率と件数、判定する、ひとこと、AI の判定、今の判定、この回の行です。
    - 成功率と件数は .nums の 2 列で、成功率・確定した回・まだの回・成功・失敗の 5 つです。
    - 判定するは y/n/u/x のボタンで、pick/place は .seg の形にしました。
    - AI の判定は暗い札にしました。
- 成功/失敗の札で色を付けたのは失敗だけです（#d64545 で塗る）。成功などは白に --line の枠、AI だけ（未確定）は 1px dashed #555 の枠にしました。青は既定の色に使っていません。
- 判定の動き、キー、書き込み、数え方（依頼183・185）は変えていません。JS で変えたのは見た目に必要な 3 か所だけです（成功率の数字の並べ方、帯の済んだ所の塗り、グラフの幅の取り方）。
- 8765 番で動いていたサーバーを止めて、立ち上げ直しました。.command はブラウザを開くので使わず、中と同じ立ち上げ方で開かずに起動しています。直す前と直した後の画面の写しは、ヘッドレスの Chrome で撮りました。

結果
- 既存のテスト test_verdicts は 39 件すべて通りました。
- 直した後の画面でスクリプトのエラーはありませんでした。404 が 1 件出ていますが、何のファイルかは確かめていません。
- 画面の写し：
  - 直す前：~/r2r2r-scripts/logs/req186/before.png
  - 直した後：~/r2r2r-scripts/logs/req186/after.png（まだ確定していない回）
  - 直した後：~/r2r2r-scripts/logs/req186/after_all_mp4.png（全部の一覧と、動画がある回）
- commit は 8f3dadf です。add したのは index.html だけです。

変えたファイル
- pi05/verdict_viewer/index.html

決めてほしいこと
- 角丸は 2 種類残っています。ボタン・入力欄・札は 6px、白い札と暗い札とグラフの枠は 8px で、どちらも手本の値どおりです。1 種類にそろえるなら、どちらに寄せるか決めてください。
- 動画の位置をグラフに示す縦線は、もとの色（関節 j0 と同じ青）のまま残しています。グラフの中のデータの色として扱いました。黒にするかどうか決めてください。

判定：止めた（決めてほしいことあり）
```

### 依頼186 のコードの差分（コミット 8f3dadf）

```diff
commit 8f3dadfc25149c6ffd79f18d3f2e85f6f0117a63
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 22:50:12 2026 +0900

    判定の画面の見た目を配膳ロボット ブラウザ版 (pixelstomotors.com/sim/serving-robot-3d) に合わせる (依頼 186). index.html の CSS と並びだけ変える. 色・字・ボタン・数字・札・帯は手本の CSS から写す (--ink #1d1d1b・--sub #6b6b66・--line #d8d6d0・--bg #f2f1ee, Noto Sans JP + Inter 600, Google Fonts の読み込みも同じ). 3 列にする: 左の一覧 (白・右に線. 選んだ回は --ink で塗って白い字) / 真ん中 (下地 --bg. 上に回の名前 (Inter 600 28px)・送ったチャンク・終わり方の白い札, 映像とコマ送りの帯 (#seek と同じ形), グラフ) / 右の操作パネル (aside の形 320px. 成功率と件数を .nums の 2 列 (成功率・確定した回・まだの回・成功・失敗) → 判定する (pick/place は .seg) → ひとこと → AI の判定 (暗い札) → 今の判定 → この回の行). 札は失敗だけ #d64545 で塗り, 成功ほかは白に --line の枠, AI だけ (未確定) は 1px dashed #555. 青は既定の色に使わない. 判定の動き・キー・書き込み・数え方 (依頼 183・185) は変えない (JS は成功率の出し方・帯の済んだ所・グラフの幅だけ). テスト test_verdicts 39 OK
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html | 204 +++++++++++++++++++++++------------------
 1 file changed, 115 insertions(+), 89 deletions(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index f9008e1..6d2b257 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -3,67 +3,89 @@
 <head>
 <meta charset="utf-8">
 <title>推論の記録の判定</title>
+<link rel="preconnect" href="https://fonts.googleapis.com">
+<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=Noto+Sans+JP:wght@400;600;700&display=swap" rel="stylesheet">
 <style>
+  /* 見た目は配膳ロボット ブラウザ版 (pixelstomotors.com/sim/serving-robot-3d) に合わせる (依頼 186) */
   :root {
-    --surface-1: #fcfcfb; --surface-2: #f3f2ee; --border: #dddcd5;
-    --text-primary: #1f1f1d; --text-secondary: #55554f; --text-muted: #8a8a82;
+    --ink: #1d1d1b; --sub: #6b6b66; --line: #d8d6d0; --bg: #f2f1ee; --stop: #d64545;
     --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100; --s5: #e87ba4; --s6: #008300;
-    --grip: #55554f;
-    --ok: #006300; --bad: #b42318; --warn: #8a5a00; --accent: #2a78d6;
+    --grip: #6b6b66;
   }
   * { box-sizing: border-box; }
-  body { margin: 0; font: 13px/1.5 -apple-system, "Hiragino Sans", sans-serif; color: var(--text-primary);
-         background: var(--surface-1); height: 100vh; display: flex; }
-  #side { width: 300px; border-right: 1px solid var(--border); display: flex; flex-direction: column; background: var(--surface-2); }
-  #side header { padding: 10px; border-bottom: 1px solid var(--border); }
-  #side h1 { font-size: 14px; margin: 0 0 6px; }
-  #filter { width: 100%; font-size: 13px; padding: 3px; }
-  #rate { margin-top: 6px; font-size: 13px; }
-  #rate b { font-size: 16px; }
-  #count { color: var(--text-secondary); margin-top: 4px; font-size: 12px; }
+  body { margin: 0; font-family: "Noto Sans JP", "Inter", system-ui, sans-serif; font-size: 13px; line-height: 1.5; color: var(--ink);
+         background: var(--bg); height: 100vh; display: grid; grid-template-columns: 280px 1fr 320px; }
+  /* 左の一覧 */
+  #side { min-height: 0; background: #fff; border-right: 1px solid var(--line); display: flex; flex-direction: column; }
+  #side header { padding: 16px; border-bottom: 1px solid var(--line); }
+  #side h1 { margin: 0 0 8px; font-size: 15px; }
+  #filter { width: 100%; font: inherit; border: 1px solid var(--line); background: #fff; border-radius: 6px; padding: 5px 6px; color: var(--ink); cursor: pointer; }
+  #count { color: var(--sub); margin-top: 6px; font-size: 11px; }
   #list { overflow-y: auto; flex: 1; }
-  .item { padding: 5px 10px; border-bottom: 1px solid var(--border); cursor: pointer; display: flex; justify-content: space-between; gap: 6px; }
-  .item:hover { background: #ebeae4; }
-  .item.sel { background: #dbe8f8; }
-  .item .stem { font-family: ui-monospace, Menlo, monospace; font-size: 12px; }
-  .item .sub { color: var(--text-muted); font-size: 11px; }
-  .tag { font-size: 11px; padding: 0 5px; border-radius: 3px; border: 1px solid var(--border); white-space: nowrap; align-self: center; }
-  .tag.success { color: var(--ok); border-color: var(--ok); }
-  .tag.failure { color: var(--bad); border-color: var(--bad); }
-  .tag.unknown, .tag.not_judgeable, .tag.not_applicable { color: var(--warn); border-color: var(--warn); }
-  .tag.ai { border-style: dashed; }
-  #main { flex: 1; overflow-y: auto; padding: 12px 16px; }
-  #title { font-family: ui-monospace, Menlo, monospace; font-size: 15px; font-weight: 600; }
-  #meta { color: var(--text-secondary); font-size: 12px; margin-bottom: 8px; }
-  #top { display: flex; gap: 16px; align-items: flex-start; }
-  #media { width: 640px; flex: none; }
-  #media video, #media img { width: 640px; background: #000; display: block; }
-  #framebar { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
-  #framebar input { flex: 1; }
-  #panel { flex: 1; min-width: 300px; }
-  .box { border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; margin-bottom: 10px; background: #fff; }
-  .box h3 { margin: 0 0 4px; font-size: 12px; color: var(--text-secondary); font-weight: 600; }
+  .item { padding: 6px 16px; border-bottom: 1px solid var(--line); cursor: pointer; display: flex; justify-content: space-between; gap: 6px; }
+  .item:hover { background: var(--bg); }
+  .item.sel { background: var(--ink); color: #fff; }
+  .item .stem { font: 600 13px/1.3 "Inter", "Noto Sans JP", system-ui, sans-serif; }
+  .item .sub { color: var(--sub); font-size: 11px; }
+  .item.sel .sub { color: rgba(255,255,255,.7); }
+  /* 成功/失敗の札: 色は失敗だけ. AI だけ (未確定) は点線の枠 */
+  .tag { flex: none; font: 600 11px/1 "Inter", "Noto Sans JP", system-ui, sans-serif; padding: 3px 6px; border-radius: 6px;
+         background: #fff; color: var(--ink); border: 1px solid var(--line); white-space: nowrap; align-self: center; }
+  .tag.failure { background: var(--stop); color: #fff; border-color: var(--stop); }
+  .tag.ai { border: 1px dashed #555; }
+  /* 真ん中 */
+  #main { min-width: 0; overflow-y: auto; padding: 14px 16px; }
+  #hud { display: inline-block; background: rgba(255,255,255,.92); padding: 10px 14px; border-radius: 8px; margin-bottom: 12px; }
+  #title { font: 600 28px/1 "Inter", "Noto Sans JP", system-ui, sans-serif; }
+  #meta { margin: 6px 0 0; font-size: 12px; color: var(--sub); }
+  #media { width: 640px; }
+  #media video, #media img { width: 640px; background: #000; display: block; border-radius: 8px; }
+  #framebar { display: flex; gap: 10px; align-items: center; margin-top: 8px; background: rgba(255,255,255,.92); padding: 8px 12px; border-radius: 8px; }
+  #fr { flex: 1; -webkit-appearance: none; appearance: none; height: 6px; border-radius: 3px;
+        background: linear-gradient(90deg, #1d1d1b var(--done, 0%), #d8d6d0 var(--done, 0%)); }
+  #fr::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 2px solid #1d1d1b; cursor: pointer; }
+  #fr::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: #fff; border: 2px solid #1d1d1b; }
+  #fl { font-size: 11px; color: var(--sub); white-space: nowrap; }
+  #media .muted { margin-top: 4px; }
+  /* 右の操作パネル */
+  #panel { min-height: 0; background: #fff; border-left: 1px solid var(--line); padding: 16px; overflow: auto; font-size: 13px; }
+  h2 { font-size: 12px; color: var(--sub); font-weight: 600; margin: 16px 0 6px; }
+  #panel > h2:first-child { margin-top: 0; }
+  .nums { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; margin-top: 4px; }
+  .num { line-height: 1.25; }
+  .num b { display: block; font: 600 24px/1.1 "Inter", "Noto Sans JP", system-ui, sans-serif; }
+  .num small { font-size: 12px; font-weight: 400; margin-left: 2px; }
+  .num > span { display: block; margin-top: 1px; line-height: 1.3; font-size: 11px; color: var(--sub); }
+  .note { margin: 6px 0 0; font-size: 11px; line-height: 1.6; color: var(--sub); }
+  .seg { display: flex; flex-wrap: wrap; gap: 4px; }
+  .row { display: flex; gap: 6px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
+  .row .lbl { width: 40px; color: var(--sub); font-size: 12px; font-weight: 600; }
+  button { font: inherit; border: 1px solid var(--line); background: #fff; border-radius: 6px; padding: 5px 9px; cursor: pointer; color: var(--ink); }
+  button.on { background: var(--ink); color: #fff; border-color: var(--ink); }
+  button.key { flex: 1 1 calc(50% - 3px); text-align: left; }
+  kbd { font: 600 11px/1 "Inter", system-ui, sans-serif; border: 1px solid var(--line); border-radius: 6px; padding: 2px 5px; background: var(--bg); color: var(--ink); }
+  #note { width: 100%; font: inherit; padding: 5px 6px; border: 1px solid var(--line); border-radius: 6px; color: var(--ink); }
+  #status { min-height: 1em; margin: 6px 0 0; font-size: 12px; color: var(--sub); }
+  #status.err { color: var(--stop); font-weight: 600; }
+  #status.ok { color: var(--ink); }
+  .dark { background: rgba(60,62,66,.86); color: #fff; border-radius: 8px; padding: 10px 12px; font-size: 12px; }
+  .dark .muted { color: #b9bcc1; }
   .big { font-size: 16px; font-weight: 600; }
-  .row { display: flex; gap: 6px; align-items: center; margin: 4px 0; flex-wrap: wrap; }
-  .row .lbl { width: 46px; color: var(--text-secondary); }
-  button { font: inherit; padding: 3px 9px; border: 1px solid var(--border); border-radius: 4px; background: #fff; cursor: pointer; }
-  button.on { background: var(--accent); color: #fff; border-color: var(--accent); }
-  button.key { min-width: 110px; }
-  kbd { font: 11px ui-monospace, Menlo, monospace; border: 1px solid var(--border); border-bottom-width: 2px; border-radius: 3px; padding: 0 4px; background: var(--surface-2); }
-  #note { width: 100%; padding: 4px; font: inherit; }
-  #status { min-height: 20px; margin: 4px 0; font-size: 12px; }
-  #status.err { color: var(--bad); font-weight: 600; }
-  #status.ok { color: var(--ok); }
-  #chart { margin-top: 10px; position: relative; }
-  #chart svg text { font-size: 11px; fill: var(--text-secondary); }
-  #legend { display: flex; gap: 12px; flex-wrap: wrap; font-size: 12px; color: var(--text-secondary); margin: 4px 0; }
+  /* グラフ */
+  #chart { margin-top: 12px; position: relative; background: #fff; border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }
+  #chart:empty { display: none; }
+  #chart svg text { font: 400 11px "Inter", "Noto Sans JP", system-ui, sans-serif; fill: var(--sub); }
+  #legend { display: flex; gap: 12px; flex-wrap: wrap; font-size: 12px; color: var(--sub); margin: 0 0 4px; }
   #legend span::before { content: ""; display: inline-block; width: 14px; height: 2px; vertical-align: middle; margin-right: 4px; background: var(--c); }
-  #tip { position: absolute; pointer-events: none; background: #fff; border: 1px solid var(--border); border-radius: 4px;
-         padding: 4px 6px; font-size: 11px; display: none; box-shadow: 0 1px 3px rgba(0,0,0,.12); white-space: nowrap; }
+  #tip { position: absolute; pointer-events: none; background: rgba(255,255,255,.92); border: 1px solid var(--line); border-radius: 6px;
+         padding: 4px 6px; font-size: 11px; display: none; white-space: nowrap; }
   #tip i { display: inline-block; width: 10px; height: 2px; vertical-align: middle; margin-right: 4px; }
   table.hist { border-collapse: collapse; font-size: 11px; width: 100%; }
-  table.hist td, table.hist th { border-bottom: 1px solid var(--border); padding: 2px 4px; text-align: left; vertical-align: top; }
-  .muted { color: var(--text-muted); }
+  table.hist td, table.hist th { border-bottom: 1px solid var(--line); padding: 4px 4px 4px 0; text-align: left; vertical-align: top; }
+  table.hist th { color: var(--sub); font-weight: 600; }
+  table.hist td:not(:first-child), table.hist th { white-space: nowrap; }
+  .muted { color: var(--sub); }
 </style>
 </head>
 <body>
@@ -76,41 +98,41 @@
       <option value="failure">失敗だけ (今の判定)</option>
       <option value="diff">AI と人が違う回</option>
     </select>
-    <div id="rate"></div>
     <div id="count"></div>
   </header>
   <div id="list"></div>
 </div>
 <div id="main">
-  <div id="title">—</div>
-  <div id="meta"></div>
-  <div id="top">
-    <div id="media"></div>
-    <div id="panel">
-      <div class="box">
-        <h3>判定する (キー)</h3>
-        <div class="row">
-          <button class="key" data-oc="success"><kbd>y</kbd> 成功</button>
-          <button class="key" data-oc="failure"><kbd>n</kbd> 失敗</button>
-          <button class="key" data-oc="unknown"><kbd>u</kbd> 分からない</button>
-          <button class="key" data-oc="not_judgeable"><kbd>x</kbd> 判定できない</button>
-        </div>
-        <div class="row"><span class="lbl">pick</span>
-          <button data-pp="pick" data-v="yes">yes</button><button data-pp="pick" data-v="no">no</button><button data-pp="pick" data-v="unknown">unknown</button>
-          <span class="muted">選ばなければ 成功→yes / ほか→unknown</span></div>
-        <div class="row"><span class="lbl">place</span>
-          <button data-pp="place" data-v="yes">yes</button><button data-pp="place" data-v="no">no</button><button data-pp="place" data-v="unknown">unknown</button></div>
-        <div class="row"><input id="note" placeholder="ひとこと (空でよい・入力中はキーで判定しない)"></div>
-        <div id="status"></div>
-        <div class="muted"><kbd>←</kbd> <kbd>→</kbd> 前後の回 ・ <kbd>,</kbd> <kbd>.</kbd> コマ送り / 動画は <kbd>space</kbd> で再生</div>
-      </div>
-      <div class="box"><h3>AI の判定 (未確定)</h3><div id="ai"></div></div>
-      <div class="box"><h3>今の判定 (いちばん新しい行)</h3><div id="cur"></div></div>
-      <div class="box"><h3>この回の行 (古い順)</h3><div id="hist"></div></div>
-    </div>
+  <div id="hud">
+    <div id="title">—</div>
+    <div id="meta"></div>
   </div>
+  <div id="media"></div>
   <div id="chart"></div>
 </div>
+<aside id="panel">
+  <h2>成功率 (確定した回だけ)</h2>
+  <div id="rate"></div>
+  <h2>判定する (キー)</h2>
+  <div class="row">
+    <button class="key" data-oc="success"><kbd>y</kbd> 成功</button>
+    <button class="key" data-oc="failure"><kbd>n</kbd> 失敗</button>
+    <button class="key" data-oc="unknown"><kbd>u</kbd> 分からない</button>
+    <button class="key" data-oc="not_judgeable"><kbd>x</kbd> 判定できない</button>
+  </div>
+  <div class="row"><span class="lbl">pick</span>
+    <div class="seg"><button data-pp="pick" data-v="yes">yes</button><button data-pp="pick" data-v="no">no</button><button data-pp="pick" data-v="unknown">unknown</button></div></div>
+  <div class="row"><span class="lbl">place</span>
+    <div class="seg"><button data-pp="place" data-v="yes">yes</button><button data-pp="place" data-v="no">no</button><button data-pp="place" data-v="unknown">unknown</button></div></div>
+  <p class="note">選ばなければ 成功→yes / ほか→unknown</p>
+  <h2>ひとこと</h2>
+  <input id="note" placeholder="ひとこと (空でよい・入力中はキーで判定しない)">
+  <div id="status"></div>
+  <p class="note"><kbd>←</kbd> <kbd>→</kbd> 前後の回 ・ <kbd>,</kbd> <kbd>.</kbd> コマ送り / 動画は <kbd>space</kbd> で再生</p>
+  <h2>AI の判定 (未確定)</h2><div id="ai" class="dark"></div>
+  <h2>今の判定 (いちばん新しい行)</h2><div id="cur"></div>
+  <h2>この回の行 (古い順)</h2><div id="hist"></div>
+</aside>
 <script>
 const OC_JA = {success: "成功", failure: "失敗", unknown: "分からない", not_judgeable: "判定できない", not_applicable: "試行でない", "": "なし"};
 const LB_JA = {run_input: "記録時の入力", ai: "AI", human: "人 (AI と同じ)", human_fixed_ai: "人 (AI を直した)", human_only: "人 (AI なし)", rule: "決め (依頼185)", "": ""};
@@ -140,16 +162,19 @@ function applyFilter() {
 function renderRate(st) {
   if (!st) { $("#rate").textContent = ""; return; }
   const b = st.by_outcome || {};
-  const pct = st.rate === null ? "—" : (st.rate * 100).toFixed(1) + "%";
-  $("#rate").innerHTML = `成功率 <b>${pct}</b> (成功 ${st.success} / (成功 ${st.success} + 失敗 ${st.failure}))`
-    + `<div class="muted">分母に入れない: 試行でない ${b.not_applicable || 0} ・ 判定できない ${b.not_judgeable || 0} ・ 分からない ${b.unknown || 0} (確定 ${st.confirmed} 回のうち)</div>`;
+  const num = (v, unit, label) => `<div class="num"><b>${v}${unit ? `<small>${unit}</small>` : ""}</b><span>${label}</span></div>`;
+  $("#rate").innerHTML = `<div class="nums">`
+    + num(st.rate === null ? "—" : (st.rate * 100).toFixed(1), st.rate === null ? "" : "%", "成功率 (成功 / (成功 + 失敗))")
+    + num(st.confirmed, "回", "確定した回") + num(runs.filter(r => !r.confirmed).length, "回", "まだの回")
+    + num(st.success, "回", "成功") + num(st.failure, "回", "失敗") + `</div>`
+    + `<p class="note">分母に入れない: 試行でない ${b.not_applicable || 0} ・ 判定できない ${b.not_judgeable || 0} ・ 分からない ${b.unknown || 0} (確定 ${st.confirmed} 回のうち)</p>`;
 }
 
 async function loadRuns() {
   const res = await fetch("/api/runs"); const j = await res.json();
   if (!res.ok || !Array.isArray(j.runs)) throw new Error(j.error || "一覧を読めません");  // 今の一覧は残す (codex 4 回目 R1)
   runs = j.runs;
-  renderRate(j.stats);
+  renderRate(j.stats);  // まだの回は runs から数えるので runs を入れてから
   applyFilter();
 }
 
@@ -197,13 +222,13 @@ function renderMedia() {
     $("#fr").oninput = e => { frameIdx = +e.target.value; showFrame(); };
     showFrame();
   } else {
-    m.innerHTML = `<div class="box">映像がありません (top.mp4 も frames/ もない)</div>`;
+    m.innerHTML = `<div class="muted">映像がありません (top.mp4 も frames/ もない)</div>`;
   }
 }
 function showFrame() {
   const n = detail.frames.length; frameIdx = Math.max(0, Math.min(n - 1, frameIdx));
   $("#frm").src = `/media/${detail.run_stem}/frames/${detail.frames[frameIdx]}`;
-  $("#fr").value = frameIdx; $("#fl").textContent = `${frameIdx + 1} / ${n}`;
+  $("#fr").value = frameIdx; $("#fr").style.setProperty("--done", (n > 1 ? frameIdx / (n - 1) * 100 : 100) + "%"); $("#fl").textContent = `${frameIdx + 1} / ${n}`;
 }
 function stepFrame(d) { if (detail && !detail.has_mp4 && detail.frames.length && $("#frm")) { frameIdx += d; showFrame(); } }
 
@@ -217,9 +242,10 @@ function renderInfo() {
 // ---- 関節と爪のグラフ (関節は 1 本の軸・爪は下に別の帯. 2 つの縦軸は使わない) ----
 let chartGeom = null;
 function renderChart() {
+  // 幅は #main から (空のときは #chart を隠すので. 余白 32・枠と内側 26. 依頼 186)
   const s = detail.states, el = $("#chart");
   if (!s.t.length) { el.innerHTML = `<div class="muted">関節の記録がありません (recording/states.csv も log.jsonl の state もない)</div>`; chartGeom = null; return; }
-  const W = Math.max(700, el.clientWidth || 900), H = 240, GH = 44, L = 44, R = 12, T = 8, gap = 22;
+  const W = Math.max(640, ($("#main").clientWidth || 900) - 58), H = 240, GH = 44, L = 44, R = 12, T = 8, gap = 22;
   const tmax = Math.max(s.t[s.t.length - 1], ...(s.grip.map(g => g[0]))) || 1;
   let lo = Infinity, hi = -Infinity;
   s.joints.forEach(js => js.forEach(v => { lo = Math.min(lo, v); hi = Math.max(hi, v); }));
@@ -230,14 +256,14 @@ function renderChart() {
   for (let v = Math.ceil(lo / step) * step; v <= hi; v += step) ticks.push(v);
   const tstep = niceStep(tmax / 8); const tt = []; for (let v = 0; v <= tmax; v += tstep) tt.push(v);
   let svg = `<svg width="${W}" height="${gy0 + GH + 20}" id="csvg">`;
-  ticks.forEach(v => svg += `<line x1="${L}" x2="${W - R}" y1="${y(v)}" y2="${y(v)}" stroke="#ecebe6"/><text x="${L - 6}" y="${y(v) + 4}" text-anchor="end">${+v.toFixed(1)}°</text>`);
+  ticks.forEach(v => svg += `<line x1="${L}" x2="${W - R}" y1="${y(v)}" y2="${y(v)}" stroke="#eeeeea"/><text x="${L - 6}" y="${y(v) + 4}" text-anchor="end">${+v.toFixed(1)}°</text>`);
   tt.forEach(v => svg += `<text x="${x(v)}" y="${gy0 + GH + 14}" text-anchor="middle">${+v.toFixed(0)}s</text>`);
-  s.stages.forEach(([t, st]) => svg += `<line x1="${x(t)}" x2="${x(t)}" y1="${T}" y2="${gy0 + GH}" stroke="#d6d5ce" stroke-dasharray="2,3"/>`);
+  s.stages.forEach(([t, st]) => svg += `<line x1="${x(t)}" x2="${x(t)}" y1="${T}" y2="${gy0 + GH}" stroke="#d8d6d0" stroke-dasharray="2,3"/>`);
   for (let j = 0; j < 6; j++) {
     const d = s.t.map((t, i) => `${i ? "L" : "M"}${x(t).toFixed(1)},${y(s.joints[i][j]).toFixed(1)}`).join("");
     svg += `<path d="${d}" fill="none" stroke="${COLORS[j]}" stroke-width="2" stroke-linejoin="round"/>`;
   }
-  svg += `<rect x="${L}" y="${gy0}" width="${W - L - R}" height="${GH}" fill="none" stroke="#ecebe6"/>`;
+  svg += `<rect x="${L}" y="${gy0}" width="${W - L - R}" height="${GH}" fill="none" stroke="#d8d6d0"/>`;
   svg += `<text x="${L - 6}" y="${gy(1) + 4}" text-anchor="end">閉</text><text x="${L - 6}" y="${gy(0) + 4}" text-anchor="end">開</text>`;
   if (s.grip.length) {
     let d = `M${x(0)},${gy(s.grip[0][1])}`, pv = s.grip[0][1];
@@ -245,7 +271,7 @@ function renderChart() {
     d += `L${x(tmax)},${gy(pv)}`;
     svg += `<path d="${d}" fill="none" stroke="var(--grip)" stroke-width="2"/>`;
   }
-  svg += `<line id="cx" x1="0" x2="0" y1="${T}" y2="${gy0 + GH}" stroke="#1f1f1d" stroke-width="1" style="display:none"/>`;
+  svg += `<line id="cx" x1="0" x2="0" y1="${T}" y2="${gy0 + GH}" stroke="#1d1d1b" stroke-width="1" style="display:none"/>`;
   svg += `<line id="vx" x1="0" x2="0" y1="${T}" y2="${gy0 + GH}" stroke="var(--s1)" stroke-width="1" style="display:none"/>`;
   svg += `<rect id="hit" x="${L}" y="0" width="${W - L - R}" height="${gy0 + GH}" fill="transparent"/></svg>`;
   el.innerHTML = `<div id="legend">${COLORS.map((c, j) => `<span style="--c:${c}">j${j}</span>`).join("")}<span style="--c:var(--grip)">爪 (下の帯・${esc(s.grip_label)})</span><span class="muted">${esc(s.source)}</span></div>${svg}<div id="tip"></div>`;
```

![手本に合わせたあとの判定の画面。左の一覧で選んでいる回は黒く塗られ、右に成功率と判定のボタンが並ぶ](https://pixelstomotors.com/media/LOG512_02_viewer_sim_style.png)

この依頼のあと、判定を付け始めてから、いくつか直しが続きました。直した順に書きます。

- 押した回が一覧から消え、← で戻っても見えなかった。押した判定は記録されていたが、絞り込みが「まだ確定していない回」なので見えなかった。自分が確定した回を見られる絞り込みと、直近5回の一覧を足した（依頼187）
- AI の失敗の赤い札に、AI だけを表す黒い点線の枠が重なっていた（依頼188）
- 成功は青か緑にしたい。手本にある青（スタッフに使っている #1761e6）にし、緑は手本にない色なので使わなかった。人が確定した札は塗り、AI だけの札は白地に同じ色の枠にした。判定のボタンも押すと色が付くようにした（依頼189）
- 依頼189 で、頼まれていない札の角丸まで手本の 9px に変えてしまった。6px に戻した（依頼191）
- 確定済みの回を開いても、記録した pick と place のボタンが塗られていなかった。値はファイルに入っていて、画面が出していなかっただけだった（依頼190）

依頼186 のあと、Claude（設計をしている側）は報告を読んだだけで、画面を手本と並べて見比べていませんでした。依頼189 の前に見比べると、札の形・右のパネルの並び（手本は操作が上、数字が下）・押したボタンの形の3つがずれていました。依頼189 からは、画面の写しを手本と並べて確かめてから知らせています。


### 依頼187 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 40
---
# 依頼187：判定の画面（pi05/verdict_viewer）で、エイイチが確定した回を見られるようにする

エイイチの指示（2026-11-14）：自分が確定した回を見られるようにしてほしい。今は、押すと「まだ確定していない回」の一覧から消えるので、← で戻っても押した回が出ず、記録されたのか分からない。
判定の書き込み・キー・数え方・見た目の決まり（依頼183・185・186）は変えない。足す部分の見た目は依頼186 で入れた手本の形（button・.seg・h2・#hud の白い札 など）だけを使う。

## やること
1. 左上の絞り込みに「自分が確定した回」を足す（labeler が human・human_fixed_ai・human_only の行がある回）。並びは確定した時刻が新しい順。一覧の各回に、人の判定（成功/失敗/分からない/判定できない）と確定した時刻（時:分）を出す
2. 右の操作パネルの「判定する」のすぐ下に「いま確定した回」を出す。直近 5 回ぶん（回の名前・人の判定・時:分）。押すとその回を開く（一覧の絞り込みはそのまま）
3. キーやボタンで確定したら、その場で「確定しました：回の名前・判定」を 3 秒ほど出す（#hud と同じ白い札。ダイアログは使わない）
4. 開いている回が人の確定済みなら、「今の判定」の所に、人が確定したことと時刻がはっきり分かるように出す（今の札の中で字を足すだけ。新しい色は足さない）
5. 確かめ：画面を立ち上げ直し（8765 番で動いていれば止めてから。ブラウザは開かない）、「自分が確定した回」の一覧と「いま確定した回」が出ている画面の写しを撮る。本物の判定ファイルには書かない（確かめの書き込みは /tmp の写しで）。既存のテストが通ること。index.html など変えたファイルだけを指定して commit（git add . と git clean は使わない）
6. 最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼187 で Claude Code が返した報告

```text
# 結果：20261114_187_判定の画面で自分が確定した回を見られるようにする

- 状態：完了
- 始めた時刻：2026-11-14 22:57
- 終わった時刻：2026-11-14 23:00（3分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 2d206a85-28fa-4f79-bba2-5d7075b77dae`

## Claude Code の報告

**やったこと**
- 左上の絞り込みに「自分が確定した回 (新しい順)」を足しました。対象は labeler が human・human_fixed_ai・human_only の行がある回です。並びは確定した時刻が新しい順で、各回に人の判定の札と「人が確定 時:分」を出します。
- 右の「判定する」のすぐ下に「いま確定した回 (新しい 5 回)」を足しました。回の名前・人の判定・時:分を出します。押すとその回が開き、一覧の絞り込みは変わりません。見た目は手本の button の形で、開いている回は `.on` の塗りです。
- キーやボタンで確定すると、画面の下に「確定しました：回の名前・判定」が 3 秒出ます。#hud と同じ白い札で、ダイアログは使っていません。
  - 初めは画面の上に出しましたが、回の名前に重なったので下に動かしました。
- 開いている回が人の確定済みなら、「今の判定」の札の中に「人が確定済み ・ 判定 ・ 日付 時:分」を太字で足しました。新しい色は足していません。
- 確定した時刻を画面に渡すため、`server.py` の一覧の答え (/api/runs) に `human_at` を 1 行だけ足しました。判定の書き込み・キー・数え方は変えていません。
- 確かめの手順:
  1. 8765 番で動いていた画面を止めました。
  2. 本物の判定ファイルを `/tmp/verdicts_187.csv` に写し、その写しに書く設定で立ち上げました。
  3. 見えないブラウザで u を 1 回押しました（写しにだけ 1 行足されます）。そのあと「自分が確定した回」に切り替え、「いま確定した回」の先頭を押しました。それぞれ画面の写しを撮りました。
  4. 終わってから、本物の判定ファイルで画面を立ち上げ直しました。8765 番・ブラウザは開かない形で、確かめる前と同じです。

**結果**
- 既存のテスト test_verdicts は 39 本すべて通りました。
- 札には「確定しました：pi05_20261017_172526・分からない」と出ました。
- 「自分が確定した回」は 7 回で、新しい順に並びました（22:59 → 22:55 → 22:51 …）。
- 「いま確定した回」に 5 回が出て、押すとその回が開きました。「今の判定」には「人が確定済み ・ 分からない ・ 2026-11-14 22:59」と出ました。
- 画面の動きで JavaScript のエラーは 0 件でした。
- 本物の判定ファイルは、確かめの前後で中身が同じでした（md5 で確かめました）。
- 画面の写しは `logs/shots_187/1_toast.png` と `logs/shots_187/2_mine.png` に置きました。
- commit は 867d4b7 で、`index.html` と `server.py` だけを指定して入れました。

**変えたファイル**
- `pi05/verdict_viewer/index.html`
- `pi05/verdict_viewer/server.py`
- 作業の記録として `logs/20261114_2300.md` と `logs/shots_187/`（どちらも commit していません）

**決めてほしいこと**
なし

判定：合格
```

### 依頼187 のコードの差分（コミット 867d4b7）

```diff
commit 867d4b773cc82b8ade85db8dc2eab5a0afa7ed72
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:00:06 2026 +0900

    判定の画面で自分が確定した回を見られるようにする (依頼 187). 絞り込みに「自分が確定した回 (新しい順)」を足す (labeler が human・human_fixed_ai・human_only の行がある回. 各回に人の判定と確定した時:分). 右の「判定する」の下に「いま確定した回」(新しい 5 回. 回の名前・人の判定・時:分. 押すとその回を開く・絞り込みはそのまま). 確定したら下に「確定しました：回の名前・判定」を 3 秒 (#hud と同じ白い札). 開いた回が人の確定済みなら「今の判定」に「人が確定済み・判定・日時」. server.py の /api/runs に human_at (人のいちばん新しい行の時刻) を足す. 判定の書き込み・キー・数え方は変えない. テスト test_verdicts 39 OK
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html | 35 ++++++++++++++++++++++++++++++++---
 pi05/verdict_viewer/server.py  |  1 +
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index 6d2b257..6df7deb 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -86,6 +86,11 @@
   table.hist th { color: var(--sub); font-weight: 600; }
   table.hist td:not(:first-child), table.hist th { white-space: nowrap; }
   .muted { color: var(--sub); }
+  /* 自分が確定した回 (依頼 187). 形は button と #hud の白い札だけ */
+  #recent button { display: flex; width: 100%; justify-content: space-between; gap: 6px; margin-top: 4px; text-align: left; }
+  #recent .stem { font: 600 12px/1.3 "Inter", "Noto Sans JP", system-ui, sans-serif; }
+  #toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: rgba(255,255,255,.92); padding: 10px 14px;
+           border-radius: 8px; font-weight: 600; display: none; z-index: 10; }
 </style>
 </head>
 <body>
@@ -97,6 +102,7 @@
       <option value="all">全部</option>
       <option value="failure">失敗だけ (今の判定)</option>
       <option value="diff">AI と人が違う回</option>
+      <option value="mine">自分が確定した回 (新しい順)</option>
     </select>
     <div id="count"></div>
   </header>
@@ -110,6 +116,7 @@
   <div id="media"></div>
   <div id="chart"></div>
 </div>
+<div id="toast"></div>
 <aside id="panel">
   <h2>成功率 (確定した回だけ)</h2>
   <div id="rate"></div>
@@ -125,6 +132,7 @@
   <div class="row"><span class="lbl">place</span>
     <div class="seg"><button data-pp="place" data-v="yes">yes</button><button data-pp="place" data-v="no">no</button><button data-pp="place" data-v="unknown">unknown</button></div></div>
   <p class="note">選ばなければ 成功→yes / ほか→unknown</p>
+  <h2>いま確定した回 (新しい 5 回)</h2><div id="recent"></div>
   <h2>ひとこと</h2>
   <input id="note" placeholder="ひとこと (空でよい・入力中はキーで判定しない)">
   <div id="status"></div>
@@ -144,18 +152,36 @@ let runs = [], view = [], cur = null, detail = null, pp = {pick: null, place: nu
 const $ = s => document.querySelector(s);
 const esc = s => String(s ?? "").replace(/[&<>"]/g, c => ({"&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;"}[c]));
 function status(msg, kind) { const el = $("#status"); el.textContent = msg; el.className = kind || ""; }
+const HUMAN = ["human", "human_fixed_ai", "human_only"];  // 人が確定した行 (依頼 187)
+const hm = iso => String(iso || "").slice(11, 16);  // 時:分 (記録した側の時刻のまま)
+const byHumanAt = (a, b) => Date.parse(b.human_at) - Date.parse(a.human_at);
+let toastTimer = null;
+function toast(msg) { const el = $("#toast"); el.textContent = msg; el.style.display = "block"; clearTimeout(toastTimer); toastTimer = setTimeout(() => el.style.display = "none", 3000); }
 function tag(oc, ai) { return oc ? `<span class="tag ${oc} ${ai ? "ai" : ""}">${ai ? "AI " : ""}${OC_JA[oc]}</span>` : `<span class="tag">印なし</span>`; }
 
 function applyFilter() {
   const f = $("#filter").value;
   view = runs.filter(r => f === "all" ? true : f === "todo" ? !r.confirmed : f === "failure" ? r.outcome === "failure"
+                          : f === "mine" ? !!r.human_at
                           : (r.ai_outcome && r.human_outcome && r.ai_outcome !== r.human_outcome));
+  if (f === "mine") view.sort(byHumanAt);  // 確定した時刻が新しい順 (依頼 187)
   $("#count").textContent = `${view.length} 回 / 全 ${runs.length} 回 (確定済み ${runs.filter(r => r.confirmed).length})`;
   $("#list").innerHTML = view.map(r => `<div class="item ${cur === r.run_stem ? "sel" : ""}" data-stem="${r.run_stem}">
       <div><div class="stem">${r.run_stem.replace("pi05_", "")}</div>
-      <div class="sub">${r.has_mp4 ? "top.mp4" : r.n_frames ? "frames " + r.n_frames : "素材なし"} ・ ${LB_JA[r.labeler] || "—"}</div></div>
-      ${tag(r.outcome, r.labeler === "ai")}</div>`).join("");
+      <div class="sub">${f === "mine" ? `人が確定 ${hm(r.human_at)} ・ ${LB_JA[r.labeler] || "—"}`
+        : `${r.has_mp4 ? "top.mp4" : r.n_frames ? "frames " + r.n_frames : "素材なし"} ・ ${LB_JA[r.labeler] || "—"}`}</div></div>
+      ${f === "mine" ? tag(r.human_outcome, false) : tag(r.outcome, r.labeler === "ai")}</div>`).join("");
   document.querySelectorAll(".item").forEach(el => el.onclick = () => select(el.dataset.stem));
+  renderRecent();
+}
+
+// いま確定した回: 人の行がある回を確定した時刻の新しい順に 5 回. 押すと開く (絞り込みはそのまま. 依頼 187)
+function renderRecent() {
+  const rec = runs.filter(r => r.human_at).sort(byHumanAt).slice(0, 5);
+  $("#recent").innerHTML = rec.length ? rec.map(r => `<button class="${cur === r.run_stem ? "on" : ""}" data-recent="${r.run_stem}">
+      <span class="stem">${r.run_stem.replace("pi05_", "")}</span><span>${OC_JA[r.human_outcome]} ・ ${hm(r.human_at)}</span></button>`).join("")
+    : `<span class="muted">まだありません</span>`;
+  document.querySelectorAll("[data-recent]").forEach(b => b.onclick = () => { b.blur(); status(""); select(b.dataset.recent); });
 }
 
 // 成功率は確定した回だけ. 分母は 成功 + 失敗 (試行でない・判定できない・分からない は入れない. 依頼 185)
@@ -235,7 +261,9 @@ function stepFrame(d) { if (detail && !detail.has_mp4 && detail.frames.length &&
 function renderInfo() {
   const a = detail.ai, l = detail.latest;
   $("#ai").innerHTML = a ? `<div class="big">${OC_JA[a.outcome]}</div><div>pick ${a.pick} / place ${a.place} ・ 素材 ${a.evidence || "なし"}</div><div class="muted">${esc(a.ai_reason)}</div>` : `<span class="muted">AI の判定はありません</span>`;
-  $("#cur").innerHTML = l ? `<div class="big">${OC_JA[l.outcome]} <span class="muted" style="font-size:12px">${LB_JA[l.labeler]}</span></div><div>pick ${l.pick} / place ${l.place} ・ ${esc(l.labeled_at)}</div>${l.note ? `<div class="muted">${esc(l.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
+  const h = detail.history.filter(r => HUMAN.includes(r.labeler)).pop();  // 人が確定した行 (依頼 187)
+  const hl = h ? `<div><b>人が確定済み</b> ・ ${OC_JA[h.outcome]} ・ ${esc(h.labeled_at.slice(0, 10))} ${hm(h.labeled_at)}</div>` : "";
+  $("#cur").innerHTML = l ? `<div class="big">${OC_JA[l.outcome]} <span class="muted" style="font-size:12px">${LB_JA[l.labeler]}</span></div>${hl}<div>pick ${l.pick} / place ${l.place} ・ ${esc(l.labeled_at)}</div>${l.note ? `<div class="muted">${esc(l.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
   $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>pick/place</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${OC_JA[r.outcome]}</td><td>${r.pick}/${r.place}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
 }
 
@@ -324,6 +352,7 @@ async function save(outcome) {
     const j = await res.json();
     if (!res.ok) { delete pendingOps[stem]; status("書けませんでした: " + j.error, "err"); return; }
     saved = true;
+    toast(`確定しました：${stem}・${OC_JA[outcome]}`);
     status(`${stem} を「${OC_JA[outcome]}」で追記しました (${LB_JA[j.row.labeler]}・pick ${j.row.pick} / place ${j.row.place})`, "ok");
     await loadRuns();
     // 同じ位置 (確定で一覧から消えたらそこに来た次の回) へ進む
diff --git a/pi05/verdict_viewer/server.py b/pi05/verdict_viewer/server.py
index 79e8055..843c87a 100644
--- a/pi05/verdict_viewer/server.py
+++ b/pi05/verdict_viewer/server.py
@@ -124,6 +124,7 @@ class App:
                 "labeler": lt["labeler"] if lt else "",
                 "ai_outcome": a["outcome"] if a else "",
                 "human_outcome": h["outcome"] if h else "",
+                "human_at": h["labeled_at"] if h else "",  # 人が確定した時刻 (自分が確定した回の一覧. 依頼 187)
                 "confirmed": bool(lt and lt["labeler"] in V.CONFIRMED_LABELERS),
             })
         return out
```


### 依頼188 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 15
---
# 依頼188：判定の画面の「AI 失敗」の赤い札から黒い点線の枠をなくす

エイイチの指示（2026-11-14）：赤い札に黒い枠線を付けない。
pi05/verdict_viewer/index.html の 36 行目 `.tag.ai { border: 1px dashed #555; }` が、赤く塗った失敗の札（.tag.failure）にも黒い点線を付けている。

## やること
1. `.tag.ai` の行のすぐ下に `.tag.ai.failure { border-color: var(--stop); }` を 1 行足す（赤い札は枠も赤になり、黒い線が見えなくなる）。AI 成功など白い札の点線の枠はそのまま。ほかは変えない
2. 8765 番の画面を立ち上げ直す（ブラウザは開かない）。左の一覧に「AI 失敗」と「AI 成功」が並ぶ所の画面の写しを撮る
3. index.html だけを指定して commit（git add . と git clean は使わない）
4. 最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼188 で Claude Code が返した報告

```text
# 結果：20261114_188_失敗の札の黒い点線の枠をやめる

- 状態：完了
- 始めた時刻：2026-11-14 23:02
- 終わった時刻：2026-11-14 23:04（1分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume d4fe6b1f-b74e-4ca5-8cad-ce3cc162808c`

## Claude Code の報告

**やったこと**
- `pi05/verdict_viewer/index.html:37` の `.tag.ai` の行のすぐ下に、`.tag.ai.failure { border-color: var(--stop); }` を 1 行足しました。ほかは変えていません。
- 8765 番で動いていた画面を止めて、`--no-open` で立ち上げ直しました。ブラウザは開いていません。
- ブラウザを画面に出さずに読み込み、左の一覧で「AI 失敗」と「AI 成功」が並ぶ所の写しを撮りました。
- `index.html` だけを指定して commit しました（955c914）。

**結果**
- 「AI 失敗」の札：枠の色は `rgb(214, 69, 69)`（塗りと同じ赤）です。点線はありますが同じ赤なので見えず、黒い線もなくなりました。
- 「AI 成功」の札：枠の色は `rgb(85, 85, 85)` の点線のままです。
- 写しを見て、赤い札に黒い枠がないこと、白い札の点線が残っていることを確かめました。
- 写しの置き場所：
  - `claude_code_reports/188_ai_tag_border_zoom.png`（一覧の拡大。AI 失敗 4 件と AI 成功 3 件が並ぶ所）
  - `claude_code_reports/188_ai_tag_border.png`（画面全体）

**変えたファイル**
- `pi05/verdict_viewer/index.html`（1 行足しただけ）
- 写し 2 枚は commit していません。

**決めてほしいこと**
なし

判定：合格
```

### 依頼188 のコードの差分（コミット 955c914）

```diff
commit 955c914379608cd9fa110d5c09cb18b37288797b
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:03:54 2026 +0900

    判定の画面の「AI 失敗」の赤い札から黒い点線の枠をなくす (依頼 188). index.html の .tag.ai の下に .tag.ai.failure { border-color: var(--stop); } を 1 行足す (赤い札は枠も赤). AI 成功など白い札の点線の枠はそのまま
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index 6df7deb..8a80ae4 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -34,6 +34,7 @@
          background: #fff; color: var(--ink); border: 1px solid var(--line); white-space: nowrap; align-self: center; }
   .tag.failure { background: var(--stop); color: #fff; border-color: var(--stop); }
   .tag.ai { border: 1px dashed #555; }
+  .tag.ai.failure { border-color: var(--stop); }
   /* 真ん中 */
   #main { min-width: 0; overflow-y: auto; padding: 14px 16px; }
   #hud { display: inline-block; background: rgba(255,255,255,.92); padding: 10px 14px; border-radius: 8px; margin-bottom: 12px; }
```


### 依頼189 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 40
---
# 依頼189：判定の画面の札とボタンを手本（配膳ロボット ブラウザ版）に合わせ、成功を青にする

エイイチの指示（2026-11-14）：成功は青か緑にする／赤い札に黒い枠線を付けない／判定するのボタンを押したら色が変わってほしい／デザインは手本に合わせると言ったはず。
手本は https://pixelstomotors.com/sim/serving-robot-3d（curl で取って <style> を読む）。判定の書き込み・キー・数え方は変えない。

## 色の決まり（この画面の中で 1 つに統一する）
- 成功＝青 #1761e6（手本でスタッフに使っている青。新しい色は作らない）／失敗＝赤 #d64545（手本の止まっている）
- 分からない・判定できない・試行でない＝色なし（白に --line の枠、字は --ink）
- 人が確定した判定は「塗り」（青や赤の地に白い字）、AI だけ（未確定）は「白地に同じ色の 1px の実線の枠と同じ色の字」。点線と黒い枠はどこにも使わない
- 緑は使わない（手本にない色のため）

## やること
1. 札（一覧・いま確定した回・今の判定・この回の行・確定しましたの知らせ に出る判定の印）を、全部手本の .tag と同じ形にそろえる：角丸 9px・font 600 11px/18px Inter と Noto Sans JP・左右の余白 7px。色は上の決まり。いま確定した回と知らせの判定の言葉も、この札にする
2. 判定するのボタン（y 成功・n 失敗・u 分からない・x 判定できない）
   - 開いている回に人の確定があれば、その判定のボタンを塗った形で出す（成功は青、失敗は赤、ほかは --ink。手本の button.on と同じ形）
   - 押したら（キーでもクリックでも）そのボタンをすぐ塗り、0.4 秒見せてから次の回へ進む（その間の 2 回目の押しは今までどおり書かない）
3. pick / place のボタンは、選んでいるものを手本の button.on（--ink の塗りに白い字）にする
4. 右の操作パネルの並びを手本と同じ「操作が上・数字が下」にする：判定する → pick/place → いま確定した回 → ひとこと → AI の判定 → 今の判定 → 成功率と件数（いまの数字の形）→ この回の行。中身は変えない
5. 確かめ：画面を立ち上げ直し（8765 番。ブラウザは開かない）、次の画面の写しを撮って報告に添える。(a) 左の一覧で AI 成功・AI 失敗・人の成功・人の失敗が並ぶ所 (b) 人が成功で確定した回を開いて成功のボタンが青く塗られている所 (c) 押した直後に塗られた所。確かめの書き込みは /tmp の写しで（本物の判定ファイルに書かない）。既存のテストが通ること
6. 手本と比べて、まだ違う所が残っていれば報告に並べる（直さずに書く）
7. 変えたファイルだけを指定して commit（git add . と git clean は使わない）。最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼189 で Claude Code が返した報告

```text
# 結果：20261114_189_判定の画面の札とボタンを手本に合わせ成功を青にする

- 状態：完了
- 始めた時刻：2026-11-14 23:05
- 終わった時刻：2026-11-14 23:08（3分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 56c52740-2ec7-4b3a-a357-fab71c38aed3`

## Claude Code の報告

**やったこと**
- 手本の画面（pixelstomotors.com/sim/serving-robot-3d）の `<style>` を取り込み、それに合わせて判定の画面（`pi05/verdict_viewer/index.html`）だけを直しました。判定の書き込み・キー・数え方は変えていません。
- 色の決まり：成功は青 #1761e6（手本でスタッフに使っている青）、失敗は赤 #d64545、ほかは白地に --line の枠です。
  - 人の確定は塗り、AI だけ（未確定）は白地に同じ色の 1px の実線の枠と字にしました。
  - 点線・黒い枠・緑はどこにも残っていません。
- 札：手本の .tag の形（角丸 9px・600 11px/18px・左右の余白 7px）にそろえました。出る場所は、一覧・いま確定した回・今の判定・この回の行・確定しましたの知らせです。いま確定した回と知らせの判定の言葉も札にしました。
- 判定するのボタン
  - 開いた回に人の確定があれば、その判定のボタンを塗ります（成功は青・失敗は赤・ほかは --ink）。
  - 押したら（キーでもクリックでも）すぐ塗り、0.4 秒見せてから次の回へ進みます。
- pick / place のボタン：選んでいるものは前から手本の button.on（--ink の塗りに白い字）になっていたので、手を入れていません。画面で確かめただけです。
- 右の操作パネルの並び：判定する → pick/place → いま確定した回 → ひとこと → AI の判定 → 今の判定 → 成功率と件数 → この回の行。中身は変えていません。

**結果**
- 既存のテスト test_verdicts は 39 件すべて通りました。
- 8765 番で画面を立ち上げ直し（ブラウザは開かない）、判定ファイルの写し（/tmp/verdicts_189.csv）に書く形で確かめました。
  - (b) 人が成功で確定した回を開くと、成功のボタンが青（rgb 23,97,230）で塗られていました。
  - (c) n を押した直後に失敗のボタンが赤（rgb 214,69,69）で塗られ、そのあと次の回へ進みました。
  - 0.4 秒の間に 2 回目の n を押しても、写しに増えた行は 1 行（276 → 277 行）だけでした。
  - 本物の判定ファイルには、確かめで判定した回（pi05_20261017_172526）の人の行はありません。
- 確かめのあと、8765 番を本物の判定ファイルで立ち上げ直しました。
- 画面の写しは `claude_code_reports/189/` に置きました。
  - a_list.png：一覧
  - b_human_success.png：人が成功で確定した回
  - c_pressed.png：押した直後
  - c_after_toast.png：次の回へ進んだあと
  - d_pickplace.png：pick/place の塗り
- (a) の 4 種類は、1 枚の写しにはそろいませんでした。
  - a_list.png に写っているのは、人の成功・人の失敗・AI 失敗です。
  - AI 成功は、b_human_success.png と c_pressed.png の一覧に写っています。
- 手本と比べて、まだ違う所（直していません）
  1. 手本の .tag には枠がありません。この画面の札は枠を付けるため、内側に 1px の線を引いて高さを 18px に保っています。
  2. 人の確定と、記録時の入力・決め（依頼185）の確定は、どちらも同じ塗りで出るので見分けられません。
  3. 判定するのボタンの中のキーの印（kbd）は、塗ったボタンの上でも薄い地のままです。手本には同じ部品がありません。
  4. 関節グラフの j0 と動画の位置を示す縦線は、前からの青 #2a78d6 のままです。今回の範囲の外なので変えていません。
  5. 右のパネルで「AI の判定」の大きな字は札にしていません（依頼の対象一覧に入っていないため）。
- 作業の記録を `logs/20261114_2308.md` に書きました。

**変えたファイル**
- `pi05/verdict_viewer/index.html`（commit eccbc6b。このファイルだけを指定して add しました）
- commit していないもの：`logs/20261114_2308.md`、`claude_code_reports/189/` の写し 5 枚

**決めてほしいこと**
- 人の確定と、記録時の入力・決めの確定を、札で見分けられるようにするかどうか。いまはどちらも同じ塗りです。
- 確かめのため、もとから 8765 番で動いていた画面（本物の判定ファイルにつながっていたもの）を止めました。止める直前の 23:07:15 に、本物の判定ファイルへ pi05_20261029_121202 の人の行（成功）が 1 行書かれています。私の確かめの書き込みではありません。エイイチがその時に画面を使っていたなら、念のため画面を開き直して確かめてください。

判定：合格
```

### 依頼189 のコードの差分（コミット eccbc6b）

```diff
commit eccbc6b2c8b8e85b55279f1a4a3b81907964b232
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:08:19 2026 +0900

    判定の画面の札とボタンを手本に合わせ成功を青にする (依頼 189). index.html だけ. 成功 #1761e6 (手本のスタッフ)・失敗 #d64545・ほかは白に --line の枠. 人の確定は塗り, AI だけは白地に同じ色の 1px 実線の枠と字 (点線と黒い枠をなくす・緑は使わない). 札は手本の .tag の形 (角丸 9px・600 11px/18px・左右 7px) で一覧・いま確定した回・今の判定・この回の行・確定しましたの知らせにそろえる. 判定するのボタンは人の確定を塗り (成功は青・失敗は赤・ほかは --ink), 押したらすぐ塗って 0.4 秒見せてから次の回へ (その間は busy のまま 2 回目は書かない). 右の並びを操作が上・数字が下に (判定する → pick/place → いま確定した回 → ひとこと → AI → 今の判定 → 成功率 → この回の行). 書き込み・キー・数え方は変えない. テスト test_verdicts 39 OK
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html | 53 ++++++++++++++++++++++++++++--------------
 1 file changed, 35 insertions(+), 18 deletions(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index 8a80ae4..b8a1443 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -9,7 +9,7 @@
 <style>
   /* 見た目は配膳ロボット ブラウザ版 (pixelstomotors.com/sim/serving-robot-3d) に合わせる (依頼 186) */
   :root {
-    --ink: #1d1d1b; --sub: #6b6b66; --line: #d8d6d0; --bg: #f2f1ee; --stop: #d64545;
+    --ink: #1d1d1b; --sub: #6b6b66; --line: #d8d6d0; --bg: #f2f1ee; --stop: #d64545; --ok: #1761e6;
     --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100; --s5: #e87ba4; --s6: #008300;
     --grip: #6b6b66;
   }
@@ -29,12 +29,15 @@
   .item .stem { font: 600 13px/1.3 "Inter", "Noto Sans JP", system-ui, sans-serif; }
   .item .sub { color: var(--sub); font-size: 11px; }
   .item.sel .sub { color: rgba(255,255,255,.7); }
-  /* 成功/失敗の札: 色は失敗だけ. AI だけ (未確定) は点線の枠 */
-  .tag { flex: none; font: 600 11px/1 "Inter", "Noto Sans JP", system-ui, sans-serif; padding: 3px 6px; border-radius: 6px;
-         background: #fff; color: var(--ink); border: 1px solid var(--line); white-space: nowrap; align-self: center; }
-  .tag.failure { background: var(--stop); color: #fff; border-color: var(--stop); }
-  .tag.ai { border: 1px dashed #555; }
-  .tag.ai.failure { border-color: var(--stop); }
+  /* 判定の札: 形は手本の .tag. 成功は青 (手本のスタッフ)・失敗は赤 (手本の止まっている)・ほかは色なし.
+     人が確定 (と記録時の入力・決め) は塗り, AI だけ (未確定) は白地に同じ色の 1px の枠と字 (依頼 189).
+     枠は高さを変えないよう内側の線で引く */
+  .tag { flex: none; min-width: 24px; text-align: center; font: 600 11px/18px "Inter", "Noto Sans JP", system-ui, sans-serif; border-radius: 9px;
+         padding: 0 7px; background: #fff; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); white-space: nowrap; align-self: center; display: inline-block; }
+  .tag.success { background: var(--ok); color: #fff; box-shadow: inset 0 0 0 1px var(--ok); }
+  .tag.failure { background: var(--stop); color: #fff; box-shadow: inset 0 0 0 1px var(--stop); }
+  .tag.ai.success { background: #fff; color: var(--ok); }
+  .tag.ai.failure { background: #fff; color: var(--stop); }
   /* 真ん中 */
   #main { min-width: 0; overflow-y: auto; padding: 14px 16px; }
   #hud { display: inline-block; background: rgba(255,255,255,.92); padding: 10px 14px; border-radius: 8px; margin-bottom: 12px; }
@@ -65,6 +68,9 @@
   button { font: inherit; border: 1px solid var(--line); background: #fff; border-radius: 6px; padding: 5px 9px; cursor: pointer; color: var(--ink); }
   button.on { background: var(--ink); color: #fff; border-color: var(--ink); }
   button.key { flex: 1 1 calc(50% - 3px); text-align: left; }
+  /* 判定するのボタン: 人の確定と押した判定を塗る. 成功は青・失敗は赤・ほかは --ink (依頼 189) */
+  button.key.on[data-oc="success"] { background: var(--ok); border-color: var(--ok); }
+  button.key.on[data-oc="failure"] { background: var(--stop); border-color: var(--stop); }
   kbd { font: 600 11px/1 "Inter", system-ui, sans-serif; border: 1px solid var(--line); border-radius: 6px; padding: 2px 5px; background: var(--bg); color: var(--ink); }
   #note { width: 100%; font: inherit; padding: 5px 6px; border: 1px solid var(--line); border-radius: 6px; color: var(--ink); }
   #status { min-height: 1em; margin: 6px 0 0; font-size: 12px; color: var(--sub); }
@@ -90,8 +96,11 @@
   /* 自分が確定した回 (依頼 187). 形は button と #hud の白い札だけ */
   #recent button { display: flex; width: 100%; justify-content: space-between; gap: 6px; margin-top: 4px; text-align: left; }
   #recent .stem { font: 600 12px/1.3 "Inter", "Noto Sans JP", system-ui, sans-serif; }
+  #recent button .tag { margin-right: 4px; }
   #toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: rgba(255,255,255,.92); padding: 10px 14px;
            border-radius: 8px; font-weight: 600; display: none; z-index: 10; }
+  #toast .tag { margin-left: 4px; }
+  #cur .tag { vertical-align: 2px; }
 </style>
 </head>
 <body>
@@ -119,8 +128,6 @@
 </div>
 <div id="toast"></div>
 <aside id="panel">
-  <h2>成功率 (確定した回だけ)</h2>
-  <div id="rate"></div>
   <h2>判定する (キー)</h2>
   <div class="row">
     <button class="key" data-oc="success"><kbd>y</kbd> 成功</button>
@@ -140,6 +147,8 @@
   <p class="note"><kbd>←</kbd> <kbd>→</kbd> 前後の回 ・ <kbd>,</kbd> <kbd>.</kbd> コマ送り / 動画は <kbd>space</kbd> で再生</p>
   <h2>AI の判定 (未確定)</h2><div id="ai" class="dark"></div>
   <h2>今の判定 (いちばん新しい行)</h2><div id="cur"></div>
+  <h2>成功率 (確定した回だけ)</h2>
+  <div id="rate"></div>
   <h2>この回の行 (古い順)</h2><div id="hist"></div>
 </aside>
 <script>
@@ -157,7 +166,7 @@ const HUMAN = ["human", "human_fixed_ai", "human_only"];  // 人が確定した
 const hm = iso => String(iso || "").slice(11, 16);  // 時:分 (記録した側の時刻のまま)
 const byHumanAt = (a, b) => Date.parse(b.human_at) - Date.parse(a.human_at);
 let toastTimer = null;
-function toast(msg) { const el = $("#toast"); el.textContent = msg; el.style.display = "block"; clearTimeout(toastTimer); toastTimer = setTimeout(() => el.style.display = "none", 3000); }
+function toast(html) { const el = $("#toast"); el.innerHTML = html; el.style.display = "block"; clearTimeout(toastTimer); toastTimer = setTimeout(() => el.style.display = "none", 3000); }
 function tag(oc, ai) { return oc ? `<span class="tag ${oc} ${ai ? "ai" : ""}">${ai ? "AI " : ""}${OC_JA[oc]}</span>` : `<span class="tag">印なし</span>`; }
 
 function applyFilter() {
@@ -180,7 +189,7 @@ function applyFilter() {
 function renderRecent() {
   const rec = runs.filter(r => r.human_at).sort(byHumanAt).slice(0, 5);
   $("#recent").innerHTML = rec.length ? rec.map(r => `<button class="${cur === r.run_stem ? "on" : ""}" data-recent="${r.run_stem}">
-      <span class="stem">${r.run_stem.replace("pi05_", "")}</span><span>${OC_JA[r.human_outcome]} ・ ${hm(r.human_at)}</span></button>`).join("")
+      <span class="stem">${r.run_stem.replace("pi05_", "")}</span><span>${tag(r.human_outcome, false)}${hm(r.human_at)}</span></button>`).join("")
     : `<span class="muted">まだありません</span>`;
   document.querySelectorAll("[data-recent]").forEach(b => b.onclick = () => { b.blur(); status(""); select(b.dataset.recent); });
 }
@@ -208,7 +217,7 @@ async function loadRuns() {
 async function select(stem) {
   const seq = ++selSeq;  // いちばん新しい選択の応答だけ使う (codex 5 回目 R2・6 回目 R3)
   if (!stem) {  // 空の一覧: 前の回の表示と状態を残さない (codex 7 回目 R1)
-    cur = null; detail = null; chartGeom = null; loading = false; pp = {pick: null, place: null}; markPP(); $("#note").value = "";
+    cur = null; detail = null; chartGeom = null; loading = false; pp = {pick: null, place: null}; markPP(); markOC(null); $("#note").value = "";
     $("#title").textContent = "この絞り込みに残っている回はありません"; $("#meta").textContent = "";
     $("#media").innerHTML = $("#chart").innerHTML = $("#ai").innerHTML = $("#cur").innerHTML = $("#hist").innerHTML = "";
     return true;
@@ -222,7 +231,7 @@ async function select(stem) {
   }
   $("#title").textContent = stem + " (読み込み中)"; $("#media").innerHTML = ""; $("#chart").innerHTML = "";
   $("#ai").innerHTML = $("#cur").innerHTML = $("#hist").innerHTML = "";
-  applyFilter(); markPP();
+  applyFilter(); markPP(); markOC(null);
   document.querySelector(`.item[data-stem="${stem}"]`)?.scrollIntoView({block: "nearest"});
   let d;
   try { const res = await fetch("/api/run/" + stem); d = await res.json(); if (!res.ok) throw new Error(d.error); }
@@ -263,9 +272,10 @@ function renderInfo() {
   const a = detail.ai, l = detail.latest;
   $("#ai").innerHTML = a ? `<div class="big">${OC_JA[a.outcome]}</div><div>pick ${a.pick} / place ${a.place} ・ 素材 ${a.evidence || "なし"}</div><div class="muted">${esc(a.ai_reason)}</div>` : `<span class="muted">AI の判定はありません</span>`;
   const h = detail.history.filter(r => HUMAN.includes(r.labeler)).pop();  // 人が確定した行 (依頼 187)
-  const hl = h ? `<div><b>人が確定済み</b> ・ ${OC_JA[h.outcome]} ・ ${esc(h.labeled_at.slice(0, 10))} ${hm(h.labeled_at)}</div>` : "";
-  $("#cur").innerHTML = l ? `<div class="big">${OC_JA[l.outcome]} <span class="muted" style="font-size:12px">${LB_JA[l.labeler]}</span></div>${hl}<div>pick ${l.pick} / place ${l.place} ・ ${esc(l.labeled_at)}</div>${l.note ? `<div class="muted">${esc(l.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
-  $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>pick/place</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${OC_JA[r.outcome]}</td><td>${r.pick}/${r.place}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
+  const hl = h ? `<div><b>人が確定済み</b> ${tag(h.outcome, false)} ・ ${esc(h.labeled_at.slice(0, 10))} ${hm(h.labeled_at)}</div>` : "";
+  $("#cur").innerHTML = l ? `<div class="big">${tag(l.outcome, l.labeler === "ai")} <span class="muted" style="font-size:12px">${LB_JA[l.labeler]}</span></div>${hl}<div>pick ${l.pick} / place ${l.place} ・ ${esc(l.labeled_at)}</div>${l.note ? `<div class="muted">${esc(l.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
+  markOC();
+  $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>pick/place</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${tag(r.outcome, r.labeler === "ai")}</td><td>${r.pick}/${r.place}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
 }
 
 // ---- 関節と爪のグラフ (関節は 1 本の軸・爪は下に別の帯. 2 つの縦軸は使わない) ----
@@ -327,6 +337,9 @@ function cursor(vt) {
   l.setAttribute("x1", xx); l.setAttribute("x2", xx); l.style.display = "";
 }
 
+// 判定するのボタン: 指定がなければ開いている回の人の確定を塗る (依頼 189)
+function humanOc() { const h = detail ? detail.history.filter(r => HUMAN.includes(r.labeler)).pop() : null; return h ? h.outcome : null; }
+function markOC(oc = humanOc()) { document.querySelectorAll("[data-oc]").forEach(b => b.classList.toggle("on", b.dataset.oc === oc)); }
 function markPP() {
   document.querySelectorAll("[data-pp]").forEach(b => b.classList.toggle("on", pp[b.dataset.pp] === b.dataset.v));
 }
@@ -338,6 +351,8 @@ document.querySelectorAll("[data-oc]").forEach(b => b.onclick = () => { b.blur()
 async function save(outcome) {
   if (!cur || busy || loading || !detail || detail.run_stem !== cur) return;
   busy = true; const stem = cur;
+  markOC(outcome);  // 押したらすぐ塗り, 0.4 秒見せてから次の回へ (その間も busy なので 2 回目は書かない. 依頼 189)
+  const shown = new Promise(r => setTimeout(r, 400));
   const payload = {run_stem: stem, outcome, pick: pp.pick, place: pp.place, note: $("#note").value};
   const key = JSON.stringify(payload);
   const prev = pendingOps[stem];
@@ -351,9 +366,9 @@ async function save(outcome) {
     const res = await fetch("/api/verdict", {method: "POST", headers: {"Content-Type": "application/json"},
       body: JSON.stringify(Object.assign({op_id: opId}, payload))});
     const j = await res.json();
-    if (!res.ok) { delete pendingOps[stem]; status("書けませんでした: " + j.error, "err"); return; }
+    if (!res.ok) { delete pendingOps[stem]; markOC(); status("書けませんでした: " + j.error, "err"); return; }
     saved = true;
-    toast(`確定しました：${stem}・${OC_JA[outcome]}`);
+    toast(`確定しました：${esc(stem)}${tag(outcome, false)}`);
     status(`${stem} を「${OC_JA[outcome]}」で追記しました (${LB_JA[j.row.labeler]}・pick ${j.row.pick} / place ${j.row.place})`, "ok");
     await loadRuns();
     // 同じ位置 (確定で一覧から消えたらそこに来た次の回) へ進む
@@ -362,9 +377,11 @@ async function save(outcome) {
     if (still >= 0) next = view[still + 1] || view[still];
     else next = view[Math.min(posBefore, view.length - 1)];
     // 画面を進め終えてから消す (読み直しや次の回の読み込みに失敗して押し直しても同じ op_id. codex 3 回目 R1・4 回目 R2)
+    await shown;
     if (selSeq !== seqAtSave) { delete pendingOps[stem]; return; }  // 保存中に人が別の回を選んでいたら動かさない (codex 6 回目 R2)
     if (await select(next ? next.run_stem : null)) delete pendingOps[stem];
   } catch (e) {
+    markOC();
     if (saved) { status(`${stem} は書けています. 一覧の読み直しに失敗しました: ${e} ・ 押し直しても 2 回は書きません`, "err"); return; }
     // 書けたのに応答が届かなかったこともある. 同じ回・同じ判定で押し直すと同じ op_id で送るので,
     // サーバーは 2 回書かない (codex R7. 別の回を判定してから戻っても pendingOps に残る)
```


![人が成功で確定した回を開いた画面。成功のボタンと札が青く塗られ、AI だけの札は白地に色の枠](https://pixelstomotors.com/media/LOG512_03_success_blue.png)


### 依頼190 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 30
---
# 依頼190：判定の画面で、確定済みの回を開いたら記録した pick / place のボタンを塗る

エイイチの指摘（2026-11-14）：pick と place は記憶されていないのか。
判定ファイルには pick・place が正しく入っている（例 pi05_20261110_114106 の 23:06:31 の行は pick=yes・place=no）。画面が、開いた回の記録を pick / place のボタンに出していないだけ。判定の書き込み・キー・数え方・見た目の決まり（依頼186・189）は変えない。

## やること
1. 回を開いたとき、その回の今の判定の行（人の確定があればそれ、なければ確定の行）の pick と place の値のボタンを button.on（--ink の塗り）で出す。値が unknown なら unknown を塗る
2. 開いたあとにエイイチが pick / place を押して変えたら、そのまま押したものが塗られる（今までどおり、y/n/u/x を押した時に書く）。回を移ったら 1 に戻る
3. 「今の判定（いちばん新しい行）」の欄で、同じ判定の札が 2 回出ている。1 回だけにする（札・人が確定・時刻・pick / place を 1 行目にまとめる。新しい色や飾りは足さない）
4. 確かめ：画面を立ち上げ直し（8765 番。ブラウザは開かない）、pi05_20261110_114106 を開いて pick が yes・place が no で塗られている画面の写しを撮る。確かめで判定は書かない。既存のテストが通ること
5. index.html など変えたファイルだけを指定して commit（git add . と git clean は使わない）。最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼190 で Claude Code が返した報告

```text
# 結果：20261114_190_確定済みの回でpickとplaceのボタンを塗る

- 状態：完了
- 始めた時刻：2026-11-14 23:11
- 終わった時刻：2026-11-14 23:13（2分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume e845f33b-f31e-4f2b-909d-3939495edaee`

## Claude Code の報告

**やったこと**
- 判定の画面 (`pi05/verdict_viewer/index.html`) を直しました。回を開いたとき、記録した行の pick と place のボタンを塗るようにしました。記録した行は、人の確定があればその行、なければ確定の行です。値が unknown なら unknown を塗ります。
- AI の判定しかない回は確定していないので、ボタンを塗りません。書けたかどうか分からない操作が残っている回は、今までどおりその時の入力を戻します。
- 開いたあとに pick や place を押せば、押したものが塗られます。判定を書くのは今までどおり y/n/u/x を押した時だけです。別の回へ移って戻ると、記録した値の塗りに戻ります。
- 「今の判定（いちばん新しい行）」の欄は札を 1 回だけにしました。1 行目に札・人が確定済み・日時・pick / place をまとめています。新しい色や飾りは足していません。
- 判定の書き込み・キー・数え方・見た目の決まり（依頼186・189）は変えていません。
- 8765 番で画面を立ち上げ直しました。ブラウザは開かず、画面の写しは見えない状態のブラウザで撮りました。

**結果**
- pi05_20261110_114106 を開くと、pick は yes、place は no で塗られています。写しは `claude_code_reports/20261114_190_screen_pi05_20261110_114106.png` です。
- 今の判定の欄に出る札は 1 個で、「失敗 人が確定済み ・ 2026-11-14 23:06 ・ pick yes / place no」と出ます。
- 回を移ったときの動きも確かめました。
  - pick の unknown を押すと、unknown が塗られました。
  - AI だけの回へ移ると、どのボタンも塗られませんでした。
  - 元の回へ戻ると、pick yes・place no の塗りに戻りました。
- 確かめでは判定を書いていません。判定ファイルは確かめの前後で変わっていないことを確認しました。
- 既存のテスト（test_verdicts）は 39 件すべて通りました。
- commit は b38dcad で、`index.html` だけを指定して add しました。

**変えたファイル**
- `pi05/verdict_viewer/index.html`
- 報告として次の 3 つを新しく作りました（commit には入れていません）。
  - `claude_code_reports/20261114_190.txt`
  - 上の画面の写し
  - `logs/` の作業記録

**決めてほしいこと**
なし

判定：合格
```

### 依頼190 のコードの差分（コミット b38dcad）

```diff
commit b38dcad7db508bd5a1cce5293c4a1ce3750ec692
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:13:32 2026 +0900

    判定の画面で確定済みの回を開いたら記録した pick / place のボタンを塗る (依頼 190). index.html だけ. 回を開いたら人の確定の行 (なければ確定の行) の pick / place を button.on で塗る (AI だけの回は塗らない・書けたか分からない操作の回はその入力を戻す). 押して変えたら押したものが塗られ, 回を移ると記録の値に戻る. 今の判定の札を 1 回にし, 札・人が確定済み・日時・pick / place を 1 行目にまとめる. 書き込み・キー・数え方・見た目の決まりは変えない. テスト test_verdicts 39 OK
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index b8a1443..044143c 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -238,6 +238,10 @@ async function select(stem) {
   catch (e) { if (seq === selSeq) { $("#title").textContent = stem; status("この回を読めませんでした: " + e.message + " ・ 一覧でもう一度選んでください", "err"); } return false; }
   if (seq !== selSeq || d.run_stem !== cur) return false;
   detail = d; loading = false;
+  if (!po) {  // 記録した pick / place を塗る (人の確定があればそれ, なければ確定の行. 依頼 190)
+    const r = recordedRow();
+    if (r) { pp = {pick: r.pick || null, place: r.place || null}; markPP(); }
+  }
   $("#title").textContent = stem;
   $("#meta").textContent = `送ったチャンク ${detail.executed_chunks} ・ 終わり方 ${detail.end_reason || "記録なし"} ・ ${detail.model || ""}`;
   renderMedia(); renderInfo(); renderChart();
@@ -272,8 +276,8 @@ function renderInfo() {
   const a = detail.ai, l = detail.latest;
   $("#ai").innerHTML = a ? `<div class="big">${OC_JA[a.outcome]}</div><div>pick ${a.pick} / place ${a.place} ・ 素材 ${a.evidence || "なし"}</div><div class="muted">${esc(a.ai_reason)}</div>` : `<span class="muted">AI の判定はありません</span>`;
   const h = detail.history.filter(r => HUMAN.includes(r.labeler)).pop();  // 人が確定した行 (依頼 187)
-  const hl = h ? `<div><b>人が確定済み</b> ${tag(h.outcome, false)} ・ ${esc(h.labeled_at.slice(0, 10))} ${hm(h.labeled_at)}</div>` : "";
-  $("#cur").innerHTML = l ? `<div class="big">${tag(l.outcome, l.labeler === "ai")} <span class="muted" style="font-size:12px">${LB_JA[l.labeler]}</span></div>${hl}<div>pick ${l.pick} / place ${l.place} ・ ${esc(l.labeled_at)}</div>${l.note ? `<div class="muted">${esc(l.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
+  const c = h || l;  // 札は 1 回だけ. 札・人が確定・時刻・pick / place を 1 行目に (依頼 190)
+  $("#cur").innerHTML = c ? `<div>${tag(c.outcome, c.labeler === "ai")} ${h ? "<b>人が確定済み</b>" : `<span class="muted">${LB_JA[c.labeler]}</span>`} ・ ${esc(c.labeled_at.slice(0, 10))} ${hm(c.labeled_at)} ・ pick ${c.pick} / place ${c.place}</div>${c.note ? `<div class="muted">${esc(c.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
   markOC();
   $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>pick/place</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${tag(r.outcome, r.labeler === "ai")}</td><td>${r.pick}/${r.place}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
 }
@@ -338,6 +342,13 @@ function cursor(vt) {
 }
 
 // 判定するのボタン: 指定がなければ開いている回の人の確定を塗る (依頼 189)
+// 開いた回の記録した行: 人の確定があればそれ, なければ確定の行 (AI だけの回は null. 依頼 190)
+function recordedRow() {
+  if (!detail) return null;
+  const h = detail.history.filter(r => HUMAN.includes(r.labeler)).pop();
+  const l = detail.latest;
+  return h || (l && l.labeler !== "ai" ? l : null);
+}
 function humanOc() { const h = detail ? detail.history.filter(r => HUMAN.includes(r.labeler)).pop() : null; return h ? h.outcome : null; }
 function markOC(oc = humanOc()) { document.querySelectorAll("[data-oc]").forEach(b => b.classList.toggle("on", b.dataset.oc === oc)); }
 function markPP() {
```


### 依頼191 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 15
---
# 依頼191：判定の画面の札の角丸を 6px に戻す

エイイチの指示（2026-11-14）：札の角丸を戻す。依頼189 で札（.tag）を手本の .tag の形（角丸 9px）にしたが、頼まれていない変更だった。
pi05/verdict_viewer/index.html の札（一覧・いま確定した回・今の判定・この回の行・確定しましたの知らせ）の角丸だけを、依頼189 の前と同じ 6px に戻す。色（成功の青・失敗の赤・AI だけは白地に色の枠）・字・余白・高さなど、ほかは一切変えない。依頼190 の変更も消さない。

## やること
1. 札の border-radius を 9px から 6px に戻す（ほかの値は触らない）
2. 画面を立ち上げ直し（8765 番。ブラウザは開かない）、左の一覧の札の写しを撮る。確かめで判定は書かない
3. index.html だけを指定して commit（git add . と git clean は使わない）。最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼191 で Claude Code が返した報告

```text
# 結果：20261114_191_札の角丸を6pxに戻す

- 状態：完了
- 始めた時刻：2026-11-14 23:14
- 終わった時刻：2026-11-14 23:15（1分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 3d3954ed-82f7-4dcf-b374-20b3da06277c`

## Claude Code の報告

**やったこと**
- `pi05/verdict_viewer/index.html:35` の札（`.tag`）の角丸を 9px から 6px に戻しました。依頼189 の前と同じ値です。直したのはこの 1 行だけで、色・字・余白・高さはそのままです。依頼190 の変更も残っています。
- 8765 番の画面を止めて立ち上げ直しました。ブラウザは開いていません。そのあと左の一覧の札を撮りました。判定は書いていません。
- `index.html` だけを指定して commit しました（b5332b9）。

**結果**
- 一覧の札は 24 個で、どれも角丸 6px・高さ 18px でした。高さは前と変わっていません。
- 写しを見ても、成功の青・失敗の赤・AI だけの白地に色の枠は前のままでした。
- 写し：`claude_code_reports/20261114_191_list_tags.png`、`claude_code_reports/20261114_191_screen.png`
- 報告：`claude_code_reports/20261114_191.txt`、作業のまとめ：`logs/` の同じ日時の md

**変えたファイル**
- `pi05/verdict_viewer/index.html`

**決めてほしいこと**
なし

判定：合格
```

### 依頼191 のコードの差分（コミット b5332b9）

```diff
commit b5332b91c002a3b6f5f13c698c44e11ed98203e0
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:15:12 2026 +0900

    判定の画面の札の角丸を 6px に戻す (依頼 191). index.html の .tag の border-radius を 9px から 6px にするだけ (依頼 189 の前と同じ値). 色・字・余白・高さ・依頼 190 の変更はそのまま. 8765 番で立ち上げ直し, 一覧の札 24 個がすべて角丸 6px・高さ 18px を確かめた (判定は書いていない)
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index 044143c..b8e046b 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -32,7 +32,7 @@
   /* 判定の札: 形は手本の .tag. 成功は青 (手本のスタッフ)・失敗は赤 (手本の止まっている)・ほかは色なし.
      人が確定 (と記録時の入力・決め) は塗り, AI だけ (未確定) は白地に同じ色の 1px の枠と字 (依頼 189).
      枠は高さを変えないよう内側の線で引く */
-  .tag { flex: none; min-width: 24px; text-align: center; font: 600 11px/18px "Inter", "Noto Sans JP", system-ui, sans-serif; border-radius: 9px;
+  .tag { flex: none; min-width: 24px; text-align: center; font: 600 11px/18px "Inter", "Noto Sans JP", system-ui, sans-serif; border-radius: 6px;
          padding: 0 7px; background: #fff; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); white-space: nowrap; align-self: center; display: inline-block; }
   .tag.success { background: var(--ok); color: #fff; box-shadow: inset 0 0 0 1px var(--ok); }
   .tag.failure { background: var(--stop); color: #fff; box-shadow: inset 0 0 0 1px var(--stop); }
```


![確定済みの回を開いた画面。記録した pick の yes と place の no のボタンが黒く塗られている](https://pixelstomotors.com/media/LOG512_04_pickplace_painted.png)


## 依頼192〜195：選んでから確定する2段にし、place に「そこまで行かなかった」を足す

判定を付けていくと、キーを押した瞬間に記録されて次の回へ移るので、押したものを確かめる間がありませんでした。y/n/u/x は選ぶだけにし、黒い確定ボタン（Enter でも押せる）で記録する形にしました。

pick と place の英語（yes / no / unknown）も分かりにくかったので、ボタンの字だけ日本語にしました。ファイルに書く値は変えていません。そのとき、つかめずに終わった回の place を記録する選択肢がないことに気づきました。no だと「置こうとしたが置けなかった」と同じになり、置く動作の失敗が実際より多く数えられます。unknown は「映像から分からない」の意味で、これも合いません。受け渡しの台帳と同じ語 `not_applicable` を足し、画面では「そこまで行かなかった」と出しています。つかめなかったを選ぶと、place は自動でそれになります。

依頼193 では、ボタンの字だけでなく、行の頭の pick / place まで「つかむ」「置く」に変えてしまいました。頼まれていない変更なので、依頼194 で pick / place に戻し、依頼195 でテストを合わせています。

- ねらい：押し間違いで記録されないようにし、つかめずに終わった回を正しく数える
- 変わったこと：選ぶ → 確定の2段。place の値に `not_applicable` を足した
- 見込める効果：置く動作の失敗率を、つかめなかった回で水増しせずに出せる（まだ数えていない）


### 依頼192 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 40
---
# 依頼192：判定の画面で、判定を選んでから「確定」で書く 2 段にする

エイイチの指示（2026-11-14）：判定する（キー）を押すとそのまま次へ進んで消えるので、もう 1 アクション欲しい。確定の決定ボタンがあるとよい。
判定ファイルの中身・列・数え方・見た目の決まり（依頼186・189・190・191。角丸 6px・成功は青・失敗は赤・選んだものは塗り）は変えない。

## 動き
1. y / n / u / x（キーでもクリックでも）は「選ぶ」だけにする。選んだボタンを今の決まりどおり塗る（成功は青・失敗は赤・ほかは --ink）。この時点では判定ファイルに書かない。選び直しもできる
2. pick / place も今までどおり選べる（選んだものは塗り）
3. 「判定する」の欄の下に「確定」ボタンを 1 つ置く（幅いっぱい・--ink の塗りに白い字・角丸 6px・手本の #cta a の強さ）。キーは Enter。y/n/u/x を選ぶまでは押せない見た目（薄く）にして、押しても何もしない
4. 確定（ボタンか Enter）で、今までと同じ 1 行を追記し、「確定しました：回の名前・判定」の知らせを出して、0.4 秒後に次の回へ進む。2 回書かない守りは今までどおり
5. 確定する前に回を移ったら（← → や一覧のクリック）、選んだものは捨てる（書かない）
6. 確定済みの回を開いたときは、記録した判定と pick / place が塗られた状態で出る（依頼190 のまま）。選び直して確定すれば、新しい行を足す（新しいほうが正）
7. ひとこと欄に入力中は y/n/u/x は今までどおり効かないが、Enter は確定として効く（1 行の欄なので改行はしない）
8. 下の操作の説明の行（← → 前後の回 …）に「Enter 確定」を足す

## 確かめ
- テスト：選んだだけでは書かないこと・Enter とボタンで 1 行だけ書くこと・選ぶ前の確定は何もしないこと・回を移ると選んだものが消えること
- 画面を立ち上げ直し（8765 番。ブラウザは開かない）、/tmp の写しの判定ファイルで (a) n を選んだだけで確定ボタンが押せる状態の写し (b) 確定したあとの知らせの写し を撮る。本物の判定ファイルには書かない。終わったら本物の判定ファイルで立ち上げ直す
- 変えたファイルだけを指定して commit（git add . と git clean は使わない）。最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼192 で Claude Code が返した報告

```text
# 結果：20261114_192_判定を選んでから確定ボタンで書く

- 状態：完了
- 始めた時刻：2026-11-14 23:16
- 終わった時刻：2026-11-14 23:20（4分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 8b1a6e72-a7ed-4aa6-9677-414f9c60f383`

## Claude Code の報告

**やったこと**
- 判定の画面で、y / n / u / x はキーでもクリックでも「選ぶ」だけにしました。選んだボタンは今の決まりどおり塗ります（成功は青・失敗は赤・ほかは --ink）。この時点では判定ファイルに書かず、選び直せます。
- 「判定する」の欄の下に「確定 Enter」のボタンを 1 つ置きました。幅いっぱい・--ink の塗りに白い字・角丸 6px で、強さは手本の #cta a に合わせています（字は太字 14px）。
  - y / n / u / x を選ぶまでは薄く出て、押しても何もしません。
  - 確定（ボタンか Enter）で、今までと同じ 1 行を書き足します。そのあと「確定しました」の知らせを出し、0.4 秒後に次の回へ進みます。2 回書かない守りは今までどおりです。
- 確定する前に回を移ると、選んだものは捨てます。確定済みの回は、記録した判定と pick / place が塗られた状態で出ます（依頼190 のまま）。
- ひとこと欄に入力中は y / n / u / x が効かず、Enter は確定として効きます。日本語の変換を決めるための Enter では確定しないようにしました。
- 下の操作の説明の行に「Enter 確定」を足しました。
- テストを 6 件足しました。画面を Chrome で実際に動かして確かめます。
  - 選んだだけでは書かない（選び直しを含む）
  - 選ぶ前に確定しても何もしない
  - Enter で 1 行だけ書く
  - ボタンで 1 行だけ書く
  - ひとこと欄の Enter で確定する
  - 回を移ると選んだものが消える

**結果**
- テスト test_verdicts は 45 件すべて通りました（今までの 39 件と新しい 6 件。飛ばしたものはなし）。
- 8765 番を /tmp の写しの判定ファイルで立ち上げ直して撮影しました（ブラウザは開いていません）。
  - (a) n を選んだ直後は、失敗のボタンが赤く塗られ、確定ボタンが押せる状態になりました。
  - (b) Enter を押すと写しの行が 281 行から 282 行に 1 行だけ増え、「確定しました：pi05_20261021_082645 失敗」の知らせが出て、次の回へ進みました。進んだ先では確定ボタンが薄い状態に戻りました。
- 本物の判定ファイルは、確かめの前後で中身が同じでした（md5 が同じ）。終わってから本物の判定ファイルで 8765 番を立ち上げ直しました。
- 画面の写しは claude_code_reports/ にあります。
  - 20261114_192_a_chosen_n.png
  - 20261114_192_a_panel.png
  - 20261114_192_b_after_confirm.png
- 報告は claude_code_reports/20261114_192.txt と logs/20261114_2320.md に書きました。
- commit は cde49e5 です（下の 2 つのファイルだけを指定しました）。

**変えたファイル**
- pi05/verdict_viewer/index.html
- pi05/verdict_viewer/test_verdicts.py

**決めてほしいこと**
なし

判定：合格
```

### 依頼192 のコードの差分（コミット cde49e5）

```diff
commit cde49e592dbe98be95e9db353c8ca47999c8aa1b
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:19:49 2026 +0900

    判定の画面で判定を選んでから「確定」で書く 2 段にする (依頼 192). index.html: y/n/u/x (キー・クリック) は選ぶだけ (塗る・書かない・選び直せる). 判定するの欄の下に確定のボタン (幅いっぱい・--ink の塗りに白い字・角丸 6px・手本の #cta a の強さ. 選ぶまでは薄く押せない). 確定 (ボタンか Enter) で今までと同じ 1 行を追記し, 確定しましたの知らせ・0.4 秒後に次の回 (2 回書かない守りはそのまま). 回を移ると選んだものは捨てる. ひとこと欄でも Enter は確定 (変換中は除く). 操作の説明に Enter 確定を足す. test_verdicts.py に画面を Chrome で動かすテスト 6 件. テスト 45 OK. 8765 番は /tmp の写しで撮影ののち本物の判定ファイルで立ち上げ直した (本物は md5 変わらず)
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html       |  53 ++++++++++++----
 pi05/verdict_viewer/test_verdicts.py | 120 +++++++++++++++++++++++++++++++++++
 2 files changed, 159 insertions(+), 14 deletions(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index b8e046b..1d95122 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -71,6 +71,12 @@
   /* 判定するのボタン: 人の確定と押した判定を塗る. 成功は青・失敗は赤・ほかは --ink (依頼 189) */
   button.key.on[data-oc="success"] { background: var(--ok); border-color: var(--ok); }
   button.key.on[data-oc="failure"] { background: var(--stop); border-color: var(--stop); }
+  /* 確定のボタン: 手本の #cta a の強さ. y/n/u/x を選ぶまでは薄く押せない (依頼 192) */
+  #confirm { display: block; width: 100%; margin-top: 10px; text-align: center; background: var(--ink); color: #fff; border-color: var(--ink);
+             font-weight: 600; font-size: 14px; padding: 11px 12px; border-radius: 6px; }
+  #confirm:hover:not(:disabled) { background: #000; }
+  #confirm:disabled { opacity: .3; cursor: default; }
+  #confirm kbd { margin-left: 6px; }
   kbd { font: 600 11px/1 "Inter", system-ui, sans-serif; border: 1px solid var(--line); border-radius: 6px; padding: 2px 5px; background: var(--bg); color: var(--ink); }
   #note { width: 100%; font: inherit; padding: 5px 6px; border: 1px solid var(--line); border-radius: 6px; color: var(--ink); }
   #status { min-height: 1em; margin: 6px 0 0; font-size: 12px; color: var(--sub); }
@@ -140,11 +146,12 @@
   <div class="row"><span class="lbl">place</span>
     <div class="seg"><button data-pp="place" data-v="yes">yes</button><button data-pp="place" data-v="no">no</button><button data-pp="place" data-v="unknown">unknown</button></div></div>
   <p class="note">選ばなければ 成功→yes / ほか→unknown</p>
+  <button id="confirm" disabled>確定<kbd>Enter</kbd></button>
   <h2>いま確定した回 (新しい 5 回)</h2><div id="recent"></div>
   <h2>ひとこと</h2>
-  <input id="note" placeholder="ひとこと (空でよい・入力中はキーで判定しない)">
+  <input id="note" placeholder="ひとこと (空でよい・入力中は y/n/u/x は効かない・Enter で確定)">
   <div id="status"></div>
-  <p class="note"><kbd>←</kbd> <kbd>→</kbd> 前後の回 ・ <kbd>,</kbd> <kbd>.</kbd> コマ送り / 動画は <kbd>space</kbd> で再生</p>
+  <p class="note"><kbd>←</kbd> <kbd>→</kbd> 前後の回 ・ <kbd>Enter</kbd> 確定 ・ <kbd>,</kbd> <kbd>.</kbd> コマ送り / 動画は <kbd>space</kbd> で再生</p>
   <h2>AI の判定 (未確定)</h2><div id="ai" class="dark"></div>
   <h2>今の判定 (いちばん新しい行)</h2><div id="cur"></div>
   <h2>成功率 (確定した回だけ)</h2>
@@ -158,6 +165,7 @@ const COLORS = ["--s1", "--s2", "--s3", "--s4", "--s5", "--s6"].map(v => getComp
 const pendingOps = {};  // run_stem → 書けたか分からない操作 (回ごとに残す. codex 6 回目 R1)
 let selSeq = 0;  // 応答が届かなかった操作. 同じ中身で押し直したら同じ op_id で送る (codex 2 回目 R2)
 let runs = [], view = [], cur = null, detail = null, pp = {pick: null, place: null}, frameIdx = 0, busy = false, loading = false;
+let chosen = null;  // y/n/u/x で選んだ判定. 確定するまで書かない・回を移ったら捨てる (依頼 192)
 
 const $ = s => document.querySelector(s);
 const esc = s => String(s ?? "").replace(/[&<>"]/g, c => ({"&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;"}[c]));
@@ -217,17 +225,17 @@ async function loadRuns() {
 async function select(stem) {
   const seq = ++selSeq;  // いちばん新しい選択の応答だけ使う (codex 5 回目 R2・6 回目 R3)
   if (!stem) {  // 空の一覧: 前の回の表示と状態を残さない (codex 7 回目 R1)
-    cur = null; detail = null; chartGeom = null; loading = false; pp = {pick: null, place: null}; markPP(); markOC(null); $("#note").value = "";
+    cur = null; detail = null; chartGeom = null; loading = false; pp = {pick: null, place: null}; chosen = null; markPP(); markOC(null); $("#note").value = "";
     $("#title").textContent = "この絞り込みに残っている回はありません"; $("#meta").textContent = "";
     $("#media").innerHTML = $("#chart").innerHTML = $("#ai").innerHTML = $("#cur").innerHTML = $("#hist").innerHTML = "";
     return true;
   }
   // 読み込みが終わるまでは判定を受け付けない (前の回を見ながら次の回に書かない. codex R1)
-  cur = stem; detail = null; loading = true; pp = {pick: null, place: null}; frameIdx = 0; $("#note").value = "";
+  cur = stem; detail = null; loading = true; pp = {pick: null, place: null}; chosen = null; frameIdx = 0; $("#note").value = "";
   const po = pendingOps[stem];
   if (po) {
-    // 書けたか分からない操作の回に戻ったら, そのときの入力を戻す (同じキーで同じ op_id になる. codex 5 回目 R1)
-    pp = {pick: po.payload.pick, place: po.payload.place}; $("#note").value = po.payload.note;
+    // 書けたか分からない操作の回に戻ったら, そのときの入力を戻す (同じ確定で同じ op_id になる. codex 5 回目 R1)
+    pp = {pick: po.payload.pick, place: po.payload.place}; $("#note").value = po.payload.note; chosen = po.payload.outcome;
   }
   $("#title").textContent = stem + " (読み込み中)"; $("#media").innerHTML = ""; $("#chart").innerHTML = "";
   $("#ai").innerHTML = $("#cur").innerHTML = $("#hist").innerHTML = "";
@@ -237,7 +245,7 @@ async function select(stem) {
   try { const res = await fetch("/api/run/" + stem); d = await res.json(); if (!res.ok) throw new Error(d.error); }
   catch (e) { if (seq === selSeq) { $("#title").textContent = stem; status("この回を読めませんでした: " + e.message + " ・ 一覧でもう一度選んでください", "err"); } return false; }
   if (seq !== selSeq || d.run_stem !== cur) return false;
-  detail = d; loading = false;
+  detail = d; loading = false; markConfirm();
   if (!po) {  // 記録した pick / place を塗る (人の確定があればそれ, なければ確定の行. 依頼 190)
     const r = recordedRow();
     if (r) { pp = {pick: r.pick || null, place: r.place || null}; markPP(); }
@@ -350,19 +358,29 @@ function recordedRow() {
   return h || (l && l.labeler !== "ai" ? l : null);
 }
 function humanOc() { const h = detail ? detail.history.filter(r => HUMAN.includes(r.labeler)).pop() : null; return h ? h.outcome : null; }
-function markOC(oc = humanOc()) { document.querySelectorAll("[data-oc]").forEach(b => b.classList.toggle("on", b.dataset.oc === oc)); }
+// 選んだ判定があればそれ, なければ人の確定を塗る (依頼 192)
+function markOC(oc = chosen || humanOc()) { document.querySelectorAll("[data-oc]").forEach(b => b.classList.toggle("on", b.dataset.oc === oc)); markConfirm(); }
+function markConfirm() { $("#confirm").disabled = !chosen || !cur || loading || !detail; }
 function markPP() {
   document.querySelectorAll("[data-pp]").forEach(b => b.classList.toggle("on", pp[b.dataset.pp] === b.dataset.v));
 }
 document.querySelectorAll("[data-pp]").forEach(b => b.onclick = () => {
   const k = b.dataset.pp; pp[k] = pp[k] === b.dataset.v ? null : b.dataset.v; markPP(); b.blur();
 });
-document.querySelectorAll("[data-oc]").forEach(b => b.onclick = () => { b.blur(); save(b.dataset.oc); });
+document.querySelectorAll("[data-oc]").forEach(b => b.onclick = () => { b.blur(); choose(b.dataset.oc); });
+$("#confirm").onclick = () => { $("#confirm").blur(); confirmChosen(); };
+
+// y/n/u/x は選ぶだけ (書かない. 選び直せる). 書くのは確定のボタンか Enter (依頼 192)
+function choose(oc) {
+  if (!cur || busy || loading || !detail || detail.run_stem !== cur) return;
+  chosen = oc; markOC();
+}
+function confirmChosen() { if (chosen) save(chosen); }
 
 async function save(outcome) {
   if (!cur || busy || loading || !detail || detail.run_stem !== cur) return;
   busy = true; const stem = cur;
-  markOC(outcome);  // 押したらすぐ塗り, 0.4 秒見せてから次の回へ (その間も busy なので 2 回目は書かない. 依頼 189)
+  markOC(outcome);  // 確定したら 0.4 秒見せてから次の回へ (その間も busy なので 2 回目は書かない. 依頼 189・192)
   const shown = new Promise(r => setTimeout(r, 400));
   const payload = {run_stem: stem, outcome, pick: pp.pick, place: pp.place, note: $("#note").value};
   const key = JSON.stringify(payload);
@@ -396,7 +414,7 @@ async function save(outcome) {
     if (saved) { status(`${stem} は書けています. 一覧の読み直しに失敗しました: ${e} ・ 押し直しても 2 回は書きません`, "err"); return; }
     // 書けたのに応答が届かなかったこともある. 同じ回・同じ判定で押し直すと同じ op_id で送るので,
     // サーバーは 2 回書かない (codex R7. 別の回を判定してから戻っても pendingOps に残る)
-    status("書けたか確かめられませんでした: " + e + " ・ 同じキーで押し直すと 2 回は書きません", "err");
+    status("書けたか確かめられませんでした: " + e + " ・ そのまま確定し直すと 2 回は書きません", "err");
   }
   finally { busy = false; }
 }
@@ -408,12 +426,19 @@ function move(d) {
 }
 
 document.addEventListener("keydown", e => {
+  // Enter は確定. ひとこと欄に入力中でも効く (変換中の Enter は確定にしない. 依頼 192)
+  if (e.key === "Enter" && e.target.tagName !== "SELECT") {
+    if (e.isComposing || e.keyCode === 229 || e.metaKey || e.ctrlKey || e.altKey || e.shiftKey) return;
+    e.preventDefault();
+    if (!e.repeat) confirmChosen();  // 押しっぱなしで次の回まで書かない (codex R5)
+    return;
+  }
   if (e.target.tagName === "INPUT" && e.target.type !== "range") { if (e.key === "Escape") e.target.blur(); return; }
   if (e.metaKey || e.ctrlKey || e.altKey) return;
-  if (e.repeat && "ynux".includes(e.key)) return;  // 押しっぱなしで次の回まで書かない (codex R5)
+  if (e.repeat && "ynux".includes(e.key)) return;
   const k = e.key;
-  if (k === "y") save("success"); else if (k === "n") save("failure");
-  else if (k === "u") save("unknown"); else if (k === "x") save("not_judgeable");
+  if (k === "y") choose("success"); else if (k === "n") choose("failure");
+  else if (k === "u") choose("unknown"); else if (k === "x") choose("not_judgeable");
   else if (k === "ArrowRight") { e.preventDefault(); move(1); } else if (k === "ArrowLeft") { e.preventDefault(); move(-1); }
   else if (k === ".") stepFrame(1); else if (k === ",") stepFrame(-1);
   else if (k === " " && $("#vid")) { e.preventDefault(); const v = $("#vid"); v.paused ? v.play() : v.pause(); }
diff --git a/pi05/verdict_viewer/test_verdicts.py b/pi05/verdict_viewer/test_verdicts.py
index 9985e43..106c984 100644
--- a/pi05/verdict_viewer/test_verdicts.py
+++ b/pi05/verdict_viewer/test_verdicts.py
@@ -374,6 +374,126 @@ class TestServer(unittest.TestCase):
             self.assertEqual(cm.exception.code, 404)
 
 
+class TestConfirm192(unittest.TestCase):
+    """依頼 192: y/n/u/x は選ぶだけ・確定 (ボタンか Enter) で 1 行だけ書く. 画面を Chrome で動かす (playwright がなければ飛ばす)."""
+    @classmethod
+    def setUpClass(cls):
+        try:
+            from playwright.sync_api import sync_playwright
+            cls.pw = sync_playwright().start()
+            cls.browser = cls.pw.chromium.launch(channel="chrome")
+        except Exception as e:  # noqa: BLE001
+            raise unittest.SkipTest(f"playwright / Chrome がない: {e}")
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.browser.close()
+        cls.pw.stop()
+
+    def setUp(self):
+        self.tmp = tempfile.TemporaryDirectory()
+        self.runs = make_runs(Path(self.tmp.name) / "runs")
+        self.csv = Path(self.tmp.name) / "v.csv"
+        V.append_rows([row("pi05_20261001_000003", "success", "ai", ai_reason="入っている", evidence="frames")], self.csv)
+        self.srv = server.ThreadingHTTPServer(("127.0.0.1", 0), server.make_handler(server.App(self.runs, self.csv)))
+        threading.Thread(target=self.srv.serve_forever, daemon=True).start()
+        self.pg = self.browser.new_page()
+        self.pg.goto(f"http://127.0.0.1:{self.srv.server_address[1]}/")
+        self.wait_loaded()
+
+    def tearDown(self):
+        self.pg.close()
+        self.srv.shutdown()
+        self.srv.server_close()
+        self.tmp.cleanup()
+
+    def wait_loaded(self):
+        self.pg.wait_for_function("() => { const t = document.querySelector('#title').textContent;"
+                                  " return t.startsWith('pi05_') && !t.includes('読み込み中'); }")
+
+    def n_rows(self):
+        return len(V.read_rows(self.csv))
+
+    def on_keys(self):
+        return self.pg.eval_on_selector_all("button.key.on", "e => e.map(x => x.dataset.oc)")
+
+    def disabled(self):
+        return self.pg.eval_on_selector("#confirm", "e => e.disabled")
+
+    def test_choose_only_does_not_write(self):
+        n = self.n_rows()
+        self.assertTrue(self.disabled())
+        self.pg.keyboard.press("n")
+        self.assertEqual(self.on_keys(), ["failure"])
+        self.assertFalse(self.disabled())
+        self.pg.click('button.key[data-oc="success"]')  # 選び直し
+        self.assertEqual(self.on_keys(), ["success"])
+        self.pg.wait_for_timeout(600)
+        self.assertEqual(self.n_rows(), n)
+
+    def test_confirm_before_choose_does_nothing(self):
+        n = self.n_rows()
+        title = self.pg.text_content("#title")
+        self.pg.keyboard.press("Enter")
+        self.pg.click("#confirm", force=True)
+        self.pg.wait_for_timeout(600)
+        self.assertEqual(self.n_rows(), n)
+        self.assertEqual(self.pg.text_content("#title"), title)
+
+    def test_enter_writes_one_row(self):
+        n = self.n_rows()
+        stem = self.pg.text_content("#title")
+        self.pg.keyboard.press("n")
+        self.pg.keyboard.press("Enter")
+        self.pg.keyboard.press("Enter")  # 0.4 秒の間の 2 回目は書かない
+        self.pg.wait_for_function("() => document.querySelector('#toast').textContent.includes('確定しました')")
+        self.assertIn(stem, self.pg.text_content("#toast"))
+        self.pg.wait_for_timeout(800)
+        rows = V.read_rows(self.csv)
+        self.assertEqual(len(rows), n + 1)
+        self.assertEqual((rows[-1]["run_stem"], rows[-1]["outcome"]), (stem, "failure"))
+
+    def test_button_writes_one_row(self):
+        n = self.n_rows()
+        stem = self.pg.text_content("#title")
+        self.pg.keyboard.press("y")
+        self.pg.click("#confirm")
+        self.pg.click("#confirm", force=True)
+        self.pg.wait_for_timeout(1000)
+        rows = V.read_rows(self.csv)
+        self.assertEqual(len(rows), n + 1)
+        self.assertEqual((rows[-1]["run_stem"], rows[-1]["outcome"]), (stem, "success"))
+
+    def test_enter_in_note_confirms_but_keys_do_not_choose(self):
+        n = self.n_rows()
+        self.pg.keyboard.press("u")
+        self.pg.click("#note")
+        self.pg.keyboard.type("yn")
+        self.assertEqual(self.on_keys(), ["unknown"])
+        self.pg.keyboard.press("Enter")
+        self.pg.wait_for_timeout(1000)
+        rows = V.read_rows(self.csv)
+        self.assertEqual(len(rows), n + 1)
+        self.assertEqual((rows[-1]["outcome"], rows[-1]["note"]), ("unknown", "yn"))
+
+    def test_moving_discards_choice(self):
+        n = self.n_rows()
+        stem = self.pg.text_content("#title")
+        self.pg.keyboard.press("n")
+        self.pg.keyboard.press("ArrowRight")
+        self.wait_loaded()
+        self.assertNotEqual(self.pg.text_content("#title"), stem)
+        self.assertEqual(self.on_keys(), [])
+        self.assertTrue(self.disabled())
+        self.pg.keyboard.press("ArrowLeft")
+        self.wait_loaded()
+        self.assertEqual(self.pg.text_content("#title"), stem)
+        self.assertEqual(self.on_keys(), [])
+        self.pg.keyboard.press("Enter")
+        self.pg.wait_for_timeout(600)
+        self.assertEqual(self.n_rows(), n)
+
+
 class TestRule185(unittest.TestCase):
     """エイイチの決め (2026-11-14 依頼 185): run_input も確定・送ったチャンク 0 → not_applicable・素材不足 → not_judgeable."""
     def setUp(self):
```


![失敗を選んで、黒い確定ボタンが押せる状態になった右のパネル](https://pixelstomotors.com/media/LOG512_05_confirm_button.png)


### 依頼193 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 40
---
# 依頼193：判定の画面の pick / place を日本語にし、place に「そこまで行かなかった」を足す

エイイチの決め（2026-11-14）：
- pick / place の画面の字を日本語にする（判定ファイルの値は yes / no / unknown のまま変えない）
- つかめずに place まで行かなかった回を記録できるように、place に「そこまで行かなかった」を足す。判定ファイルの値は not_applicable（受け渡しの台帳と同じ語）
依頼192（選んでから確定）までの動き・見た目の決まり（角丸 6px・選んだものは --ink の塗り・成功は青・失敗は赤）は変えない。

## やること
1. 画面の字（ボタンの字だけ。値は変えない）
   - pick：つかめた（yes）／つかめなかった（no）／分からない（unknown）
   - place：置けた（yes）／置けなかった（no）／そこまで行かなかった（not_applicable）／分からない（unknown）
   - 行の頭の pick / place も「つかむ」「置く」にする
   - 「この回の行」の表・今の判定の欄など、pick / place の値を出している所も同じ日本語にする
2. verdicts.py の place の値に not_applicable を足す（pick には足さない）。書き込み・読み込みのチェックとテストを合わせる
3. 「つかめなかった」を選んだら、place は自動で「そこまで行かなかった」を選んだ状態にする（あとから選び直せる）。「つかめた」に戻したら place は選んでいない状態に戻す
4. 何も選ばずに確定したときの値は今までどおり（成功→両方 yes／ほか→両方 unknown）。ボタンの下の説明の字も日本語にする（例：選ばなければ 成功→つかめた・置けた／ほか→分からない）
5. 確かめ：テスト（place に not_applicable を書けること・pick には書けないこと・つかめなかったで place が自動で選ばれること）。画面を立ち上げ直し（8765 番。ブラウザは開かない）、/tmp の写しの判定ファイルで「つかめなかった」を選んで place が「そこまで行かなかった」になった画面の写しを撮る。本物の判定ファイルには書かない。終わったら本物の判定ファイルで立ち上げ直す
6. 変えたファイルだけを指定して commit（git add . と git clean は使わない）。最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼193 で Claude Code が返した報告

```text
# 結果：20261114_193_pickとplaceを日本語にしそこまで行かなかったを足す

- 状態：完了
- 始めた時刻：2026-11-14 23:21
- 終わった時刻：2026-11-14 23:24（3分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume ee2300cb-0732-4dcf-b81c-e2ef855fc21c`

## Claude Code の報告

**やったこと**
- 判定の画面のボタンを日本語にしました。判定ファイルに書く値は変えていません。
  - つかむ：つかめた／つかめなかった／分からない
  - 置く：置けた／置けなかった／そこまで行かなかった／分からない
- 行の頭を「つかむ」「置く」にしました。AI の判定・今の判定・「この回の行」の表・確定したときの知らせも、同じ日本語で出します。
- ボタンの下の説明の字を「選ばなければ 成功→つかめた・置けた／ほか→分からない」にしました。何も選ばずに確定したときの値は今までどおりです。
- 判定ファイルの置くの値に not_applicable（そこまで行かなかった）を足しました。つかむには足していません。書き込みのチェックとテストもこれに合わせました。
- 「つかめなかった」を選ぶと、置くは自動で「そこまで行かなかった」になります（あとから選び直せます）。「つかめなかった」から「つかめた」に戻すと、置くは選んでいない状態に戻ります。
- 依頼192 までの動きと見た目は変えていません。

**結果**
- テストは 49 件すべて合格しました（今までの 45 件に 4 件を足しました）。足した 4 件で確かめたこと：
  - 置くには「そこまで行かなかった」を書ける
  - つかむには書けない（判定ファイルに直接書いても、画面から送っても書かずに止まる）
  - ボタンの字が日本語になっている
  - 「つかめなかった」で置くが自動で選ばれ、確定するとつかむ＝つかめなかった・置く＝そこまで行かなかったの 1 行が書かれる
- 8765 番を /tmp の写しの判定ファイルで立ち上げ直しました。「つかめなかった」を押すと置くが「そこまで行かなかった」になる画面を撮りました。写しにも書いていません。
  - claude_code_reports/20261114_193_a_pick_no.png
  - claude_code_reports/20261114_193_a_panel.png
- 本物の判定ファイルは前後で変わっていません（287 行のまま、md5 ae81830061ede087931cf083797c5c6b）。終わってから、本物の判定ファイルで 8765 番を立ち上げ直しました（ブラウザは開いていません）。
- 3 つのファイルを指定して commit しました（2066ac2）。報告は claude_code_reports/20261114_193.txt と logs/20261114_2324.md に書きました。

**変えたファイル**
- pi05/verdict_viewer/index.html
- pi05/verdict_viewer/verdicts.py
- pi05/verdict_viewer/test_verdicts.py

**決めてほしいこと**
なし

判定：合格
```

### 依頼193 のコードの差分（コミット 2066ac2）

```diff
commit 2066ac279221c036615d73a0283556d1e053e338
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:24:36 2026 +0900

    判定の画面の pick / place を日本語にし place に「そこまで行かなかった」を足す (依頼 193). index.html: ボタンの字を つかむ (つかめた・つかめなかった・分からない) / 置く (置けた・置けなかった・そこまで行かなかった・分からない) に. 値は yes / no / unknown のまま, place だけ not_applicable を足す. AI の判定・今の判定・この回の行・知らせも同じ日本語. つかめなかったで置くは自動でそこまで行かなかった (選び直せる), つかめたに戻すと置くは選んでいない状態に. 選ばないときの値は今までどおり (説明の字だけ日本語). verdicts.py: PLACE_VALUES を足し place だけ not_applicable を通す. test_verdicts.py に 4 件. テスト 49 OK. 8765 番は /tmp の写しで撮影ののち本物の判定ファイルで立ち上げ直した (本物は md5 変わらず)
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html       | 28 +++++++++++++--------
 pi05/verdict_viewer/test_verdicts.py | 49 ++++++++++++++++++++++++++++++++++++
 pi05/verdict_viewer/verdicts.py      |  7 ++++--
 3 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index 1d95122..a9ca0ba 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -141,11 +141,11 @@
     <button class="key" data-oc="unknown"><kbd>u</kbd> 分からない</button>
     <button class="key" data-oc="not_judgeable"><kbd>x</kbd> 判定できない</button>
   </div>
-  <div class="row"><span class="lbl">pick</span>
-    <div class="seg"><button data-pp="pick" data-v="yes">yes</button><button data-pp="pick" data-v="no">no</button><button data-pp="pick" data-v="unknown">unknown</button></div></div>
-  <div class="row"><span class="lbl">place</span>
-    <div class="seg"><button data-pp="place" data-v="yes">yes</button><button data-pp="place" data-v="no">no</button><button data-pp="place" data-v="unknown">unknown</button></div></div>
-  <p class="note">選ばなければ 成功→yes / ほか→unknown</p>
+  <div class="row"><span class="lbl">つかむ</span>
+    <div class="seg"><button data-pp="pick" data-v="yes">つかめた</button><button data-pp="pick" data-v="no">つかめなかった</button><button data-pp="pick" data-v="unknown">分からない</button></div></div>
+  <div class="row"><span class="lbl">置く</span>
+    <div class="seg"><button data-pp="place" data-v="yes">置けた</button><button data-pp="place" data-v="no">置けなかった</button><button data-pp="place" data-v="not_applicable">そこまで行かなかった</button><button data-pp="place" data-v="unknown">分からない</button></div></div>
+  <p class="note">選ばなければ 成功→つかめた・置けた / ほか→分からない</p>
   <button id="confirm" disabled>確定<kbd>Enter</kbd></button>
   <h2>いま確定した回 (新しい 5 回)</h2><div id="recent"></div>
   <h2>ひとこと</h2>
@@ -160,6 +160,10 @@
 </aside>
 <script>
 const OC_JA = {success: "成功", failure: "失敗", unknown: "分からない", not_judgeable: "判定できない", not_applicable: "試行でない", "": "なし"};
+// pick / place の値は yes / no / unknown (place だけ not_applicable も) のまま. 画面の字だけ日本語 (依頼 193)
+const PICK_JA = {yes: "つかめた", no: "つかめなかった", unknown: "分からない"};
+const PLACE_JA = {yes: "置けた", no: "置けなかった", not_applicable: "そこまで行かなかった", unknown: "分からない"};
+const ppJa = r => `つかむ ${esc(PICK_JA[r.pick] ?? r.pick)} / 置く ${esc(PLACE_JA[r.place] ?? r.place)}`;
 const LB_JA = {run_input: "記録時の入力", ai: "AI", human: "人 (AI と同じ)", human_fixed_ai: "人 (AI を直した)", human_only: "人 (AI なし)", rule: "決め (依頼185)", "": ""};
 const COLORS = ["--s1", "--s2", "--s3", "--s4", "--s5", "--s6"].map(v => getComputedStyle(document.documentElement).getPropertyValue(v).trim());
 const pendingOps = {};  // run_stem → 書けたか分からない操作 (回ごとに残す. codex 6 回目 R1)
@@ -282,12 +286,12 @@ function stepFrame(d) { if (detail && !detail.has_mp4 && detail.frames.length &&
 
 function renderInfo() {
   const a = detail.ai, l = detail.latest;
-  $("#ai").innerHTML = a ? `<div class="big">${OC_JA[a.outcome]}</div><div>pick ${a.pick} / place ${a.place} ・ 素材 ${a.evidence || "なし"}</div><div class="muted">${esc(a.ai_reason)}</div>` : `<span class="muted">AI の判定はありません</span>`;
+  $("#ai").innerHTML = a ? `<div class="big">${OC_JA[a.outcome]}</div><div>${ppJa(a)} ・ 素材 ${a.evidence || "なし"}</div><div class="muted">${esc(a.ai_reason)}</div>` : `<span class="muted">AI の判定はありません</span>`;
   const h = detail.history.filter(r => HUMAN.includes(r.labeler)).pop();  // 人が確定した行 (依頼 187)
   const c = h || l;  // 札は 1 回だけ. 札・人が確定・時刻・pick / place を 1 行目に (依頼 190)
-  $("#cur").innerHTML = c ? `<div>${tag(c.outcome, c.labeler === "ai")} ${h ? "<b>人が確定済み</b>" : `<span class="muted">${LB_JA[c.labeler]}</span>`} ・ ${esc(c.labeled_at.slice(0, 10))} ${hm(c.labeled_at)} ・ pick ${c.pick} / place ${c.place}</div>${c.note ? `<div class="muted">${esc(c.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
+  $("#cur").innerHTML = c ? `<div>${tag(c.outcome, c.labeler === "ai")} ${h ? "<b>人が確定済み</b>" : `<span class="muted">${LB_JA[c.labeler]}</span>`} ・ ${esc(c.labeled_at.slice(0, 10))} ${hm(c.labeled_at)} ・ ${ppJa(c)}</div>${c.note ? `<div class="muted">${esc(c.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
   markOC();
-  $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>pick/place</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${tag(r.outcome, r.labeler === "ai")}</td><td>${r.pick}/${r.place}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
+  $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>つかむ/置く</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${tag(r.outcome, r.labeler === "ai")}</td><td>${esc(PICK_JA[r.pick] ?? r.pick)}/${esc(PLACE_JA[r.place] ?? r.place)}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
 }
 
 // ---- 関節と爪のグラフ (関節は 1 本の軸・爪は下に別の帯. 2 つの縦軸は使わない) ----
@@ -365,7 +369,11 @@ function markPP() {
   document.querySelectorAll("[data-pp]").forEach(b => b.classList.toggle("on", pp[b.dataset.pp] === b.dataset.v));
 }
 document.querySelectorAll("[data-pp]").forEach(b => b.onclick = () => {
-  const k = b.dataset.pp; pp[k] = pp[k] === b.dataset.v ? null : b.dataset.v; markPP(); b.blur();
+  const k = b.dataset.pp, prev = pp[k]; pp[k] = prev === b.dataset.v ? null : b.dataset.v;
+  // つかめなかった → 置くは自動でそこまで行かなかった (選び直せる). つかめなかったからつかめたに戻したら置くは選んでいない状態に (依頼 193)
+  if (k === "pick" && pp.pick === "no") pp.place = "not_applicable";
+  else if (k === "pick" && pp.pick === "yes" && prev === "no") pp.place = null;
+  markPP(); b.blur();
 });
 document.querySelectorAll("[data-oc]").forEach(b => b.onclick = () => { b.blur(); choose(b.dataset.oc); });
 $("#confirm").onclick = () => { $("#confirm").blur(); confirmChosen(); };
@@ -398,7 +406,7 @@ async function save(outcome) {
     if (!res.ok) { delete pendingOps[stem]; markOC(); status("書けませんでした: " + j.error, "err"); return; }
     saved = true;
     toast(`確定しました：${esc(stem)}${tag(outcome, false)}`);
-    status(`${stem} を「${OC_JA[outcome]}」で追記しました (${LB_JA[j.row.labeler]}・pick ${j.row.pick} / place ${j.row.place})`, "ok");
+    status(`${stem} を「${OC_JA[outcome]}」で追記しました (${LB_JA[j.row.labeler]}・${ppJa(j.row)})`, "ok");
     await loadRuns();
     // 同じ位置 (確定で一覧から消えたらそこに来た次の回) へ進む
     let next;
diff --git a/pi05/verdict_viewer/test_verdicts.py b/pi05/verdict_viewer/test_verdicts.py
index 106c984..7ab46a9 100644
--- a/pi05/verdict_viewer/test_verdicts.py
+++ b/pi05/verdict_viewer/test_verdicts.py
@@ -86,6 +86,15 @@ class TestAppend(unittest.TestCase):
                 V.append_rows([row("pi05_9", "success", "ai"), bad], self.csv)
         self.assertEqual(self.csv.read_bytes(), before, "まちがった行のときに途中まで書いた")
 
+    def test_place_not_applicable_only_for_place(self):
+        # 依頼 193: place は not_applicable (そこまで行かなかった) を書ける. pick には書けない
+        V.append_rows([row("pi05_1", "failure", "human_only", pick="no", place="not_applicable")], self.csv)
+        self.assertEqual(V.read_rows(self.csv)[-1]["place"], "not_applicable")
+        before = self.csv.read_bytes()
+        with self.assertRaises(ValueError):
+            V.append_rows([row("pi05_2", "failure", "human_only", pick="not_applicable", place="not_applicable")], self.csv)
+        self.assertEqual(self.csv.read_bytes(), before)
+
     def test_comma_and_newline_in_reason(self):
         V.append_rows([row("pi05_1", "failure", "ai", ai_reason='箱の外, "落とした"\n2 行目')], self.csv)
         self.assertEqual(V.read_rows(self.csv)[0]["ai_reason"], '箱の外, "落とした"\n2 行目')
@@ -342,6 +351,16 @@ class TestServer(unittest.TestCase):
         self.assertTrue(runs["pi05_20261001_000003"]["confirmed"])
         self.assertEqual(runs["pi05_20261001_000003"]["outcome"], "success")
 
+    def test_post_place_not_applicable(self):
+        # 依頼 193: 画面から place=not_applicable を送れる. pick=not_applicable は 400 で書かない
+        st, j = self.post({"run_stem": "pi05_20261001_000003", "outcome": "failure", "pick": "no", "place": "not_applicable"})
+        self.assertEqual(st, 200)
+        self.assertEqual((j["row"]["pick"], j["row"]["place"]), ("no", "not_applicable"))
+        before = self.csv.read_bytes()
+        st, j = self.post({"run_stem": "pi05_20261001_000003", "outcome": "failure", "pick": "not_applicable"})
+        self.assertEqual(st, 400)
+        self.assertEqual(self.csv.read_bytes(), before)
+
     def test_same_op_id_writes_once(self):
         n = len(V.read_rows(self.csv))
         b = {"op_id": "abc", "run_stem": "pi05_20261001_000003", "outcome": "failure"}
@@ -493,6 +512,36 @@ class TestConfirm192(unittest.TestCase):
         self.pg.wait_for_timeout(600)
         self.assertEqual(self.n_rows(), n)
 
+    # ---- 依頼 193: つかむ / 置くを日本語に・つかめなかったで置くは自動でそこまで行かなかった ----
+    def pp_on(self):
+        return self.pg.eval_on_selector_all("[data-pp].on", "e => e.map(x => x.dataset.pp + '=' + x.dataset.v)")
+
+    def test_pp_labels_are_japanese(self):
+        got = self.pg.eval_on_selector_all("[data-pp]", "e => e.map(x => x.dataset.pp + '=' + x.dataset.v + ':' + x.textContent)")
+        self.assertEqual(got, ["pick=yes:つかめた", "pick=no:つかめなかった", "pick=unknown:分からない",
+                               "place=yes:置けた", "place=no:置けなかった", "place=not_applicable:そこまで行かなかった",
+                               "place=unknown:分からない"])
+        self.assertEqual(self.pg.eval_on_selector_all("#panel .row .lbl", "e => e.map(x => x.textContent)"), ["つかむ", "置く"])
+
+    def test_pick_no_selects_place_not_applicable(self):
+        n = self.n_rows()
+        self.pg.click('[data-pp="pick"][data-v="no"]')
+        self.assertEqual(self.pp_on(), ["pick=no", "place=not_applicable"])
+        self.pg.click('[data-pp="place"][data-v="unknown"]')  # 選び直せる
+        self.assertEqual(self.pp_on(), ["pick=no", "place=unknown"])
+        self.pg.click('[data-pp="pick"][data-v="yes"]')  # つかめたに戻すと置くは選んでいない
+        self.assertEqual(self.pp_on(), ["pick=yes"])
+        self.pg.click('[data-pp="pick"][data-v="no"]')
+        self.pg.wait_for_timeout(300)
+        self.assertEqual(self.n_rows(), n)  # 選ぶだけでは書かない
+        stem = self.pg.text_content("#title")
+        self.pg.keyboard.press("n")
+        self.pg.keyboard.press("Enter")
+        self.pg.wait_for_timeout(1000)
+        rows = V.read_rows(self.csv)
+        self.assertEqual(len(rows), n + 1)
+        self.assertEqual((rows[-1]["run_stem"], rows[-1]["pick"], rows[-1]["place"]), (stem, "no", "not_applicable"))
+
 
 class TestRule185(unittest.TestCase):
     """エイイチの決め (2026-11-14 依頼 185): run_input も確定・送ったチャンク 0 → not_applicable・素材不足 → not_judgeable."""
diff --git a/pi05/verdict_viewer/verdicts.py b/pi05/verdict_viewer/verdicts.py
index e88a95e..ed520f3 100644
--- a/pi05/verdict_viewer/verdicts.py
+++ b/pi05/verdict_viewer/verdicts.py
@@ -27,6 +27,7 @@ VERDICTS_CSV = DATA_ROOT / "runs" / "pi05_policy_verdicts_v1.csv"
 COLUMNS = ["labeled_at", "run_stem", "pick", "place", "outcome", "labeler",
            "ai_outcome", "ai_reason", "evidence", "note"]
 PICK_PLACE = ("yes", "no", "unknown")
+PLACE_VALUES = PICK_PLACE + ("not_applicable",)  # つかめず place まで行かなかった回 (依頼 193. pick には足さない)
 OUTCOMES = ("success", "failure", "unknown", "not_judgeable", "not_applicable")
 AI_OUTCOMES = ("success", "failure", "unknown", "not_judgeable")  # AI が付けてよい outcome (not_applicable は rule だけ)
 LABELERS = ("run_input", "ai", "human", "human_fixed_ai", "human_only", "rule")
@@ -65,8 +66,10 @@ def validate_row(row):
             r[c] = r[c][:n] + "…"
     if not r["run_stem"]:
         raise ValueError("run_stem が空です")
-    if r["pick"] not in PICK_PLACE or r["place"] not in PICK_PLACE:
-        raise ValueError(f"pick / place は {PICK_PLACE} のどれか: {r['pick']!r} {r['place']!r}")
+    if r["pick"] not in PICK_PLACE:
+        raise ValueError(f"pick は {PICK_PLACE} のどれか: {r['pick']!r}")
+    if r["place"] not in PLACE_VALUES:
+        raise ValueError(f"place は {PLACE_VALUES} のどれか: {r['place']!r}")
     if r["outcome"] not in OUTCOMES:
         raise ValueError(f"outcome は {OUTCOMES} のどれか: {r['outcome']!r}")
     if r["labeler"] not in LABELERS:
```


### 依頼194 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 15
---
# 依頼194：判定の画面の行の頭の字を「pick」「place」に戻す

エイイチの指示（2026-11-14）：行の頭は pick / place のままでよい。依頼193 で「つかむ」「置く」に変えたのは頼まれていない変更だった。
pi05/verdict_viewer/index.html で、依頼193 の前に「pick」「place」と出ていた所（判定するの欄の行の頭、この回の行の表の見出し、今の判定の欄など）の見出しの字だけを「pick」「place」に戻す。ボタンの字（つかめた・置けた・そこまで行かなかった など）・値・動き・見た目はそのまま。ほかは一切変えない。

## やること
1. 上の見出しの字だけを戻す
2. 画面を立ち上げ直し（8765 番。ブラウザは開かない）、判定するの欄の写しを撮る。確かめで判定は書かない。既存のテストが通ること
3. index.html だけを指定して commit（git add . と git clean は使わない）。最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼194 で Claude Code が返した報告

```text
# 結果：20261114_194_行の頭をpickとplaceに戻す

- 状態：完了
- 始めた時刻：2026-11-14 23:25
- 終わった時刻：2026-11-14 23:27（2分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume c624385e-be74-4383-8ea0-31d243b841a2`

## Claude Code の報告

やったこと
- pi05/verdict_viewer/index.html で、依頼193 で「つかむ」「置く」に変えた見出しの字を「pick」「place」に戻しました。戻したのは次の所です。
  - 判定するの欄の行の頭 2 か所
  - 今の判定・AI の判定・確定したときの知らせの「pick ○○ / place ○○」（3 か所とも同じ部品を使っているので、直したのは 1 行）
  - この回の行の表の見出し「pick/place」
- ボタンの字（つかめた・置けた・そこまで行かなかった など）・値・動き・見た目は変えていません。
- 8765 番を立ち上げ直しました（ブラウザは開いていません）。判定するの欄の写しを logs/verdict_viewer_194_panel.png に置きました。確かめのあいだ判定は書いていません。
- index.html だけを指定して commit しました（13f6514）。作業のまとめを logs/20261114_1940.md に書きました。

結果
- 画面の行の頭は「pick」「place」になり、ボタンの字は依頼193 のままです。写しで確かめました。
- 既存のテストは 49 件中 48 件が通り、1 件が落ちています。落ちたのは test_pp_labels_are_japanese です。test_verdicts.py の 524 行目が、行の頭を依頼193 の字（つかむ・置く）のまま確かめています。今回の変更でそこが合わなくなりました。テストは index.html の外なので直していません。

変えたファイル
- pi05/verdict_viewer/index.html（4 行）
- logs/20261114_1940.md（作業のまとめ。新しく作成）
- logs/verdict_viewer_194_panel.png（写し。新しく作成）

決めてほしいこと
- test_verdicts.py 524 行目の確かめを、["つかむ", "置く"] から ["pick", "place"] に直してよいか。直せば 49 件とも通る見込みです。

判定：止めた（決めてほしいことあり）
```

### 依頼194 のコードの差分（コミット 13f6514）

```diff
commit 13f6514b892f34ce9293789b46b79239fd8b8563
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:27:30 2026 +0900

    判定の画面の行の頭の字を pick / place に戻す (依頼 194). index.html だけ. 依頼 193 で つかむ / 置く にした見出しを戻す: 判定するの欄の行の頭 2 か所・今の判定とAIの判定と知らせの「pick … / place …」・この回の行の表の見出し pick/place. ボタンの字 (つかめた・置けた・そこまで行かなかった など)・値・動き・見た目は変えない. テスト 49 中 48 OK, test_pp_labels_are_japanese の見出しの確かめ 1 件が古い字 (つかむ / 置く) を見ているため落ちる (テストは今回の範囲外で直していない). 8765 番で立ち上げ直し判定するの欄を撮った (判定は書いていない)
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index a9ca0ba..9f5d37e 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -141,9 +141,9 @@
     <button class="key" data-oc="unknown"><kbd>u</kbd> 分からない</button>
     <button class="key" data-oc="not_judgeable"><kbd>x</kbd> 判定できない</button>
   </div>
-  <div class="row"><span class="lbl">つかむ</span>
+  <div class="row"><span class="lbl">pick</span>
     <div class="seg"><button data-pp="pick" data-v="yes">つかめた</button><button data-pp="pick" data-v="no">つかめなかった</button><button data-pp="pick" data-v="unknown">分からない</button></div></div>
-  <div class="row"><span class="lbl">置く</span>
+  <div class="row"><span class="lbl">place</span>
     <div class="seg"><button data-pp="place" data-v="yes">置けた</button><button data-pp="place" data-v="no">置けなかった</button><button data-pp="place" data-v="not_applicable">そこまで行かなかった</button><button data-pp="place" data-v="unknown">分からない</button></div></div>
   <p class="note">選ばなければ 成功→つかめた・置けた / ほか→分からない</p>
   <button id="confirm" disabled>確定<kbd>Enter</kbd></button>
@@ -163,7 +163,7 @@ const OC_JA = {success: "成功", failure: "失敗", unknown: "分からない",
 // pick / place の値は yes / no / unknown (place だけ not_applicable も) のまま. 画面の字だけ日本語 (依頼 193)
 const PICK_JA = {yes: "つかめた", no: "つかめなかった", unknown: "分からない"};
 const PLACE_JA = {yes: "置けた", no: "置けなかった", not_applicable: "そこまで行かなかった", unknown: "分からない"};
-const ppJa = r => `つかむ ${esc(PICK_JA[r.pick] ?? r.pick)} / 置く ${esc(PLACE_JA[r.place] ?? r.place)}`;
+const ppJa = r => `pick ${esc(PICK_JA[r.pick] ?? r.pick)} / place ${esc(PLACE_JA[r.place] ?? r.place)}`;
 const LB_JA = {run_input: "記録時の入力", ai: "AI", human: "人 (AI と同じ)", human_fixed_ai: "人 (AI を直した)", human_only: "人 (AI なし)", rule: "決め (依頼185)", "": ""};
 const COLORS = ["--s1", "--s2", "--s3", "--s4", "--s5", "--s6"].map(v => getComputedStyle(document.documentElement).getPropertyValue(v).trim());
 const pendingOps = {};  // run_stem → 書けたか分からない操作 (回ごとに残す. codex 6 回目 R1)
@@ -291,7 +291,7 @@ function renderInfo() {
   const c = h || l;  // 札は 1 回だけ. 札・人が確定・時刻・pick / place を 1 行目に (依頼 190)
   $("#cur").innerHTML = c ? `<div>${tag(c.outcome, c.labeler === "ai")} ${h ? "<b>人が確定済み</b>" : `<span class="muted">${LB_JA[c.labeler]}</span>`} ・ ${esc(c.labeled_at.slice(0, 10))} ${hm(c.labeled_at)} ・ ${ppJa(c)}</div>${c.note ? `<div class="muted">${esc(c.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
   markOC();
-  $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>つかむ/置く</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${tag(r.outcome, r.labeler === "ai")}</td><td>${esc(PICK_JA[r.pick] ?? r.pick)}/${esc(PLACE_JA[r.place] ?? r.place)}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
+  $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>pick/place</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${tag(r.outcome, r.labeler === "ai")}</td><td>${esc(PICK_JA[r.pick] ?? r.pick)}/${esc(PLACE_JA[r.place] ?? r.place)}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
 }
 
 // ---- 関節と爪のグラフ (関節は 1 本の軸・爪は下に別の帯. 2 つの縦軸は使わない) ----
```


### 依頼195 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 10
---
# 依頼195：test_verdicts.py の行の頭の確かめを pick / place に合わせる

依頼194 の「決めてほしいこと」への答え：直してよい（エイイチの指示で行の頭を pick / place に戻したため）。
pi05/verdict_viewer/test_verdicts.py の 524 行目あたりの ["つかむ", "置く"] を ["pick", "place"] に直す。テストの名前 test_pp_labels_are_japanese の中身がボタンの日本語の確かめなら、名前はそのままでよい。ほかは変えない。
テストを全部回して通ることを確かめ、test_verdicts.py だけを指定して commit（git add . と git clean は使わない）。最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼195 で Claude Code が返した報告

```text
# 結果：20261114_195_テストの確かめをpickとplaceに合わせる

- 状態：完了
- 始めた時刻：2026-11-14 23:28
- 終わった時刻：2026-11-14 23:29（1分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 0b77fc2a-9009-497c-a483-9dba93ab63bd`

## Claude Code の報告

やったこと：
- `pi05/verdict_viewer/test_verdicts.py` の 524 行目で、行の頭を確かめる期待値を ["つかむ", "置く"] から ["pick", "place"] に変えました。変えたのはこの 1 行だけです。
- テストの名前 `test_pp_labels_are_japanese` は変えていません。中身の大半は、ボタンの字（つかめた・置けた・そこまで行かなかった など）が日本語かを確かめるものだからです。
- テストを全部回したあと、`test_verdicts.py` だけを指定して add し、commit しました（`git add .` と `git clean` は使っていません）。
- 作業のまとめを `logs/20261114_2329.md` に書きました。

結果：
- テスト 49 件すべて通りました（`python3 -m unittest test_verdicts`、18.6 秒）。
- commit は `bd613b5` で、変わったのは 1 ファイル（足した行 1・消した行 1）です。

変えたファイル：
- `pi05/verdict_viewer/test_verdicts.py`
- `logs/20261114_2329.md`（作業のまとめ、新しく作ったファイル。commit には入れていません）

決めてほしいこと：なし

判定：合格
```

### 依頼195 のコードの差分（コミット bd613b5）

```diff
commit bd613b5d104650152a706553c3006ac50aa142d7
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:29:27 2026 +0900

    判定の画面のテストで行の頭の確かめを pick / place に合わせる (依頼 195). test_verdicts.py の test_pp_labels_are_japanese で #panel .row .lbl の期待値を [つかむ, 置く] から [pick, place] に直すだけ (依頼 194 で行の頭を pick / place に戻したため). テストの名前・ボタンの日本語の確かめ・ほかのテストは変えない. テスト 49 OK
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/test_verdicts.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pi05/verdict_viewer/test_verdicts.py b/pi05/verdict_viewer/test_verdicts.py
index 7ab46a9..658efb6 100644
--- a/pi05/verdict_viewer/test_verdicts.py
+++ b/pi05/verdict_viewer/test_verdicts.py
@@ -521,7 +521,7 @@ class TestConfirm192(unittest.TestCase):
         self.assertEqual(got, ["pick=yes:つかめた", "pick=no:つかめなかった", "pick=unknown:分からない",
                                "place=yes:置けた", "place=no:置けなかった", "place=not_applicable:そこまで行かなかった",
                                "place=unknown:分からない"])
-        self.assertEqual(self.pg.eval_on_selector_all("#panel .row .lbl", "e => e.map(x => x.textContent)"), ["つかむ", "置く"])
+        self.assertEqual(self.pg.eval_on_selector_all("#panel .row .lbl", "e => e.map(x => x.textContent)"), ["pick", "place"])
 
     def test_pick_no_selects_place_not_applicable(self):
         n = self.n_rows()
```


![pick と place のボタンを日本語にし、place に「そこまで行かなかった」を足した右のパネル](https://pixelstomotors.com/media/LOG512_06_pick_place_japanese.png)


## 依頼198：絞り込みの矢印を太くし、右に余白をつける


### 依頼198 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 15
---
# 依頼198：判定の画面の絞り込み（#filter）の矢印を太くし、右に余白をつける

エイイチの指示（2026-11-15）：左上の絞り込みの選択欄の矢印をもう少し太く、右側に余白をつける。
pi05/verdict_viewer/index.html の #filter の見た目だけを変える。枠の色・太さ・角丸・字・高さ・動き・ほかの部品は変えない。

## やること
1. #filter を appearance: none にして、ブラウザの矢印の代わりに CSS の背景で下向きの山形の矢印（SVG。線の太さ 2px・色は --ink #1d1d1b・幅 12px ほど）を右に置く
2. 矢印の位置は右端から 14px ほど内側（background-position: right 14px center）。字が矢印に重ならないように padding-right を 40px ほどにする
3. 画面を立ち上げ直し（8765 番。ブラウザは開かない）、絞り込みの所の写し（拡大）を撮る。確かめで判定は書かない。既存のテストが通ること
4. index.html だけを指定して commit（git add . と git clean は使わない）。最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼198 で Claude Code が返した報告

```text
# 結果：20261115_198_絞り込みの矢印を太くし右に余白をつける

- 状態：完了
- 始めた時刻：2026-11-15 06:49
- 終わった時刻：2026-11-15 06:52（2分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 797006f9-6570-431c-9576-005bc60ffd81`

## Claude Code の報告

やったこと
判定の画面の絞り込み欄（#filter）の見た目を `pi05/verdict_viewer/index.html` の中だけで変えました。
- ブラウザの矢印を消し（appearance: none）、代わりに CSS の背景で下向きの山形の矢印を置きました。線の太さは 2px、色は #1d1d1b、大きさは幅 12px・高さ 8px です。
- 矢印の位置は右端から 14px 内側です。字が矢印にかからないよう、右の余白（padding-right）を 40px にしました。
- ブラウザの矢印を消しただけで欄の高さが 33px から 31.5px に縮みました。依頼で高さは変えないことになっているので、height: 33px を足して元の高さに戻しました。
- 枠の色・太さ・角丸・字・動きは変えていません。
- 8765 番の画面をブラウザを開かずに立ち上げ直し、絞り込みの所を 3 倍に拡大して撮りました。判定は書いていません。
- index.html だけを指定して commit しました（0783fd4）。git add . と git clean は使っていません。

結果
- 既存のテストは 49 件すべて通りました。
- 欄の高さは 33px で、変える前と同じです。
- 拡大した写しでは、矢印が太い山形で右側に余白があり、字にも重なっていませんでした。写しは `claude_code_reports/198_filter_zoom.png` です。
- 作業の記録を `logs/20261115_0652.md` に残しました（git には入れていません）。

変えたファイル
- `pi05/verdict_viewer/index.html`

決めてほしいこと
なし

判定：合格
```

### 依頼198 のコードの差分（コミット 0783fd4）

```diff
commit 0783fd4bc6345f25e2d7dcaf14fef0221fa751da
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sun Nov 15 06:52:09 2026 +0900

    判定の画面の絞り込み (#filter) の矢印を太くし右に余白をつける (依頼 198). index.html だけ. appearance: none にしてブラウザの矢印の代わりに背景の SVG の山形 (線 2px・色 #1d1d1b・幅 12px) を右端から 14px 内側に置き, padding-right を 40px に. appearance: none で高さが 33px から 31.5px に縮んだため height: 33px で元の高さに合わせた. 枠の色・太さ・角丸・字・動きは変えない. テスト 49 OK. 8765 番で立ち上げ直し絞り込みの所を拡大して撮った (判定は書いていない)
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/verdict_viewer/index.html | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/pi05/verdict_viewer/index.html b/pi05/verdict_viewer/index.html
index 9f5d37e..8a5281b 100644
--- a/pi05/verdict_viewer/index.html
+++ b/pi05/verdict_viewer/index.html
@@ -20,7 +20,9 @@
   #side { min-height: 0; background: #fff; border-right: 1px solid var(--line); display: flex; flex-direction: column; }
   #side header { padding: 16px; border-bottom: 1px solid var(--line); }
   #side h1 { margin: 0 0 8px; font-size: 15px; }
-  #filter { width: 100%; font: inherit; border: 1px solid var(--line); background: #fff; border-radius: 6px; padding: 5px 6px; color: var(--ink); cursor: pointer; }
+  #filter { width: 100%; font: inherit; border: 1px solid var(--line); border-radius: 6px; padding: 5px 40px 5px 6px; color: var(--ink); cursor: pointer;
+    appearance: none; -webkit-appearance: none; height: 33px;  /* ブラウザの矢印の代わりに太い山形. 高さは元の 33px のまま (依頼 198) */
+    background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%231d1d1b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 14px center / 12px 8px; }
   #count { color: var(--sub); margin-top: 6px; font-size: 11px; }
   #list { overflow-y: auto; flex: 1; }
   .item { padding: 6px 16px; border-bottom: 1px solid var(--line); cursor: pointer; display: flex; justify-content: space-between; gap: 6px; }
```


![絞り込みの選択欄。矢印を太くし、右端から内側に寄せた](https://pixelstomotors.com/media/LOG512_07_filter_arrow.png)


## 176回の判定を終えた結果

判定のファイル（`runs/pi05_policy_verdicts_v1.csv`）は、この時点で298行・176回です。回ごとに、人の確定があればその行、なければ決まりや記録したときの入力の行を正にして数えました。

| 今の判定 | 回数 |
|---|---|
| 成功 | 55 |
| 失敗 | 37 |
| 試行でない（アームを動かしていない） | 50 |
| 判定できない | 33 |
| 分からない | 1 |

| だれが確定したか | 回数 |
|---|---|
| 記録したときの入力 | 68 |
| 決まり（依頼185） | 83 |
| 人が画面で確定（AI と同じ） | 20 |
| 人が画面で確定（AI を直した） | 5 |

- 成功率（成功 ÷ 成功と失敗）は 59.8%（55/92）。10月は 63%（20/32）、11月は 58%（35/60）
- 人が見た25回のうち、AI の先回り判定と同じだったのは20回（8割）。違ったのは、AI が成功→人が失敗が2回、AI が失敗→人が成功が2回、AI が判定できない→人が分からないが1回
- 人の行は38行で、25回分。見直して付け直した回がある（新しい行が正）

AI の判定は下書きとしては役に立ちますが、確定に使うには外れが多い、という結果です。


## 依頼196：補ったコマに1コマごとの印を付け、既存のお手本を数えた

補正のお手本を作る `build_correction_episodes.py` は、送信中に角度が読めなかった間（約1.6秒）を、前後の実測を結ぶ直線で埋めて `state` に入れていました。どのコマが埋めた値かは残っていませんでした。そこで、1コマごとの印 `state_source` を足し、既存のデータセットは書き換えずに、元の記録から印だけを作り直して数えました。


### 依頼196 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 90
---
# 依頼196：補正エピソードの 1 コマごとに「実測か・埋めた値か」の印を残す

実機は動かさない（記録を読むだけ）。フィジカルAI研究室のデータ集めや補正の道具の直し。
エイイチの決め（2026-11-14）：データの質の分析で挙げた「実測角の抜けを埋めた値に、1 コマずつ印がない」を直す。

## なぜ
pi05/build_correction_episodes.py は、送信中に実測角が抜けた所（約 1.6 秒）を fill_motion_gaps（--gap-fill speed20 / linear）で埋めて state に入れている。meta.json には gap_fill の件数（gaps・motion_gaps・unmatched など）しか残らず、episode.npz（t・t_orig・state・actions）からは、どのコマが実測でどのコマが埋めた値か分からない。学習に効くデータの質を後から測れない。

## 守ること
- 既存のデータセット（datasets/ の中）は上書き・移動・削除しない。新しく作り直すこともしない（今回は道具の直しと、測るだけ）
- state・actions の値は 1 つも変えない。今のコードと同じ引数で作ったときに state・actions・t がバイト単位で同じになることをテストで確かめる
- 書き込み先は保存先テーブルどおり。測った結果は diag/ に置く（KIOXIA のマウントを確かめ、なければ止める）

## やること
1. build_correction_episodes.py
   - 1 コマごとの印 state_source（int8）を作る：0 = 実測角をそのまま使ったコマ／1 = 抜けを埋めた値のコマ（fill_motion_gaps が作った値）。ほかの区別（例：前後のコマから補った値など）がコードにあれば番号を足し、意味を報告に書く
   - episode.npz に state_source を足す（ほかのキーはそのまま）。meta.json に filled_steps（埋めたコマの数）と filled_ratio（全コマに対する割合）を足す
   - README の作り方の説明に、印の意味を 1 段落足す
2. convert_to_lerobot.py ほか episode.npz を読むコードが、新しいキーがあっても今までどおり動くことを確かめる（直さずに済むなら直さない。直したら報告に書く）
3. 既存の補正データセットを測る（書き換えない）
   - 対象：datasets/ の名前に corr が入るもの（mecharm_redblock_box_corr_v1〜v5・v4b・teach_v1_trim2_corr_v*・deep_even10_v1 の補正入りの本 など）。元の runs/pi05_policy/{run_stem}/ を読むだけで、各データセットの meta.json の作り方（gap_fill の mode・trim など）と同じ条件で、印だけを /tmp で作り直して数える
   - 作り直した state が、データセットに入っている state と一致するかも確かめる（一致しなければ、その本は数えずに報告に書く）
   - 結果を diag/fill_flags_20261114/ に CSV で置く（データセット・本・全コマ・埋めたコマ・割合）と、データセットごとのまとめ（本数・全コマ・埋めたコマ・割合・いちばん多い本）
4. 手教示のデータセット（teach_v1 系・teach_pos1to4_deep_v1）と scripted_v1 にも、同じような「埋めた値」があるかをコードから確かめて報告に書く（直さない）
5. テスト（印の数が meta の gap_fill の件数と矛盾しないこと・state/actions/t が今と同じこと）。codex のレビューを 1 回。変えたファイルだけを指定して commit（git add . と git clean は使わない）

## 報告に書くこと
- 印の番号と意味
- データセットごとの、埋めたコマの割合（表）。学習に使ったことがあるデータセット（corr_v5・deep_even10_v1 など）を先に
- 手教示・scripted に埋めた値があるか
- 最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼196 で Claude Code が返した報告

```text
# 結果：20261114_196_補正エピソードの1コマごとに埋めた値の印を残す

- 状態：完了
- 始めた時刻：2026-11-14 23:31
- 終わった時刻：2026-11-14 23:53（22分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 33911490-06b8-4595-a4f2-9b2e50a3158e`

## Claude Code の報告

**やったこと**
- `pi05/build_correction_episodes.py` に、1 コマごとの印 `state_source`（int8）を作る処理を足しました。`episode.npz` に `state_source` を入れ、`meta.json` に次の 4 つを足しました。README の作り方の説明にも、印の意味を 1 段落足しました。
  - `filled_steps`（埋めたコマの数）
  - `filled_motion_steps`（そのうち動いた抜けのコマの数）
  - `filled_ratio`（全コマに対する割合）
  - `state_source_codes`（番号の意味）
- 印の番号と意味:
  - 0 = 実測角。0.25 秒以内の前後の実測角をまっすぐ結んだ値で、ふだんは 0.1 秒おきに読めています。
  - 1 = 動いた抜け（前後の実測角の差が 0.5° を超える）の中を、`fill_motion_gaps` が埋めた値。
  - 2 = 動かなかった抜け（爪の送信など）の中を埋めた値。コードに「動いた抜け」と「動かなかった抜け」の区別があったので、番号を 1 つ足しました。
  - 印は関節 6 列についてのものです。爪の列はいつも指令の値です。actions の関節は次のコマの state なので、その出どころは次のコマの印で分かります。
- 直したところがもう 1 つあります。`check_compat`（`--check-with` でお手本と比べる所）は、お手本にない `state_source` のキーを「キーが違う」と数えないようにしました。直さないと、`--check-with` が新しいキーのせいで不合格を出すためです。
- `convert_to_lerobot.py`・`check_dataset.py`・`eval_policy_offline.py`・`merge_raw_episodes.py` などは、`state`・`actions`・`t_orig` をキーの名前で読むか、フォルダをそのまま写すだけです。新しいキーがあっても今までどおり動くので、直していません。
- 測る道具 `pi05/diag_fill_flags.py` を新しく作りました。元の `runs/pi05_policy` から各エピソードの `meta.json` と同じ条件で /tmp に作り直して数えます。データセットには書き込んでいません。
- codex のレビューを 1 回受けました。本体の不具合はなしで、`diag_fill_flags.py` の P2 が 1 件（対象が 0 本だと落ちる）でした。これは直しました。

**結果**
- テスト: 新しい `test_state_source.py` の 6 件はすべて通りました。実データ 2 本を 3 条件で、直す前（HEAD）と今のコードで作り、`state`・`actions`・`t`・`t_orig` がバイト単位で同じことを確かめました。印のつながりの数が meta の `gaps`・`motion_gaps` を超えないことも確かめています。pi05 のテストは 25 ファイルすべて OK です。
- 既存の補正データセット 14 個・95 本を作り直したところ、全本で state・actions・t がデータセットの中身と一致しました。数えなかった本はありません。

| データセット | 本数 | 全コマ | 埋めたコマ（うち動いた抜け） | 割合 | 割合がいちばん多い本 |
|---|---|---|---|---|---|
| teach_v1_trim2_corr_v5（学習に使用） | 11 | 1584 | 655 (624) | 41.4% | pi05_20261031_175527（76.3%） |
| deep_even10_v1（学習に使用） | 6 | 884 | 385 (366) | 43.6% | 同上（76.3%） |
| teach_v1_trim2_corr_v5_deep | 7 | 1029 | 478 (455) | 46.5% | 同上（76.3%） |
| corr_v1 / trim2_corr_v1 | 5 | 1469 | 1365 (1354) | 92.9% | 同上（95.8%） |
| corr_v2 / trim2_corr_v2 | 5 | 1159 | 922 (900) | 79.6% | 同上（83.9%） |
| corr_v3 / trim2_corr_v3 | 5 | 726 | 514 (497) | 70.8% | 同上（76.3%） |
| corr_v4 / trim2_corr_v4 | 8 | 1090 | 754 (729) | 69.2% | 同上（76.3%） |
| corr_v4b / trim2_corr_v4b | 7 | 893 | 629 (607) | 70.4% | 同上（76.3%） |
| corr_v5 | 11 | 1584 | 655 (624) | 41.4% | 同上（76.3%） |

- 2026-11-06 に記録した 4 本は埋めた割合が 2〜5% と低く、10 月 31 日・11 月 1 日の本は 57〜96% です。

**手教示・scripted に埋めた値があるか**
- あります。印はありません（直していません）。
- `build_demo_episodes.py` は、実測角の間がどれだけ長くても前後をまっすぐ結んでいます。これは補正の `--gap-fill linear` と同じ埋め方です。
- 元の記録では、実測角はふだん約 0.32 秒おきにしか読めていません。補正と同じ「0.25 秒より長い間」の決まりで数えると、10Hz のコマのほぼ全部（98.8〜99.4%）が抜けになります。
- 1 秒を超える間だけを見ると、全体の時間に対して次の割合です（どちらも詰める前の時間軸で数えた値）。
  - teach_v1_trim2・teach_pos1to4_deep_v1: 62%
  - scripted_v1: 93%（最大の間は 212 秒）

**変えたファイル**
- `pi05/build_correction_episodes.py`（直した）
- `pi05/test_state_source.py`（新しく作った）
- `pi05/diag_fill_flags.py`（新しく作った）
- commit は 18e579c です。3 つのファイルだけを指定して add しました。
- 測った結果は `/Volumes/KIOXIA/r2r2r-data/diag/fill_flags_20261114/` にあります: `episodes.csv`・`summary.csv`・`README.md`・`teach_scripted.txt`・`codex_review.txt`。
- 作業の記録として `logs/20261114_2353.md` も置きました（commit はしていません）。

**決めてほしいこと**
- 手教示・scripted の印の決まり: ふだんの読み取りが約 0.32 秒おきなので、補正と同じ 0.25 秒の決まりは使えません。印を付けるなら「何秒より長い間を抜けとみなすか」をエイイチが決める必要があります（今回は直していません）。
- 既存の補正データセットに `state_source` を付けて作り直すかどうか（今回は作り直していません）。

判定：止めた（決めてほしいことあり）
```

### 依頼196 のコードの差分（コミット 18e579c）

```diff
commit 18e579c9f0ef4793e24cf84d988990fd51cf945e
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sat Nov 14 23:52:49 2026 +0900

    補正エピソードの 1 コマごとに実測か埋めた値かの印 state_source を残す (依頼 196)
    
    build_correction_episodes.py: gap_fill_flags で state_source (int8. 0 実測 / 1 動いた抜けを埋めた値 /
    2 動かなかった抜けを埋めた値) を作り episode.npz に足す. meta.json に filled_steps / filled_motion_steps /
    filled_ratio / state_source_codes. README に印の説明. check_compat はお手本にない state_source を
    キーの違いとして数えない. state / actions / t / t_orig は直す前とバイト単位で同じ (test_state_source.py).
    diag_fill_flags.py: 既存の補正データセットを /tmp で作り直して印を数え, diag/fill_flags_20261114/ に CSV.
    データセットは書き換えていない. 補正エピソード 95 本 (14 データセット)すべて state / actions / t が一致.
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 pi05/build_correction_episodes.py |  39 +++++++++-
 pi05/diag_fill_flags.py           | 132 +++++++++++++++++++++++++++++++++
 pi05/test_state_source.py         | 152 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 321 insertions(+), 2 deletions(-)

diff --git a/pi05/build_correction_episodes.py b/pi05/build_correction_episodes.py
index e5bce79..ae813b3 100644
--- a/pi05/build_correction_episodes.py
+++ b/pi05/build_correction_episodes.py
@@ -16,6 +16,7 @@
   - 使うのは 結果が「成功」(y) の run だけ
   - 時間軸は 10Hz. state は実測角の線形補間 + グリッパーは指令の時刻で 0/1 (build_demo_episodes と同じ)
     実測角の抜け (送信中) は --gap-fill で埋める (linear = corr_v1 / speed20 = corr_v2. 依頼 46)
+    埋めたコマには episode.npz の state_source で印を残す (0 実測 / 1 動いた抜け / 2 動かなかった抜け. 依頼 196)
   - 学習に使うのは状態が model / correct のステップだけ. rewind / home / wait (確認の入力待ち.
     人がブロックを置き直すと手が写る) / regrip (補正の R で開いてから閉じ終わるまで. 2026-10-30 依頼 35)
     のステップと,
@@ -176,6 +177,26 @@ def fill_motion_gaps(t, at, aq, mode="speed20", gap_sec=GAP_SEC, speed=SPEED20_D
     return q, gaps
 
 
+# ---- 1 コマごとの state の出どころ (state_source. int8. 2026-11-14 依頼 196) ----
+# 関節 6 列が実測角か, fill_motion_gaps が抜けを埋めた値かの印. 爪の列は指令なのでどれでも同じ
+SRC_MEASURED = 0     # 実測角 (0.25 秒以内の前後の実測角の線形補間. ふだんは 0.1 秒おき)
+SRC_FILLED_MOVE = 1  # 動いた抜け (前後の実測角の差 > GAP_MOVE_MIN_DEG) の中を埋めた値
+SRC_FILLED_STILL = 2  # 動かなかった抜け (差 <= GAP_MOVE_MIN_DEG. 爪の送信など) の中を埋めた値
+STATE_SOURCE_CODES = {SRC_MEASURED: "measured", SRC_FILLED_MOVE: "filled_motion_gap",
+                      SRC_FILLED_STILL: "filled_still_gap"}
+
+
+def gap_fill_flags(t, at, aq, gap_sec=GAP_SEC, min_move=GAP_MOVE_MIN_DEG):
+    """時刻 t のコマごとの state_source (int8). fill_motion_gaps と同じ「抜け」(実測角の間が gap_sec より長い
+    [ta, tb]) の中 (ta < t < tb) が埋めた値. 埋め方 (linear / speed20) によらず同じ印になる."""
+    src = np.zeros(len(t), dtype=np.int8)
+    for i in np.flatnonzero(np.diff(at) > gap_sec):
+        ta, tb = at[i], at[i + 1]
+        moved = float(np.max(np.abs(aq[i + 1] - aq[i]))) > min_move
+        src[(t > ta) & (t < tb)] = SRC_FILLED_MOVE if moved else SRC_FILLED_STILL
+    return src
+
+
 def logged_sends(log):
     """log.jsonl から, 送った目標とそのときの時刻の手がかりを集める.
 
@@ -443,9 +464,12 @@ def build_one(run_dir, out_dir, args):
         return {"run": stem, "used": False,
                 "reason": f"フレーム抽出不足 written={written} steps={len(tt)} (mp4 と frame_log の不一致)"}
 
+    state_source = gap_fill_flags(t, at, aq)[sel["idx"]]
     np.savez_compressed(out_dir / "episode.npz",
                         t=(np.arange(len(tt)) / FPS).astype(np.float64),
-                        t_orig=tt - tt[0], state=sel["state"], actions=sel["actions"])
+                        t_orig=tt - tt[0], state=sel["state"], actions=sel["actions"],
+                        state_source=state_source)
+    filled = int((state_source != SRC_MEASURED).sum())
     c = sel["counts"]
     meta = {
         "run_stem": stem, "task": bde.TASK, "fps": FPS, "steps": int(len(tt)),
@@ -475,6 +499,11 @@ def build_one(run_dir, out_dir, args):
         "gap_fill": {"mode": gap_fill, "gap_sec": GAP_SEC,
                      "speed_deg_per_sec": SPEED20_DEG_PER_SEC if gap_fill == "speed20" else None,
                      "gaps": len(gaps), **gap_match},
+        # 依頼 196: episode.npz の state_source (コマごとの印) の数
+        "filled_steps": filled,
+        "filled_motion_steps": int((state_source == SRC_FILLED_MOVE).sum()),
+        "filled_ratio": round(filled / len(tt), 4),
+        "state_source_codes": {str(k): v for k, v in STATE_SOURCE_CODES.items()},
         "max_step_deg": [round(float(v), 2) for v in
                          (np.abs(np.diff(sel["state"][:, :6], axis=0)).max(axis=0) if len(sel["state"]) > 1
                           else np.zeros(6))],
@@ -506,7 +535,8 @@ def check_compat(ours, ref):
     for ep in a:
         m = json.loads((ep / "meta.json").read_text())
         z = np.load(ep / "episode.npz")
-        if sorted(z.files) != sorted(rz.files):
+        # 依頼 196: state_source (コマごとの印) はお手本にないキー. 読む側は state / actions しか使わないので比べない
+        if sorted(set(z.files) - {"state_source"}) != sorted(set(rz.files) - {"state_source"}):
             probs.append(f"{ep.name}: npz のキー {sorted(z.files)} != お手本 {sorted(rz.files)}")
         for k in ("state", "actions"):
             if z[k].dtype != rz[k].dtype or z[k].shape[1:] != rz[k].shape[1:]:
@@ -554,6 +584,11 @@ def write_readme(ds, results, args):
         + ("前後の実測角をまっすぐ結ぶ (linear)" if args.gap_fill == "linear" else
            f"抜けの頭から速度 20 の速さ ({SPEED20_DEG_PER_SEC:.0f}°/秒. いちばん大きく動く関節) で前後の実測角を結ぶ"
            "直線を進み, 着いたら止まる (speed20)"),
+        "- 1 コマごとの state の出どころを episode.npz の `state_source` (int8. state と同じ長さ) に残す: "
+        "0 = 実測角 (0.25 秒以内の前後の実測角の線形補間) / 1 = 動いた抜け (前後の実測角の差が "
+        f"{GAP_MOVE_MIN_DEG}° を超える) の中を上の埋め方で埋めた値 / 2 = 動かなかった抜け (爪の送信など) の中を埋めた値。"
+        "印は関節 6 列のもの (爪の列はいつも指令)。actions の関節は次のコマの state なので, その出どころは次のコマの印。"
+        "meta.json の filled_steps (1 と 2 のコマの数) / filled_motion_steps (1 の数) / filled_ratio (全コマに対する 1 と 2 の割合)",
         "- 戻りきれなかった巻き戻しがある run は使わない (前後の姿勢が続かない)",
     ]
     if getattr(args, "max_protrude_px", None) is not None:
diff --git a/pi05/diag_fill_flags.py b/pi05/diag_fill_flags.py
new file mode 100644
index 0000000..4402ca4
--- /dev/null
+++ b/pi05/diag_fill_flags.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+"""diag_fill_flags.py — 既存の補正データセットで, 実測角の抜けを埋めたコマの割合を測る (2026-11-14 依頼 196).
+
+datasets/ の名前に corr / deep_even10 が入るデータセットの, 補正エピソード (meta.json の source が pi05_policy)
+ごとに, 元の runs/pi05_policy/{run_stem}/ から build_correction_episodes.build_one を meta.json と同じ条件
+(gap_fill の mode・trim_mid_idle・trim_hold) で /tmp に作り直し, state_source (コマごとの印) を数える.
+作り直した state / actions / t がデータセットの episode.npz と一致しない本は数えない (理由を CSV に残す).
+
+データセット・元の記録は読むだけ (書かない). 書くのは /tmp と diag/fill_flags_20261114/ だけ.
+
+  python3 pi05/diag_fill_flags.py
+"""
+import argparse
+import csv
+import json
+import sys
+from pathlib import Path
+from types import SimpleNamespace
+
+import numpy as np
+
+_HERE = Path(__file__).resolve().parent
+sys.path.insert(0, str(_HERE))
+
+import build_correction_episodes as bce  # noqa: E402
+import build_demo_episodes as bde  # noqa: E402
+
+OUT_NAME = "fill_flags_20261114"
+TMP_ROOT = Path("/tmp") / OUT_NAME
+# 学習に使ったことがあるデータセットを先に並べる (依頼 196)
+TRAINED_FIRST = ("mecharm_redblock_box_teach_v1_trim2_corr_v5", "mecharm_redblock_box_deep_even10_v1",
+                 "mecharm_redblock_box_teach_v1_trim2_corr_v5_deep")
+
+
+def target_datasets(ds_root):
+    names = sorted(p.name for p in ds_root.iterdir()
+                   if p.is_dir() and not p.name.startswith(".") and ("corr" in p.name or "deep_even10" in p.name))
+    return sorted(names, key=lambda n: (n not in TRAINED_FIRST, TRAINED_FIRST.index(n) if n in TRAINED_FIRST else 0, n))
+
+
+def rebuild(run_stem, meta, cache):
+    """meta.json と同じ条件で /tmp に作り直す. 戻り値: (npz の中身 dict / None, 理由)."""
+    gf = meta.get("gap_fill") or {}
+    key = (run_stem, gf.get("mode"), bool(meta.get("trim_mid_idle")), meta.get("trim_hold") is not None)
+    if key in cache:
+        return cache[key]
+    out = TMP_ROOT / "rebuild" / "_".join(str(k) for k in key) / run_stem
+    args = SimpleNamespace(gap_fill=gf.get("mode") or "linear", trim_hold=key[3],
+                           no_trim_mid_idle=not key[2], max_protrude_px=None, force=True)
+    res = bce.build_one(bce.RUNS_ROOT / run_stem, out, args)
+    if not res.get("used"):
+        cache[key] = (None, f"作り直せない: {res.get('reason')}")
+    else:
+        z = np.load(out / "episode.npz")
+        cache[key] = ({k: z[k] for k in z.files}, "ok")
+    return cache[key]
+
+
+def main():
+    ap = argparse.ArgumentParser()
+    ap.add_argument("--dataset", action="append", help="このデータセットだけ (複数可)")
+    args = ap.parse_args()
+    bde.ensure_ssd()
+    ds_root = bde.DATA_ROOT / "datasets"
+    out_dir = bde.DATA_ROOT / "diag" / OUT_NAME
+    if out_dir.exists():
+        sys.exit(f"[ABORT] 出力先がもうある: {out_dir}")
+    names = args.dataset or target_datasets(ds_root)
+    rows, cache = [], {}
+    for name in names:
+        for mp in sorted((ds_root / name / "raw_episodes").glob("[!.]*/meta.json")):
+            meta = json.loads(mp.read_text())
+            if not str(meta.get("source", "")).startswith("pi05_policy"):
+                continue
+            ep = mp.parent
+            stem = meta.get("run_stem", ep.name)
+            z = np.load(ep / "episode.npz")
+            row = {"dataset": name, "episode": ep.name, "run_stem": stem,
+                   "gap_fill": (meta.get("gap_fill") or {}).get("mode"),
+                   "trim_hold": meta.get("trim_hold") is not None, "steps": len(z["state"]),
+                   "filled_steps": "", "filled_motion_steps": "", "filled_ratio": "",
+                   "gaps": (meta.get("gap_fill") or {}).get("gaps"),
+                   "motion_gaps": (meta.get("gap_fill") or {}).get("motion_gaps"), "status": ""}
+            new, why = rebuild(stem, meta, cache)
+            if new is None:
+                row["status"] = why
+            elif not all(k in new and new[k].shape == z[k].shape and new[k].tobytes() == z[k].tobytes()
+                         for k in ("state", "actions", "t")):
+                row["status"] = "state が一致しない (数えない)"
+            else:
+                src = new["state_source"]
+                n_f = int((src != bce.SRC_MEASURED).sum())
+                row.update(filled_steps=n_f, filled_motion_steps=int((src == bce.SRC_FILLED_MOVE).sum()),
+                           filled_ratio=round(n_f / len(src), 4), status="ok")
+            rows.append(row)
+            print(f"{name}  {ep.name}  {row['status']}  {row['filled_steps']}/{row['steps']}")
+
+    if not rows:   # codex P2: 出力先を作る前に止める (空のまま作ると次に走らせられない)
+        sys.exit("[ABORT] 対象の補正エピソードがない")
+    out_dir.mkdir(parents=True)
+    with (out_dir / "episodes.csv").open("w", newline="") as f:
+        w = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
+        w.writeheader(); w.writerows(rows)
+    summ = []
+    for name in names:
+        rs = [r for r in rows if r["dataset"] == name]
+        ok = [r for r in rs if r["status"] == "ok"]
+        steps = sum(r["steps"] for r in ok); filled = sum(r["filled_steps"] for r in ok)
+        top = max(ok, key=lambda r: r["filled_ratio"]) if ok else None
+        summ.append({"dataset": name, "corr_episodes": len(rs), "counted": len(ok),
+                     "not_counted": len(rs) - len(ok), "steps": steps, "filled_steps": filled,
+                     "filled_motion_steps": sum(r["filled_motion_steps"] for r in ok),
+                     "filled_ratio": round(filled / steps, 4) if steps else "",
+                     "max_episode": top["episode"] if top else "",
+                     "max_episode_ratio": top["filled_ratio"] if top else ""})
+    with (out_dir / "summary.csv").open("w", newline="") as f:
+        w = csv.DictWriter(f, fieldnames=list(summ[0].keys()))
+        w.writeheader(); w.writerows(summ)
+    (out_dir / "README.md").write_text(
+        "# fill_flags_20261114 (依頼 196)\n\n"
+        "既存の補正データセットで, 実測角の抜けを埋めたコマ (state_source が 1 または 2) の数と割合。\n"
+        "`python3 pi05/diag_fill_flags.py` で作った。データセットは読むだけ。作り直しは /tmp。\n\n"
+        "- state_source: 0 = 実測角 / 1 = 動いた抜けを埋めた値 / 2 = 動かなかった抜けを埋めた値\n"
+        "- filled_ratio = (1 と 2 のコマ) / 全コマ。filled_motion_steps は 1 のコマの数\n"
+        "- status が ok でない本 (作り直した state / actions / t がデータセットと一致しない・作り直せない) は数えない\n"
+        "- episodes.csv: 本ごと / summary.csv: データセットごと (max_episode = 割合がいちばん多い本)\n")
+    print(f"→ {out_dir}")
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/pi05/test_state_source.py b/pi05/test_state_source.py
new file mode 100644
index 0000000..cb6b6ae
--- /dev/null
+++ b/pi05/test_state_source.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python3
+"""test_state_source.py — 1 コマごとの state の出どころ (state_source. 依頼 196) の確かめ.
+
+  python3 pi05/test_state_source.py -v
+
+前半はファイルを読まない部分だけ. 後半 (TestSameAsBefore) は KIOXIA の runs/pi05_policy を読み,
+直す前のコード (git の HEAD) と今のコードで /tmp に作り, state / actions / t がバイト単位で同じことを見る
+(KIOXIA がなければ飛ばす. データセットにもアームにも触らない).
+"""
+import importlib.util
+import json
+import subprocess
+import sys
+import tempfile
+import unittest
+from pathlib import Path
+from types import SimpleNamespace
+
+import numpy as np
+
+_HERE = Path(__file__).resolve().parent
+sys.path.insert(0, str(_HERE))
+
+import build_correction_episodes as bce  # noqa: E402
+
+
+def samples(still=False):
+    """0〜1 秒は 0.1 秒おき → 1.0〜2.6 秒は抜け (j1 が 6° 動く. still なら動かない) → 2.6〜3.6 秒は 0.1 秒おき."""
+    a = np.round(np.arange(0.0, 1.01, 0.1), 3)
+    b = np.round(np.arange(2.6, 3.61, 0.1), 3)
+    at = np.concatenate([a, b])
+    aq = np.zeros((len(at), 6))
+    if not still:
+        aq[len(a):, 1] = 6.0
+    return at, aq
+
+
+def runs_of_nonzero(src):
+    nz = np.r_[0, (np.asarray(src) != 0).astype(int)]
+    return int((np.diff(nz) == 1).sum())
+
+
+class TestFlags(unittest.TestCase):
+    def test_motion_gap_is_1(self):
+        at, aq = samples()
+        t = np.arange(0.0, 3.6, 0.1)
+        src = bce.gap_fill_flags(t, at, aq)
+        self.assertEqual(src.dtype, np.int8)
+        inside = (t > 1.0) & (t < 2.6)
+        self.assertTrue(np.all(src[inside] == bce.SRC_FILLED_MOVE))
+        self.assertTrue(np.all(src[~inside] == bce.SRC_MEASURED))
+
+    def test_still_gap_is_2(self):
+        at, aq = samples(still=True)
+        t = np.arange(0.0, 3.6, 0.1)
+        src = bce.gap_fill_flags(t, at, aq)
+        self.assertEqual(set(np.unique(src)), {bce.SRC_MEASURED, bce.SRC_FILLED_STILL})
+
+    def test_flags_mark_exactly_what_speed20_changes(self):
+        """speed20 が線形補間から変えたコマは, すべて印が 0 でないコマ."""
+        at, aq = samples()
+        t = np.arange(0.0, 3.6, 0.1)
+        q_lin, _ = bce.fill_motion_gaps(t, at, aq, mode="linear")
+        q_sp, _ = bce.fill_motion_gaps(t, at, aq, mode="speed20")
+        src = bce.gap_fill_flags(t, at, aq)
+        changed = np.any(np.abs(q_lin - q_sp) > 1e-9, axis=1)
+        self.assertTrue(changed.any())
+        self.assertTrue(np.all(src[changed] != bce.SRC_MEASURED))
+
+    def test_no_gap_no_flag(self):
+        at = np.round(np.arange(0.0, 3.01, 0.1), 3)
+        aq = np.cumsum(np.ones((len(at), 6)), axis=0)
+        self.assertEqual(int(bce.gap_fill_flags(np.arange(0.0, 3.0, 0.1), at, aq).sum()), 0)
+
+    def test_compat_ignores_state_source(self):
+        """お手本にない state_source のキーがあっても check_compat はキーの違いとして数えない."""
+        with tempfile.TemporaryDirectory() as d:
+            import cv2
+            for name, extra in (("ours", True), ("ref", False)):
+                ep = Path(d) / name / "e0"
+                (ep / "frames").mkdir(parents=True)
+                cv2.imwrite(str(ep / "frames" / "000000.jpg"), np.zeros((4, 6, 3), np.uint8))
+                kw = {"state_source": np.zeros(1, np.int8)} if extra else {}
+                np.savez_compressed(ep / "episode.npz", t=np.zeros(1), t_orig=np.zeros(1),
+                                    state=np.zeros((1, 7), np.float32), actions=np.zeros((1, 7), np.float32), **kw)
+                (ep / "meta.json").write_text(json.dumps({"fps": 10, "image_size": [6, 4], "state_dim": 7,
+                                                          "state_names": [], "task": "x"}))
+            self.assertEqual(bce.check_compat(Path(d) / "ours", Path(d) / "ref"), [])
+
+
+def _old_module():
+    """直す前の build_correction_episodes.py (git の HEAD) を別の名前で読み込む."""
+    src = subprocess.run(["git", "show", "HEAD:pi05/build_correction_episodes.py"], cwd=_HERE,
+                         capture_output=True, text=True, check=True).stdout
+    tmp = Path(tempfile.mkdtemp()) / "bce_old.py"
+    tmp.write_text(src)
+    spec = importlib.util.spec_from_file_location("bce_old", tmp)
+    mod = importlib.util.module_from_spec(spec)
+    spec.loader.exec_module(mod)
+    return mod
+
+
+# 補正の多い本・巻き戻しのある本など. 依頼 196 の時点で KIOXIA にあるもの
+SAMPLE_RUNS = ("pi05_20261031_175527", "pi05_20261031_180435")
+
+
+@unittest.skipUnless(Path("/Volumes/KIOXIA").is_mount() and bce.RUNS_ROOT.is_dir(), "KIOXIA がない")
+class TestSameAsBefore(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.old = _old_module()
+
+    def _build(self, mod, run, d, gap_fill, trim_hold):
+        args = SimpleNamespace(gap_fill=gap_fill, trim_hold=trim_hold, no_trim_mid_idle=False,
+                               max_protrude_px=None, force=True)
+        out = Path(d) / mod.__name__ / f"{gap_fill}_{trim_hold}" / run
+        res = mod.build_one(bce.RUNS_ROOT / run, out, args)
+        self.assertTrue(res.get("used"), res)
+        z = np.load(out / "episode.npz")
+        return {k: z[k] for k in z.files}, json.loads((out / "meta.json").read_text())
+
+    def test_bytes_and_counts(self):
+        with tempfile.TemporaryDirectory() as d:
+            for run in SAMPLE_RUNS:
+                if not (bce.RUNS_ROOT / run).is_dir():
+                    self.skipTest(f"{run} がない")
+                for gap_fill, trim_hold in (("linear", False), ("speed20", False), ("speed20", True)):
+                    with self.subTest(run=run, gap_fill=gap_fill, trim_hold=trim_hold):
+                        a, _ = self._build(self.old, run, d, gap_fill, trim_hold)
+                        b, meta = self._build(bce, run, d, gap_fill, trim_hold)
+                        self.assertNotIn("state_source", a)
+                        for k in ("t", "t_orig", "state", "actions"):
+                            self.assertEqual(a[k].dtype, b[k].dtype, k)
+                            self.assertEqual(a[k].tobytes(), b[k].tobytes(), k)
+                        src = b["state_source"]
+                        self.assertEqual(src.dtype, np.int8)
+                        self.assertEqual(len(src), len(b["state"]))
+                        self.assertTrue(set(np.unique(src)) <= set(bce.STATE_SOURCE_CODES))
+                        gf = meta["gap_fill"]
+                        filled = int((src != 0).sum())
+                        self.assertEqual(meta["filled_steps"], filled)
+                        self.assertEqual(meta["filled_motion_steps"], int((src == 1).sum()))
+                        self.assertAlmostEqual(meta["filled_ratio"], filled / len(src), places=4)
+                        # 印のつながりの数は抜けの数を超えない (1 つの抜けが印を 2 つに分けることはない)
+                        self.assertLessEqual(runs_of_nonzero(src), gf["gaps"])
+                        self.assertLessEqual(runs_of_nonzero(src == 1), gf["motion_gaps"])
+                        if gf["gaps"] == 0:
+                            self.assertEqual(filled, 0)
+
+
+if __name__ == "__main__":
+    unittest.main()
```


学習に使ったデータセットの数字を読むときに、気をつけることが1つあります。`deep_even10_v1` の 43.6% は、50本のうち補正のお手本6本だけの割合です。残りの44本は手で教えたお手本で、こちらには印がありません。手教示の分は、次の依頼197 で別に測りました。

- ねらい：お手本の中の補った値を、1コマずつ数えられるようにする
- 変わったこと：`episode.npz` に `state_source`（0＝実測・1＝動いた間を埋めた値・2＝動かなかった間を埋めた値）、`meta.json` に埋めたコマの数と割合を足した。`state`・`actions`・`t` はバイト単位で同じ
- 見込める効果：次にお手本を作るとき、補った値の割合でお手本を選んだり、学習で重みを変えたりできる（まだやっていない）

### 依頼196 の測った結果（`diag/fill_flags_20261114/`）

#### summary.csv


```csv
dataset,corr_episodes,counted,not_counted,steps,filled_steps,filled_motion_steps,filled_ratio,max_episode,max_episode_ratio
mecharm_redblock_box_teach_v1_trim2_corr_v5,11,11,0,1584,655,624,0.4135,pi05_20261031_175527,0.7627
mecharm_redblock_box_deep_even10_v1,6,6,0,884,385,366,0.4355,pi05_20261031_175527,0.7627
mecharm_redblock_box_teach_v1_trim2_corr_v5_deep,7,7,0,1029,478,455,0.4645,pi05_20261031_175527,0.7627
mecharm_redblock_box_corr_v1,5,5,0,1469,1365,1354,0.9292,pi05_20261031_175527,0.9575
mecharm_redblock_box_corr_v2,5,5,0,1159,922,900,0.7955,pi05_20261031_175527,0.8385
mecharm_redblock_box_corr_v3,5,5,0,726,514,497,0.708,pi05_20261031_175527,0.7627
mecharm_redblock_box_corr_v4,8,8,0,1090,754,729,0.6917,pi05_20261031_175527,0.7627
mecharm_redblock_box_corr_v4b,7,7,0,893,629,607,0.7044,pi05_20261031_175527,0.7627
mecharm_redblock_box_corr_v5,11,11,0,1584,655,624,0.4135,pi05_20261031_175527,0.7627
mecharm_redblock_box_teach_v1_trim2_corr_v1,5,5,0,1469,1365,1354,0.9292,pi05_20261031_175527,0.9575
mecharm_redblock_box_teach_v1_trim2_corr_v2,5,5,0,1159,922,900,0.7955,pi05_20261031_175527,0.8385
mecharm_redblock_box_teach_v1_trim2_corr_v3,5,5,0,726,514,497,0.708,pi05_20261031_175527,0.7627
mecharm_redblock_box_teach_v1_trim2_corr_v4,8,8,0,1090,754,729,0.6917,pi05_20261031_175527,0.7627
mecharm_redblock_box_teach_v1_trim2_corr_v4b,7,7,0,893,629,607,0.7044,pi05_20261031_175527,0.7627
```

#### episodes.csv

```csv
dataset,episode,run_stem,gap_fill,trim_hold,steps,filled_steps,filled_motion_steps,filled_ratio,gaps,motion_gaps,status
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261031_181946,pi05_20261031_181946,speed20,True,126,95,93,0.754,56,50,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261101_190347,pi05_20261101_190347,speed20,True,115,76,74,0.6609,51,46,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261101_190854,pi05_20261101_190854,speed20,True,145,93,89,0.6414,62,56,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261101_192101,pi05_20261101_192101,speed20,True,104,71,69,0.6827,46,40,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261106_183926,pi05_20261106_183926,speed20,True,188,5,2,0.0266,6,1,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261106_184452,pi05_20261106_184452,speed20,True,190,4,3,0.0211,7,3,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261106_184650,pi05_20261106_184650,speed20,True,178,10,8,0.0562,8,3,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5,pi05_20261106_184906,pi05_20261106_184906,speed20,True,135,7,4,0.0519,6,2,ok
mecharm_redblock_box_deep_even10_v1,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_deep_even10_v1,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_deep_even10_v1,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_deep_even10_v1,pi05_20261101_190347,pi05_20261101_190347,speed20,True,115,76,74,0.6609,51,46,ok
mecharm_redblock_box_deep_even10_v1,pi05_20261106_183926,pi05_20261106_183926,speed20,True,188,5,2,0.0266,6,1,ok
mecharm_redblock_box_deep_even10_v1,pi05_20261106_184650,pi05_20261106_184650,speed20,True,178,10,8,0.0562,8,3,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5_deep,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5_deep,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5_deep,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5_deep,pi05_20261101_190347,pi05_20261101_190347,speed20,True,115,76,74,0.6609,51,46,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5_deep,pi05_20261101_190854,pi05_20261101_190854,speed20,True,145,93,89,0.6414,62,56,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5_deep,pi05_20261106_183926,pi05_20261106_183926,speed20,True,188,5,2,0.0266,6,1,ok
mecharm_redblock_box_teach_v1_trim2_corr_v5_deep,pi05_20261106_184650,pi05_20261106_184650,speed20,True,178,10,8,0.0562,8,3,ok
mecharm_redblock_box_corr_v1,pi05_20261031_175527,pi05_20261031_175527,,False,259,248,244,0.9575,,,ok
mecharm_redblock_box_corr_v1,pi05_20261031_180435,pi05_20261031_180435,,False,323,293,289,0.9071,,,ok
mecharm_redblock_box_corr_v1,pi05_20261031_181946,pi05_20261031_181946,,False,269,255,255,0.948,,,ok
mecharm_redblock_box_corr_v1,pi05_20261031_182545,pi05_20261031_182545,,False,333,298,298,0.8949,,,ok
mecharm_redblock_box_corr_v1,pi05_20261031_184016,pi05_20261031_184016,,False,285,271,268,0.9509,,,ok
mecharm_redblock_box_corr_v2,pi05_20261031_175527,pi05_20261031_175527,speed20,False,192,161,157,0.8385,52,45,ok
mecharm_redblock_box_corr_v2,pi05_20261031_180435,pi05_20261031_180435,speed20,False,247,192,188,0.7773,61,55,ok
mecharm_redblock_box_corr_v2,pi05_20261031_181946,pi05_20261031_181946,speed20,False,210,176,172,0.8381,56,50,ok
mecharm_redblock_box_corr_v2,pi05_20261031_182545,pi05_20261031_182545,speed20,False,301,221,215,0.7342,82,70,ok
mecharm_redblock_box_corr_v2,pi05_20261031_184016,pi05_20261031_184016,speed20,False,209,172,168,0.823,54,48,ok
mecharm_redblock_box_corr_v3,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_corr_v3,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_corr_v3,pi05_20261031_181946,pi05_20261031_181946,speed20,True,126,95,93,0.754,56,50,ok
mecharm_redblock_box_corr_v3,pi05_20261031_182545,pi05_20261031_182545,speed20,True,197,125,122,0.6345,82,70,ok
mecharm_redblock_box_corr_v3,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_corr_v4,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_corr_v4,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_corr_v4,pi05_20261031_181946,pi05_20261031_181946,speed20,True,126,95,93,0.754,56,50,ok
mecharm_redblock_box_corr_v4,pi05_20261031_182545,pi05_20261031_182545,speed20,True,197,125,122,0.6345,82,70,ok
mecharm_redblock_box_corr_v4,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_corr_v4,pi05_20261101_190347,pi05_20261101_190347,speed20,True,115,76,74,0.6609,51,46,ok
mecharm_redblock_box_corr_v4,pi05_20261101_190854,pi05_20261101_190854,speed20,True,145,93,89,0.6414,62,56,ok
mecharm_redblock_box_corr_v4,pi05_20261101_192101,pi05_20261101_192101,speed20,True,104,71,69,0.6827,46,40,ok
mecharm_redblock_box_corr_v4b,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_corr_v4b,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_corr_v4b,pi05_20261031_181946,pi05_20261031_181946,speed20,True,126,95,93,0.754,56,50,ok
mecharm_redblock_box_corr_v4b,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_corr_v4b,pi05_20261101_190347,pi05_20261101_190347,speed20,True,115,76,74,0.6609,51,46,ok
mecharm_redblock_box_corr_v4b,pi05_20261101_190854,pi05_20261101_190854,speed20,True,145,93,89,0.6414,62,56,ok
mecharm_redblock_box_corr_v4b,pi05_20261101_192101,pi05_20261101_192101,speed20,True,104,71,69,0.6827,46,40,ok
mecharm_redblock_box_corr_v5,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_corr_v5,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_corr_v5,pi05_20261031_181946,pi05_20261031_181946,speed20,True,126,95,93,0.754,56,50,ok
mecharm_redblock_box_corr_v5,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_corr_v5,pi05_20261101_190347,pi05_20261101_190347,speed20,True,115,76,74,0.6609,51,46,ok
mecharm_redblock_box_corr_v5,pi05_20261101_190854,pi05_20261101_190854,speed20,True,145,93,89,0.6414,62,56,ok
mecharm_redblock_box_corr_v5,pi05_20261101_192101,pi05_20261101_192101,speed20,True,104,71,69,0.6827,46,40,ok
mecharm_redblock_box_corr_v5,pi05_20261106_183926,pi05_20261106_183926,speed20,True,188,5,2,0.0266,6,1,ok
mecharm_redblock_box_corr_v5,pi05_20261106_184452,pi05_20261106_184452,speed20,True,190,4,3,0.0211,7,3,ok
mecharm_redblock_box_corr_v5,pi05_20261106_184650,pi05_20261106_184650,speed20,True,178,10,8,0.0562,8,3,ok
mecharm_redblock_box_corr_v5,pi05_20261106_184906,pi05_20261106_184906,speed20,True,135,7,4,0.0519,6,2,ok
mecharm_redblock_box_teach_v1_trim2_corr_v1,pi05_20261031_175527,pi05_20261031_175527,,False,259,248,244,0.9575,,,ok
mecharm_redblock_box_teach_v1_trim2_corr_v1,pi05_20261031_180435,pi05_20261031_180435,,False,323,293,289,0.9071,,,ok
mecharm_redblock_box_teach_v1_trim2_corr_v1,pi05_20261031_181946,pi05_20261031_181946,,False,269,255,255,0.948,,,ok
mecharm_redblock_box_teach_v1_trim2_corr_v1,pi05_20261031_182545,pi05_20261031_182545,,False,333,298,298,0.8949,,,ok
mecharm_redblock_box_teach_v1_trim2_corr_v1,pi05_20261031_184016,pi05_20261031_184016,,False,285,271,268,0.9509,,,ok
mecharm_redblock_box_teach_v1_trim2_corr_v2,pi05_20261031_175527,pi05_20261031_175527,speed20,False,192,161,157,0.8385,52,45,ok
mecharm_redblock_box_teach_v1_trim2_corr_v2,pi05_20261031_180435,pi05_20261031_180435,speed20,False,247,192,188,0.7773,61,55,ok
mecharm_redblock_box_teach_v1_trim2_corr_v2,pi05_20261031_181946,pi05_20261031_181946,speed20,False,210,176,172,0.8381,56,50,ok
mecharm_redblock_box_teach_v1_trim2_corr_v2,pi05_20261031_182545,pi05_20261031_182545,speed20,False,301,221,215,0.7342,82,70,ok
mecharm_redblock_box_teach_v1_trim2_corr_v2,pi05_20261031_184016,pi05_20261031_184016,speed20,False,209,172,168,0.823,54,48,ok
mecharm_redblock_box_teach_v1_trim2_corr_v3,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_teach_v1_trim2_corr_v3,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_teach_v1_trim2_corr_v3,pi05_20261031_181946,pi05_20261031_181946,speed20,True,126,95,93,0.754,56,50,ok
mecharm_redblock_box_teach_v1_trim2_corr_v3,pi05_20261031_182545,pi05_20261031_182545,speed20,True,197,125,122,0.6345,82,70,ok
mecharm_redblock_box_teach_v1_trim2_corr_v3,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4,pi05_20261031_181946,pi05_20261031_181946,speed20,True,126,95,93,0.754,56,50,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4,pi05_20261031_182545,pi05_20261031_182545,speed20,True,197,125,122,0.6345,82,70,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4,pi05_20261101_190347,pi05_20261101_190347,speed20,True,115,76,74,0.6609,51,46,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4,pi05_20261101_190854,pi05_20261101_190854,speed20,True,145,93,89,0.6414,62,56,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4,pi05_20261101_192101,pi05_20261101_192101,speed20,True,104,71,69,0.6827,46,40,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4b,pi05_20261031_175527,pi05_20261031_175527,speed20,True,118,90,86,0.7627,52,45,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4b,pi05_20261031_180435,pi05_20261031_180435,speed20,True,152,105,101,0.6908,61,55,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4b,pi05_20261031_181946,pi05_20261031_181946,speed20,True,126,95,93,0.754,56,50,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4b,pi05_20261031_184016,pi05_20261031_184016,speed20,True,133,99,95,0.7444,54,48,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4b,pi05_20261101_190347,pi05_20261101_190347,speed20,True,115,76,74,0.6609,51,46,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4b,pi05_20261101_190854,pi05_20261101_190854,speed20,True,145,93,89,0.6414,62,56,ok
mecharm_redblock_box_teach_v1_trim2_corr_v4b,pi05_20261101_192101,pi05_20261101_192101,speed20,True,104,71,69,0.6827,46,40,ok
```


#### README.md

```markdown
# fill_flags_20261114 (依頼 196)

既存の補正データセットで, 実測角の抜けを埋めたコマ (state_source が 1 または 2) の数と割合。
`python3 pi05/diag_fill_flags.py` で作った。データセットは読むだけ。作り直しは /tmp。

- state_source: 0 = 実測角 / 1 = 動いた抜けを埋めた値 / 2 = 動かなかった抜けを埋めた値
- filled_ratio = (1 と 2 のコマ) / 全コマ。filled_motion_steps は 1 のコマの数
- status が ok でない本 (作り直した state / actions / t がデータセットと一致しない・作り直せない) は数えない
- episodes.csv: 本ごと / summary.csv: データセットごと (max_episode = 割合がいちばん多い本)
```


#### teach_scripted.txt

```text
依頼 196 の 4: 手教示・scripted の「埋めた値」(コードの確かめと, 元の記録の実測角の間の数え. 直していない)

コード: pi05/build_demo_episodes.py の build_one は q = np.interp(t, at, aq) で, 実測角の間がどれだけ長くても
前後をまっすぐ結ぶ (= build_correction_episodes の --gap-fill linear と同じ埋め方). 抜けの判定も印もない.

元の記録 (runs/run_pick_place/{run}/recording/states.csv) の実測角の間 (秒):
  teach_v1_trim2          19 本 中央値 0.324 / 90% 0.32〜1.05 / 99% 6.04  1 秒を超える間が時間の 62%
  teach_pos1to4_deep_v1   31 本 中央値 0.324 / 90% 1.06 / 99% 6.04        1 秒を超える間が時間の 62%
  scripted_v1             20 本 中央値 0.322 / 90% 3.46 / 99% 32.9 (最大 212 秒)  1 秒を超える間が時間の 93%
ふだんの間が約 0.32 秒なので, 補正と同じ 0.25 秒の決まりで数えると 10Hz のコマのほぼ全部 (98.8〜99.4%) が「抜け」になる.
(どちらも詰める前の 10Hz の時間軸で数えた)
```


#### codex_review.txt

```text
Reading additional input from stdin...
OpenAI Codex v0.163.0
--------
workdir: /Users/shimazueiichi/r2r2r-scripts
model: gpt-6.1-sol
provider: openai
approval: never
sandbox: read-only
reasoning effort: none
reasoning summaries: none
session id: 01a1da87-96a1-7d20-8a44-a8e6fabb2f24
--------
user
依頼196のレビューをお願いします。pi05/build_correction_episodes.py に 1 コマごとの state の出どころ state_source (int8: 0 実測 / 1 動いた抜けを埋めた値 / 2 動かなかった抜けを埋めた値) を足しました。差分は /tmp/req196.diff。新しいファイル pi05/test_state_source.py と pi05/diag_fill_flags.py も見てください。条件: state/actions/t の値は 1 つも変えないこと、既存データセットは書き換えないこと、印は fill_motion_gaps が埋めたコマと一致すること。正しさの不具合を P1/P2/P3 で日本語で短く挙げてください。
codex
差分と追加ファイルを確認し、既存の補間処理と照合して、値の不変性と印の一致をレビューします。
exec
/bin/zsh -lc 'cat /tmp/req196.diff' in /Users/shimazueiichi/r2r2r-scripts
 succeeded in 0ms:
diff --git a/pi05/build_correction_episodes.py b/pi05/build_correction_episodes.py
index e5bce79..ae813b3 100644
--- a/pi05/build_correction_episodes.py
+++ b/pi05/build_correction_episodes.py
@@ -16,6 +16,7 @@
   - 使うのは 結果が「成功」(y) の run だけ
   - 時間軸は 10Hz. state は実測角の線形補間 + グリッパーは指令の時刻で 0/1 (build_demo_episodes と同じ)
     実測角の抜け (送信中) は --gap-fill で埋める (linear = corr_v1 / speed20 = corr_v2. 依頼 46)
+    埋めたコマには episode.npz の state_source で印を残す (0 実測 / 1 動いた抜け / 2 動かなかった抜け. 依頼 196)
   - 学習に使うのは状態が model / correct のステップだけ. rewind / home / wait (確認の入力待ち.
     人がブロックを置き直すと手が写る) / regrip (補正の R で開いてから閉じ終わるまで. 2026-10-30 依頼 35)
     のステップと,
@@ -176,6 +177,26 @@ def fill_motion_gaps(t, at, aq, mode="speed20", gap_sec=GAP_SEC, speed=SPEED20_D
     return q, gaps
 
 
+# ---- 1 コマごとの state の出どころ (state_source. int8. 2026-11-14 依頼 196) ----
+# 関節 6 列が実測角か, fill_motion_gaps が抜けを埋めた値かの印. 爪の列は指令なのでどれでも同じ
+SRC_MEASURED = 0     # 実測角 (0.25 秒以内の前後の実測角の線形補間. ふだんは 0.1 秒おき)
+SRC_FILLED_MOVE = 1  # 動いた抜け (前後の実測角の差 > GAP_MOVE_MIN_DEG) の中を埋めた値
+SRC_FILLED_STILL = 2  # 動かなかった抜け (差 <= GAP_MOVE_MIN_DEG. 爪の送信など) の中を埋めた値
+STATE_SOURCE_CODES = {SRC_MEASURED: "measured", SRC_FILLED_MOVE: "filled_motion_gap",
+                      SRC_FILLED_STILL: "filled_still_gap"}
+
+
+def gap_fill_flags(t, at, aq, gap_sec=GAP_SEC, min_move=GAP_MOVE_MIN_DEG):
+    """時刻 t のコマごとの state_source (int8). fill_motion_gaps と同じ「抜け」(実測角の間が gap_sec より長い
+    [ta, tb]) の中 (ta < t < tb) が埋めた値. 埋め方 (linear / speed20) によらず同じ印になる."""
+    src = np.zeros(len(t), dtype=np.int8)
+    for i in np.flatnonzero(np.diff(at) > gap_sec):
+        ta, tb = at[i], at[i + 1]
+        moved = float(np.max(np.abs(aq[i + 1] - aq[i]))) > min_move
+        src[(t > ta) & (t < tb)] = SRC_FILLED_MOVE if moved else SRC_FILLED_STILL
+    return src
+
+
 def logged_sends(log):
     """log.jsonl から, 送った目標とそのときの時刻の手がかりを集める.
 
@@ -443,9 +464,12 @@ def build_one(run_dir, out_dir, args):
         return {"run": stem, "used": False,
                 "reason": f"フレーム抽出不足 written={written} steps={len(tt)} (mp4 と frame_log の不一致)"}
 
+    state_source = gap_fill_flags(t, at, aq)[sel["idx"]]
     np.savez_compressed(out_dir / "episode.npz",
                         t=(np.arange(len(tt)) / FPS).astype(np.float64),
-                        t_orig=tt - tt[0], state=sel["state"], actions=sel["actions"])
+                        t_orig=tt - tt[0], state=sel["state"], actions=sel["actions"],
+                        state_source=state_source)
+    filled = int((state_source != SRC_MEASURED).sum())
     c = sel["counts"]
     meta = {
         "run_stem": stem, "task": bde.TASK, "fps": FPS, "steps": int(len(tt)),
@@ -475,6 +499,11 @@ def build_one(run_dir, out_dir, args):
         "gap_fill": {"mode": gap_fill, "gap_sec": GAP_SEC,
                      "speed_deg_per_sec": SPEED20_DEG_PER_SEC if gap_fill == "speed20" else None,
                      "gaps": len(gaps), **gap_match},
+        # 依頼 196: episode.npz の state_source (コマごとの印) の数
+        "filled_steps": filled,
+        "filled_motion_steps": int((state_source == SRC_FILLED_MOVE).sum()),
+        "filled_ratio": round(filled / len(tt), 4),
+        "state_source_codes": {str(k): v for k, v in STATE_SOURCE_CODES.items()},
         "max_step_deg": [round(float(v), 2) for v in
                          (np.abs(np.diff(sel["state"][:, :6], axis=0)).max(axis=0) if len(sel["state"]) > 1
                           else np.zeros(6))],
@@ -506,7 +535,8 @@ def check_compat(ours, ref):
     for ep in a:
         m = json.loads((ep / "meta.json").read_text())
         z = np.load(ep / "episode.npz")
-        if sorted(z.files) != sorted(rz.files):
+        # 依頼 196: state_source (コマごとの印) はお手本にないキー. 読む側は state / actions しか使わないので比べない
+        if sorted(set(z.files) - {"state_source"}) != sorted(set(rz.files) - {"state_source"}):
             probs.append(f"{ep.name}: npz のキー {sorted(z.files)} != お手本 {sorted(rz.files)}")
         for k in ("state", "actions"):
             if z[k].dtype != rz[k].dtype or z[k].shape[1:] != rz[k].shape[1:]:
@@ -554,6 +584,11 @@ def write_readme(ds, results, args):
         + ("前後の実測角をまっすぐ結ぶ (linear)" if args.gap_fill == "linear" else
            f"抜けの頭から速度 20 の速さ ({SPEED20_DEG_PER_SEC:.0f}°/秒. いちばん大きく動く関節) で前後の実測角を結ぶ"
            "直線を進み, 着いたら止まる (speed20)"),
+        "- 1 コマごとの state の出どころを episode.npz の `state_source` (int8. state と同じ長さ) に残す: "
+        "0 = 実測角 (0.25 秒以内の前後の実測角の線形補間) / 1 = 動いた抜け (前後の実測角の差が "
+        f"{GAP_MOVE_MIN_DEG}° を超える) の中を上の埋め方で埋めた値 / 2 = 動かなかった抜け (爪の送信など) の中を埋めた値。"
+        "印は関節 6 列のもの (爪の列はいつも指令)。actions の関節は次のコマの state なので, その出どころは次のコマの印。"
+        "meta.json の filled_steps (1 と 2 のコマの数) / filled_motion_steps (1 の数) / filled_ratio (全コマに対する 1 と 2 の割合)",
         "- 戻りきれなかった巻き戻しがある run は使わない (前後の姿勢が続かない)",
     ]
     if getattr(args, "max_protrude_px", None) is not None:

exec
/bin/zsh -lc 'cat pi05/test_state_source.py pi05/diag_fill_flags.py' in /Users/shimazueiichi/r2r2r-scripts
 succeeded in 0ms:
#!/usr/bin/env python3
"""test_state_source.py — 1 コマごとの state の出どころ (state_source. 依頼 196) の確かめ.

  python3 pi05/test_state_source.py -v

前半はファイルを読まない部分だけ. 後半 (TestSameAsBefore) は KIOXIA の runs/pi05_policy を読み,
直す前のコード (git の HEAD) と今のコードで /tmp に作り, state / actions / t がバイト単位で同じことを見る
(KIOXIA がなければ飛ばす. データセットにもアームにも触らない).
"""
import importlib.util
import json
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
from types import SimpleNamespace

import numpy as np

_HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(_HERE))

import build_correction_episodes as bce  # noqa: E402


def samples(still=False):
    """0〜1 秒は 0.1 秒おき → 1.0〜2.6 秒は抜け (j1 が 6° 動く. still なら動かない) → 2.6〜3.6 秒は 0.1 秒おき."""
    a = np.round(np.arange(0.0, 1.01, 0.1), 3)
    b = np.round(np.arange(2.6, 3.61, 0.1), 3)
    at = np.concatenate([a, b])
    aq = np.zeros((len(at), 6))
    if not still:
        aq[len(a):, 1] = 6.0
    return at, aq


def runs_of_nonzero(src):
    nz = np.r_[0, (np.asarray(src) != 0).astype(int)]
    return int((np.diff(nz) == 1).sum())


class TestFlags(unittest.TestCase):
    def test_motion_gap_is_1(self):
        at, aq = samples()
        t = np.arange(0.0, 3.6, 0.1)
        src = bce.gap_fill_flags(t, at, aq)
        self.assertEqual(src.dtype, np.int8)
        inside = (t > 1.0) & (t < 2.6)
        self.assertTrue(np.all(src[inside] == bce.SRC_FILLED_MOVE))
        self.assertTrue(np.all(src[~inside] == bce.SRC_MEASURED))

    def test_still_gap_is_2(self):
        at, aq = samples(still=True)
        t = np.arange(0.0, 3.6, 0.1)
        src = bce.gap_fill_flags(t, at, aq)
        self.assertEqual(set(np.unique(src)), {bce.SRC_MEASURED, bce.SRC_FILLED_STILL})

    def test_flags_mark_exactly_what_speed20_changes(self):
        """speed20 が線形補間から変えたコマは, すべて印が 0 でないコマ."""
        at, aq = samples()
        t = np.arange(0.0, 3.6, 0.1)
        q_lin, _ = bce.fill_motion_gaps(t, at, aq, mode="linear")
        q_sp, _ = bce.fill_motion_gaps(t, at, aq, mode="speed20")
        src = bce.gap_fill_flags(t, at, aq)
        changed = np.any(np.abs(q_lin - q_sp) > 1e-9, axis=1)
        self.assertTrue(changed.any())
        self.assertTrue(np.all(src[changed] != bce.SRC_MEASURED))

    def test_no_gap_no_flag(self):
        at = np.round(np.arange(0.0, 3.01, 0.1), 3)
        aq = np.cumsum(np.ones((len(at), 6)), axis=0)
        self.assertEqual(int(bce.gap_fill_flags(np.arange(0.0, 3.0, 0.1), at, aq).sum()), 0)

    def test_compat_ignores_state_source(self):
        """お手本にない state_source のキーがあっても check_compat はキーの違いとして数えない."""
        with tempfile.TemporaryDirectory() as d:
            import cv2
            for name, extra in (("ours", True), ("ref", False)):
                ep = Path(d) / name / "e0"
                (ep / "frames").mkdir(parents=True)
                cv2.imwrite(str(ep / "frames" / "000000.jpg"), np.zeros((4, 6, 3), np.uint8))
                kw = {"state_source": np.zeros(1, np.int8)} if extra else {}
                np.savez_compressed(ep / "episode.npz", t=np.zeros(1), t_orig=np.zeros(1),
                                    state=np.zeros((1, 7), np.float32), actions=np.zeros((1, 7), np.float32), **kw)
                (ep / "meta.json").write_text(json.dumps({"fps": 10, "image_size": [6, 4], "state_dim": 7,
                                                          "state_names": [], "task": "x"}))
            self.assertEqual(bce.check_compat(Path(d) / "ours", Path(d) / "ref"), [])


def _old_module():
    """直す前の build_correction_episodes.py (git の HEAD) を別の名前で読み込む."""
    src = subprocess.run(["git", "show", "HEAD:pi05/build_correction_episodes.py"], cwd=_HERE,
                         capture_output=True, text=True, check=True).stdout
    tmp = Path(tempfile.mkdtemp()) / "bce_old.py"
    tmp.write_text(src)
    spec = importlib.util.spec_from_file_location("bce_old", tmp)
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod


# 補正の多い本・巻き戻しのある本など. 依頼 196 の時点で KIOXIA にあるもの
SAMPLE_RUNS = ("pi05_20261031_175527", "pi05_20261031_180435")


@unittest.skipUnless(Path("/Volumes/KIOXIA").is_mount() and bce.RUNS_ROOT.is_dir(), "KIOXIA がない")
class TestSameAsBefore(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.old = _old_module()

    def _build(self, mod, run, d, gap_fill, trim_hold):
        args = SimpleNamespace(gap_fill=gap_fill, trim_hold=trim_hold, no_trim_mid_idle=False,
                               max_protrude_px=None, force=True)
        out = Path(d) / mod.__name__ / f"{gap_fill}_{trim_hold}" / run
        res = mod.build_one(bce.RUNS_ROOT / run, out, args)
        self.assertTrue(res.get("used"), res)
        z = np.load(out / "episode.npz")
        return {k: z[k] for k in z.files}, json.loads((out / "meta.json").read_text())

    def test_bytes_and_counts(self):
        with tempfile.TemporaryDirectory() as d:
            for run in SAMPLE_RUNS:
                if not (bce.RUNS_ROOT / run).is_dir():
                    self.skipTest(f"{run} がない")
                for gap_fill, trim_hold in (("linear", False), ("speed20", False), ("speed20", True)):
                    with self.subTest(run=run, gap_fill=gap_fill, trim_hold=trim_hold):
                        a, _ = self._build(self.old, run, d, gap_fill, trim_hold)
                        b, meta = self._build(bce, run, d, gap_fill, trim_hold)
                        self.assertNotIn("state_source", a)
                        for k in ("t", "t_orig", "state", "actions"):
                            self.assertEqual(a[k].dtype, b[k].dtype, k)
                            self.assertEqual(a[k].tobytes(), b[k].tobytes(), k)
                        src = b["state_source"]
                        self.assertEqual(src.dtype, np.int8)
                        self.assertEqual(len(src), len(b["state"]))
                        self.assertTrue(set(np.unique(src)) <= set(bce.STATE_SOURCE_CODES))
                        gf = meta["gap_fill"]
                        filled = int((src != 0).sum())
                        self.assertEqual(meta["filled_steps"], filled)
                        self.assertEqual(meta["filled_motion_steps"], int((src == 1).sum()))
                        self.assertAlmostEqual(meta["filled_ratio"], filled / len(src), places=4)
                        # 印のつながりの数は抜けの数を超えない (1 つの抜けが印を 2 つに分けることはない)
                        self.assertLessEqual(runs_of_nonzero(src), gf["gaps"])
                        self.assertLessEqual(runs_of_nonzero(src == 1), gf["motion_gaps"])
                        if gf["gaps"] == 0:
                            self.assertEqual(filled, 0)


if __name__ == "__main__":
    unittest.main()
#!/usr/bin/env python3
"""diag_fill_flags.py — 既存の補正データセットで, 実測角の抜けを埋めたコマの割合を測る (2026-11-14 依頼 196).

datasets/ の名前に corr / deep_even10 が入るデータセットの, 補正エピソード (meta.json の source が pi05_policy)
ごとに, 元の runs/pi05_policy/{run_stem}/ から build_correction_episodes.build_one を meta.json と同じ条件
(gap_fill の mode・trim_mid_idle・trim_hold) で /tmp に作り直し, state_source (コマごとの印) を数える.
作り直した state / actions / t がデータセットの episode.npz と一致しない本は数えない (理由を CSV に残す).

データセット・元の記録は読むだけ (書かない). 書くのは /tmp と diag/fill_flags_20261114/ だけ.

  python3 pi05/diag_fill_flags.py
"""
import argparse
import csv
import json
import sys
from pathlib import Path
from types import SimpleNamespace

import numpy as np

_HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(_HERE))

import build_correction_episodes as bce  # noqa: E402
import build_demo_episodes as bde  # noqa: E402

OUT_NAME = "fill_flags_20261114"
TMP_ROOT = Path("/tmp") / OUT_NAME
# 学習に使ったことがあるデータセットを先に並べる (依頼 196)
TRAINED_FIRST = ("mecharm_redblock_box_teach_v1_trim2_corr_v5", "mecharm_redblock_box_deep_even10_v1",
                 "mecharm_redblock_box_teach_v1_trim2_corr_v5_deep")


def target_datasets(ds_root):
    names = sorted(p.name for p in ds_root.iterdir()
                   if p.is_dir() and not p.name.startswith(".") and ("corr" in p.name or "deep_even10" in p.name))
    return sorted(names, key=lambda n: (n not in TRAINED_FIRST, TRAINED_FIRST.index(n) if n in TRAINED_FIRST else 0, n))


def rebuild(run_stem, meta, cache):
    """meta.json と同じ条件で /tmp に作り直す. 戻り値: (npz の中身 dict / None, 理由)."""
    gf = meta.get("gap_fill") or {}
    key = (run_stem, gf.get("mode"), bool(meta.get("trim_mid_idle")), meta.get("trim_hold") is not None)
    if key in cache:
        return cache[key]
    out = TMP_ROOT / "rebuild" / "_".join(str(k) for k in key) / run_stem
    args = SimpleNamespace(gap_fill=gf.get("mode") or "linear", trim_hold=key[3],
                           no_trim_mid_idle=not key[2], max_protrude_px=None, force=True)
    res = bce.build_one(bce.RUNS_ROOT / run_stem, out, args)
    if not res.get("used"):
        cache[key] = (None, f"作り直せない: {res.get('reason')}")
    else:
        z = np.load(out / "episode.npz")
        cache[key] = ({k: z[k] for k in z.files}, "ok")
    return cache[key]


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--dataset", action="append", help="このデータセットだけ (複数可)")
    args = ap.parse_args()
    bde.ensure_ssd()
    ds_root = bde.DATA_ROOT / "datasets"
    out_dir = bde.DATA_ROOT / "diag" / OUT_NAME
    if out_dir.exists():
        sys.exit(f"[ABORT] 出力先がもうある: {out_dir}")
    names = args.dataset or target_datasets(ds_root)
    rows, cache = [], {}
    for name in names:
        for mp in sorted((ds_root / name / "raw_episodes").glob("[!.]*/meta.json")):
            meta = json.loads(mp.read_text())
            if not str(meta.get("source", "")).startswith("pi05_policy"):
                continue
            ep = mp.parent
            stem = meta.get("run_stem", ep.name)
            z = np.load(ep / "episode.npz")
            row = {"dataset": name, "episode": ep.name, "run_stem": stem,
                   "gap_fill": (meta.get("gap_fill") or {}).get("mode"),
                   "trim_hold": meta.get("trim_hold") is not None, "steps": len(z["state"]),
                   "filled_steps": "", "filled_motion_steps": "", "filled_ratio": "",
                   "gaps": (meta.get("gap_fill") or {}).get("gaps"),
                   "motion_gaps": (meta.get("gap_fill") or {}).get("motion_gaps"), "status": ""}
            new, why = rebuild(stem, meta, cache)
            if new is None:
                row["status"] = why
            elif not all(k in new and new[k].shape == z[k].shape and new[k].tobytes() == z[k].tobytes()
                         for k in ("state", "actions", "t")):
                row["status"] = "state が一致しない (数えない)"
            else:
                src = new["state_source"]
                n_f = int((src != bce.SRC_MEASURED).sum())
                row.update(filled_steps=n_f, filled_motion_steps=int((src == bce.SRC_FILLED_MOVE).sum()),
                           filled_ratio=round(n_f / len(src), 4), status="ok")
            rows.append(row)
            print(f"{name}  {ep.name}  {row['status']}  {row['filled_steps']}/{row['steps']}")

    out_dir.mkdir(parents=True)
    with (out_dir / "episodes.csv").open("w", newline="") as f:
        w = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
        w.writeheader(); w.writerows(rows)
    summ = []
    for name in names:
        rs = [r for r in rows if r["dataset"] == name]
        ok = [r for r in rs if r["status"] == "ok"]
        steps = sum(r["steps"] for r in ok); filled = sum(r["filled_steps"] for r in ok)
        top = max(ok, key=lambda r: r["filled_ratio"]) if ok else None
        summ.append({"dataset": name, "corr_episodes": len(rs), "counted": len(ok),
                     "not_counted": len(rs) - len(ok), "steps": steps, "filled_steps": filled,
                     "filled_motion_steps": sum(r["filled_motion_steps"] for r in ok),
                     "filled_ratio": round(filled / steps, 4) if steps else "",
                     "max_episode": top["episode"] if top else "",
                     "max_episode_ratio": top["filled_ratio"] if top else ""})
    with (out_dir / "summary.csv").open("w", newline="") as f:
        w = csv.DictWriter(f, fieldnames=list(summ[0].keys()))
        w.writeheader(); w.writerows(summ)
    (out_dir / "README.md").write_text(
        "# fill_flags_20261114 (依頼 196)\n\n"
        "既存の補正データセットで, 実測角の抜けを埋めたコマ (state_source が 1 または 2) の数と割合。\n"
        "`python3 pi05/diag_fill_flags.py` で作った。データセットは読むだけ。作り直しは /tmp。\n\n"
        "- state_source: 0 = 実測角 / 1 = 動いた抜けを埋めた値 / 2 = 動かなかった抜けを埋めた値\n"
        "- filled_ratio = (1 と 2 のコマ) / 全コマ。filled_motion_steps は 1 のコマの数\n"
        "- status が ok でない本 (作り直した state / actions / t がデータセットと一致しない・作り直せない) は数えない\n"
        "- episodes.csv: 本ごと / summary.csv: データセットごと (max_episode = 割合がいちばん多い本)\n")
    print(f"→ {out_dir}")
    return 0


if __name__ == "__main__":
    sys.exit(main())

exec
/bin/zsh -lc "sed -n '65,180p' pi05/build_correction_episodes.py; sed -n '310,470p' pi05/build_correction_episodes.py; rg -n 'trim_mid_idle|trim_hold|sel\\[|idx|out_dir|force' pi05/build_correction_episodes.py" in /Users/shimazueiichi/r2r2r-scripts
 succeeded in 0ms:
# 角度を読み直す間 (約 1.6 秒. 動いている間は読めずにやり直す) 返ってこないので, その間は実測角が残らない.
# 腕はこの抜けの頭で動き出し, 抜けの終わりの実測角 (着いた姿勢) で止まっている.
#   linear  : 抜けの前後の実測角をまっすぐ結ぶ (corr_v1. 1.6 秒かけてゆっくり動いたことになる)
#   speed20 : 抜けの頭から, 速度 20 の速さで前後の実測角を結ぶ直線 (関節空間. 全関節が同時に着く) を進み,
#             着いたら抜けの終わりまで止まる. 速さは trim2 の元の記録 (run_pick_place 19 本. 速度 20 で
#             0.32 秒おきに動いている間も読めていた) の, 動いている途中の先頭の関節の速さ 128 区間の中央値 29.8°/秒
GAP_FILL_MODES = ("linear", "speed20")
GAP_SEC = 0.25                  # 実測角の間がこれより長いところを「抜け」とみなす (ふだんは 0.1 秒おき)
SPEED20_DEG_PER_SEC = 30.0      # 速度 20 で動いている間の先頭の関節の速さ (上の 29.8°/秒)
GAP_MOVE_MIN_DEG = 0.5          # 抜けの前後でこれより動いていれば「動いた抜け」として数える
# ---- 着いたあとの止まりの詰め方 (--trim-hold. 2026-10-31 依頼 48. corr_v3) ----
# 推論・補正では 1 回の send_angles ごとに daemon の読み直し (約 1.6 秒) を待つので, 中継点・補正の 1 刻みの
# たびに「動いて止まる」をくり返す. trim2 の決まり (止まりの区間ごとに先頭 2 コマ) では, 区間が 2〜3 コマ
# おきに来るため止まりが約 50% 残る (corr_v2). この止まりは送信の確かめを待つだけで, 動作の意味はない.
#   model の区間       : 残さない (中継点の動きだけをつなぐ)
#   correct の区間     : 先頭 1 コマ (補正のコマを減らしすぎない. 補正は 1 刻みが 1 コマで動き終わる)
#   爪の切り替えの直前・直後の区間 : trim2 と同じ先頭 2 コマ (爪が動き終わるのを待つ意味がある) + gripper_guard
HOLD_KEEP_MODEL = 0
HOLD_KEEP_CORRECT = 1
HOLD_KEEP_GRIP = bde.MID_IDLE_KEEP_STEPS


def _rmtree(path):
    """exFAT では本体を消すと macOS が ._ (AppleDouble) も一緒に消すため, 後から ._ を消そうとして
    FileNotFoundError になる. もう無いものは飛ばして消す."""
    def _skip_missing(func, p, exc):
        exc = exc[1] if isinstance(exc, tuple) else exc   # onerror (3.11 まで) は exc_info
        if not isinstance(exc, FileNotFoundError):
            raise exc
    if sys.version_info >= (3, 12):
        shutil.rmtree(path, onexc=_skip_missing)
    else:
        shutil.rmtree(path, onerror=_skip_missing)


def load_stage_times(path):
    """states.csv の stage 行 (状態の切り替わり) と, 各行の stage 列."""
    ts, modes = [], []
    with path.open(newline="") as f:
        for row in csv.DictReader(f):
            if row.get("event_type") != "stage":
                continue
            try:
                ts.append(float(row["ts"])); modes.append(row.get("stage") or MODE_MODEL)
            except Exception:
                continue
    return np.array(ts), modes


def load_log(path):
    out = []
    if not path.exists():
        return out
    for line in path.read_text().splitlines():
        line = line.strip()
        if line:
            try:
                out.append(json.loads(line))
            except Exception:
                continue
    return out


def idle_keep_mask(state, actions):
    """build_demo_episodes.build_one の「停止区間を詰める」(IDLE_*) と同じ決まり. 戻り値: (keep, 詰めた数)."""
    n = len(state)
    motion = np.max(np.abs(actions - state), axis=1)
    keep = np.ones(n, dtype=bool)
    i, trimmed = 0, 0
    while i < n:
        if motion[i] < bde.IDLE_EPS_DEG:
            j = i
            while j < n and motion[j] < bde.IDLE_EPS_DEG:
                j += 1
            if (j - i) / FPS > bde.IDLE_MAX_SEC:
                cut_from = i + int(bde.IDLE_KEEP_SEC * FPS)
                keep[cut_from:j] = False
                trimmed += j - cut_from
            i = j
        else:
            i += 1
    guard = bde.gripper_guard_mask(state)
    trimmed -= int((~keep & guard).sum())
    keep |= guard
    return keep, trimmed


def fill_motion_gaps(t, at, aq, mode="speed20", gap_sec=GAP_SEC, speed=SPEED20_DEG_PER_SEC):
    """10Hz の時刻 t の関節角を, 実測角 (at, aq) から作る. 実測角があるところは実測角の線形補間.

    実測角の間が gap_sec より長い「抜け」[ta, tb] だけ, mode で埋め方を変える:
      linear  : qa → qb を ta〜tb でまっすぐ結ぶ (np.interp と同じ)
      speed20 : ta から qa → qb の直線を, いちばん大きく動く関節が speed (°/秒) になる速さで進み,
                着いたら tb まで qb で止まる. 着くまでの時間が抜けより長いときは抜けいっぱいを使う (linear と同じ)
    戻り値: (q (len(t), 6), 抜けの一覧 [{ta, tb, move_deg, move_sec}])
    """
    if mode not in GAP_FILL_MODES:
        raise ValueError(f"gap fill mode: {mode}")
    q = np.stack([np.interp(t, at, aq[:, k]) for k in range(6)], axis=1)
    gaps = []
    for i in np.flatnonzero(np.diff(at) > gap_sec):
        ta, tb, qa, qb = at[i], at[i + 1], aq[i], aq[i + 1]
        d = float(np.max(np.abs(qb - qa)))
        dur = min(d / speed, tb - ta) if mode == "speed20" else tb - ta
        gaps.append({"ta": float(ta), "tb": float(tb), "move_deg": d, "move_sec": float(dur)})
        if mode == "linear":
            continue
        m = (t > ta) & (t < tb)
        if not m.any():
            continue
        frac = np.ones(int(m.sum())) if dur <= 0 else np.clip((t[m] - ta) / dur, 0.0, 1.0)
        q[m] = qa + frac[:, None] * (qb - qa)
    return q, gaps


# ---- 1 コマごとの state の出どころ (state_source. int8. 2026-11-14 依頼 196) ----

def select_steps(t, q, g, mode_ts, modes, windows, trim_mid_idle=True, trim_hold=False):
    """学習に使うステップを選び, state / actions を作る (ファイルを読まない部分. テストで使う).

    戻り値: dict(idx=元の t の添字, state, actions, modes, counts)
    """
    state_all = np.concatenate([q, g[:, None]], axis=1).astype(np.float32)
    keep, m_all = step_keep_mask(t, mode_ts, modes, windows)
    idx = np.flatnonzero(keep)
    counts = {"grid_steps": int(len(t)),
              "excluded_mode": int((~np.isin(m_all, (MODE_MODEL, MODE_CORRECT))).sum()),
              "excluded_window": int((np.isin(m_all, (MODE_MODEL, MODE_CORRECT)) & ~keep).sum())}
    if len(idx) == 0:
        return {"idx": idx, "state": state_all[:0], "actions": state_all[:0], "modes": [], "counts": counts}
    state = state_all[idx]
    # 除いたあとに残ったステップでつなぐ. actions は「つないだ並びでの次の state」
    actions = next_state_actions(state)
    k1, idle_trimmed = idle_keep_mask(state, actions)
    idx, state, actions = idx[k1], state[k1], actions[k1]
    counts["idle_trimmed"] = int(idle_trimmed)
    counts["steps_before_mid_trim"] = int(len(idx))
    mid = 0
    if trim_mid_idle and len(idx):
        if trim_hold:
            mk = hold_keep_mask(state, actions, [str(m_all[k]) for k in idx])
        else:
            mk = bde.mid_idle_keep_mask(state, actions)
        mid = int((~mk).sum())
        idx, state, actions = idx[mk], state[mk], actions[mk]
    # trim2 と同じ: 関節 6 列は残ったステップで作り直す. グリッパー列は元の (次の) 指令のまま
    actions = actions.copy()
    actions[:-1, :6] = state[1:, :6]
    actions[-1, :6] = state[-1, :6]
    counts["mid_idle_trimmed"] = mid
    sel_modes = [str(m_all[k]) for k in idx]
    counts["model_steps"] = sel_modes.count(MODE_MODEL)
    counts["correct_steps"] = sel_modes.count(MODE_CORRECT)
    return {"idx": idx, "state": state, "actions": actions, "modes": sel_modes, "counts": counts}


def build_one(run_dir, out_dir, args):
    stem = run_dir.name
    trial_p = run_dir / f"{stem}.json"
    rec = run_dir / "recording"
    if not trial_p.exists():
        return {"run": stem, "used": False, "reason": f"missing:{trial_p.name}"}
    trial = json.loads(trial_p.read_text())
    if trial.get("recording_enabled") is not True:
        return {"run": stem, "used": False, "reason": "no_recording"}
    if trial.get("outcome") != "success":
        return {"run": stem, "used": False, "reason": f"outcome={trial.get('outcome')}"}
    need = [rec / "states.csv", rec / "top.mp4", rec / "top_frame_log.csv"]
    missing = [p.name for p in need if not p.exists()]
    if missing:
        return {"run": stem, "used": False, "reason": "missing:" + ",".join(missing)}
    log = load_log(run_dir / "log.jsonl")
    unfinished = [r for r in log if r.get("type") == "rewind" and not r.get("finished", True)]
    unfinished += [r for r in log if r.get("type") == "correction" and r.get("action") == "cancel"
                   and not r.get("finished", True)]
    if unfinished:
        # 戻りきれなかった巻き戻しがあると, つないだ前後で姿勢が続かない
        return {"run": stem, "used": False, "reason": f"rewind_unfinished x{len(unfinished)}"}

    at, aq, gt, gs = bde.load_states(rec / "states.csv")
    if len(at) < bde.MIN_ACTUAL_SAMPLES:
        return {"run": stem, "used": False, "reason": f"actual 実測が少ない ({len(at)})"}
    order = np.argsort(at); at, aq = at[order], aq[order]
    at, aq = bde.drop_spikes(at, aq)
    try:
        tm = json.loads((rec / "top_meta.json").read_text())
    except Exception:
        tm = {}
    if tm.get("status") != "ok":
        return {"run": stem, "used": False, "reason": f"recording_status={tm.get('status')}"}
    fidx, fts = bde.load_frame_log(rec / "top_frame_log.csv")
    if len(fts) < FPS:
        return {"run": stem, "used": False, "reason": f"top フレームが少ない ({len(fts)})"}
    t0, t1 = max(fts[0], at[0]), min(fts[-1], at[-1])
    if t1 - t0 < 3.0:
        return {"run": stem, "used": False, "reason": "記録の重なりが短い"}
    t = np.arange(t0, t1, 1.0 / FPS)
    gap_fill = getattr(args, "gap_fill", "linear")
    q, gaps = fill_motion_gaps(t, at, aq, mode=gap_fill)
    for g in gaps:
        k = int(np.searchsorted(at, g["tb"]))
        g["qb"] = aq[k]
    gap_match = match_gaps_to_sends(gaps, log)
    g = np.zeros(len(t))
    if len(gt):
        go = np.argsort(gt); gt, gs = gt[go], gs[go]
        for i, ti in enumerate(t):
            k = np.searchsorted(gt, ti, side="right") - 1
            g[i] = gs[k] if k >= 0 else 0.0

    mode_ts, modes = load_stage_times(rec / "states.csv")
    windows = excluded_windows(log)
    trim_hold = getattr(args, "trim_hold", False)
    sel = select_steps(t, q, g, mode_ts, modes, windows, trim_mid_idle=not args.no_trim_mid_idle,
                       trim_hold=trim_hold)
    if len(sel["idx"]) < FPS:
        return {"run": stem, "used": False, "reason": f"使えるステップが少ない ({len(sel['idx'])})"}
    tt = t[sel["idx"]]

    # 依頼 117: つかみの深さで採否を決める (--max-protrude-px のときだけ. 既定では測らない)
    depth = None
    max_pr = getattr(args, "max_protrude_px", None)
    if max_pr is not None:
        import grasp_depth
        drop, why, depth = grasp_depth.judge(run_dir, max_pr,
                                             grasp_depth.first_close_label_time(tt, sel["state"][:, 6]))
        if drop:
            if out_dir.exists():
                why += " (前に作ったエピソードが残っている. 消していない)"
            return {"run": stem, "used": False, "reason": why, "grasp_depth": depth}

    # codex R1-4: 画像の候補も同じ決まりで絞る (除いた区間・rewind / home の画像を, 境界の
    # 最近傍として拾わない). 候補から選ぶので, 除いた時刻の画像は入らない
    fkeep, _ = step_keep_mask(fts, mode_ts, modes, windows)
    fidx, fts = fidx[fkeep], fts[fkeep]
    if len(fts) < 2:
        return {"run": stem, "used": False, "reason": "使える画像が少ない"}
    nearest = np.clip(np.searchsorted(fts, tt), 1, len(fts) - 1)
    left = fts[nearest - 1]; right = fts[nearest]
    nearest = np.where(np.abs(tt - left) <= np.abs(right - tt), nearest - 1, nearest)
    want = {}
    for step, n in enumerate(nearest):
        want.setdefault(int(fidx[n]), []).append(step)

    if out_dir.exists():
        if not args.force:
            return {"run": stem, "used": True, "reason": "既存 (スキップ・--force で再生成)",
                    "steps": int(len(tt))}
        _rmtree(out_dir)
    (out_dir / "frames").mkdir(parents=True)
    cap = cv2.VideoCapture(str(rec / "top.mp4"))
    fi, written, max_need, size = 0, 0, max(want), None
    while fi <= max_need:
        ok, frame = cap.read()
        if not ok:
            break
        if fi in want:
            h, w = frame.shape[:2]
            s = bde.IMG_LONG / max(h, w)
            small = cv2.resize(frame, (round(w * s), round(h * s)), interpolation=cv2.INTER_AREA)
            size = small.shape[1], small.shape[0]
            for step in want[fi]:
                # codex R3 P2: 保存に失敗したコマは数えない (欠けたエピソードを採用しない)
                if cv2.imwrite(str(out_dir / "frames" / f"{step:06d}.jpg"), small,
                               [cv2.IMWRITE_JPEG_QUALITY, bde.JPEG_QUALITY]):
                    written += 1
        fi += 1
    cap.release()
    if written != len(tt):
        _rmtree(out_dir)
        return {"run": stem, "used": False,
                "reason": f"フレーム抽出不足 written={written} steps={len(tt)} (mp4 と frame_log の不一致)"}

    state_source = gap_fill_flags(t, at, aq)[sel["idx"]]
    np.savez_compressed(out_dir / "episode.npz",
                        t=(np.arange(len(tt)) / FPS).astype(np.float64),
                        t_orig=tt - tt[0], state=sel["state"], actions=sel["actions"],
39:  python3 pi05/build_correction_episodes.py --run pi05_20261030_101500 --force
311:def select_steps(t, q, g, mode_ts, modes, windows, trim_mid_idle=True, trim_hold=False):
314:    戻り値: dict(idx=元の t の添字, state, actions, modes, counts)
318:    idx = np.flatnonzero(keep)
322:    if len(idx) == 0:
323:        return {"idx": idx, "state": state_all[:0], "actions": state_all[:0], "modes": [], "counts": counts}
324:    state = state_all[idx]
328:    idx, state, actions = idx[k1], state[k1], actions[k1]
330:    counts["steps_before_mid_trim"] = int(len(idx))
332:    if trim_mid_idle and len(idx):
333:        if trim_hold:
334:            mk = hold_keep_mask(state, actions, [str(m_all[k]) for k in idx])
338:        idx, state, actions = idx[mk], state[mk], actions[mk]
344:    sel_modes = [str(m_all[k]) for k in idx]
347:    return {"idx": idx, "state": state, "actions": actions, "modes": sel_modes, "counts": counts}
350:def build_one(run_dir, out_dir, args):
384:    fidx, fts = bde.load_frame_log(rec / "top_frame_log.csv")
406:    trim_hold = getattr(args, "trim_hold", False)
407:    sel = select_steps(t, q, g, mode_ts, modes, windows, trim_mid_idle=not args.no_trim_mid_idle,
408:                       trim_hold=trim_hold)
409:    if len(sel["idx"]) < FPS:
410:        return {"run": stem, "used": False, "reason": f"使えるステップが少ない ({len(sel['idx'])})"}
411:    tt = t[sel["idx"]]
419:                                             grasp_depth.first_close_label_time(tt, sel["state"][:, 6]))
421:            if out_dir.exists():
428:    fidx, fts = fidx[fkeep], fts[fkeep]
436:        want.setdefault(int(fidx[n]), []).append(step)
438:    if out_dir.exists():
439:        if not args.force:
440:            return {"run": stem, "used": True, "reason": "既存 (スキップ・--force で再生成)",
442:        _rmtree(out_dir)
443:    (out_dir / "frames").mkdir(parents=True)
457:                if cv2.imwrite(str(out_dir / "frames" / f"{step:06d}.jpg"), small,
463:        _rmtree(out_dir)
467:    state_source = gap_fill_flags(t, at, aq)[sel["idx"]]
468:    np.savez_compressed(out_dir / "episode.npz",
470:                        t_orig=tt - tt[0], state=sel["state"], actions=sel["actions"],
473:    c = sel["counts"]
478:        "trim_mid_idle": not args.no_trim_mid_idle,
479:        "trim_hold": ({"keep_model": HOLD_KEEP_MODEL, "keep_correct": HOLD_KEEP_CORRECT,
480:                       "keep_grip": HOLD_KEEP_GRIP} if trim_hold and not args.no_trim_mid_idle else None),
508:                         (np.abs(np.diff(sel["state"][:, :6], axis=0)).max(axis=0) if len(sel["state"]) > 1
510:        "step_modes": sel["modes"],
512:    (out_dir / "meta.json").write_text(json.dumps(meta, indent=2, ensure_ascii=False))
567:        + ("" if not args.no_trim_mid_idle else " --no-trim-mid-idle")
569:        + (" --trim-hold" if getattr(args, "trim_hold", False) else "")
580:        + ("" if not getattr(args, "trim_hold", False) else
630:    ap.add_argument("--force", action="store_true", help="既存エピソードを作り直す")
644:    if args.trim_hold and args.no_trim_mid_idle:

exec
/bin/zsh -lc 'PYTHONDONTWRITEBYTECODE=1 python3 -m unittest pi05.test_state_source.TestFlags.test_motion_gap_is_1 pi05.test_state_source.TestFlags.test_still_gap_is_2 pi05.test_state_source.TestFlags.test_flags_mark_exactly_what_speed20_changes pi05.test_state_source.TestFlags.test_no_gap_no_flag -v' in /Users/shimazueiichi/r2r2r-scripts
 succeeded in 2020ms:
python3: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead
python3: error: couldn't create cache file '/tmp/xcrun_db-5TP6ATAD' (errno=Operation not permitted)
python3: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead
python3: error: couldn't create cache file '/tmp/xcrun_db-IQ6Btzl5' (errno=Operation not permitted)
test_motion_gap_is_1 (pi05.test_state_source.TestFlags) ... ok
test_still_gap_is_2 (pi05.test_state_source.TestFlags) ... ok
test_flags_mark_exactly_what_speed20_changes (pi05.test_state_source.TestFlags)
speed20 が線形補間から変えたコマは, すべて印が 0 でないコマ. ... ok
test_no_gap_no_flag (pi05.test_state_source.TestFlags) ... ok

----------------------------------------------------------------------
Ran 4 tests in 0.002s

OK

exec
/bin/zsh -lc "nl -ba pi05/diag_fill_flags.py | sed -n '109,138p'; git status --short" in /Users/shimazueiichi/r2r2r-scripts
 succeeded in 0ms:
   109	                     "not_counted": len(rs) - len(ok), "steps": steps, "filled_steps": filled,
   110	                     "filled_motion_steps": sum(r["filled_motion_steps"] for r in ok),
   111	                     "filled_ratio": round(filled / steps, 4) if steps else "",
   112	                     "max_episode": top["episode"] if top else "",
   113	                     "max_episode_ratio": top["filled_ratio"] if top else ""})
   114	    with (out_dir / "summary.csv").open("w", newline="") as f:
   115	        w = csv.DictWriter(f, fieldnames=list(summ[0].keys()))
   116	        w.writeheader(); w.writerows(summ)
   117	    (out_dir / "README.md").write_text(
   118	        "# fill_flags_20261114 (依頼 196)\n\n"
   119	        "既存の補正データセットで, 実測角の抜けを埋めたコマ (state_source が 1 または 2) の数と割合。\n"
   120	        "`python3 pi05/diag_fill_flags.py` で作った。データセットは読むだけ。作り直しは /tmp。\n\n"
   121	        "- state_source: 0 = 実測角 / 1 = 動いた抜けを埋めた値 / 2 = 動かなかった抜けを埋めた値\n"
   122	        "- filled_ratio = (1 と 2 のコマ) / 全コマ。filled_motion_steps は 1 のコマの数\n"
   123	        "- status が ok でない本 (作り直した state / actions / t がデータセットと一致しない・作り直せない) は数えない\n"
   124	        "- episodes.csv: 本ごと / summary.csv: データセットごと (max_episode = 割合がいちばん多い本)\n")
   125	    print(f"→ {out_dir}")
   126	    return 0
   127	
   128	
   129	if __name__ == "__main__":
   130	    sys.exit(main())
git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead
git: error: couldn't create cache file '/tmp/xcrun_db-2alXXSXW' (errno=Operation not permitted)
git: warning: confstr() failed with code 5: couldn't get path of DARWIN_USER_TEMP_DIR; using /tmp instead
git: error: couldn't create cache file '/tmp/xcrun_db-xU66tj9U' (errno=Operation not permitted)
 M dynamic_tracking_limits/diag/j4_probe.py
 M dynamic_tracking_limits/drag_teaching/waypoint_streaming_replay.py
 M dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_02.json
 M dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_03.json
 M dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_04.json
 M dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_06.json
 M dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_07.json
 M dynamic_tracking_limits/place/place_modules/06f_top_white_box_detect_v7.py
 M observe/emit.py
 M observe/static/index.html
 M pi05/DEEP_DEMOS.md
 M pi05/build_correction_episodes.py
 M pi05/policy_recorder.py
 M visual_servo_pick.py
?? AGENTS.md
?? DAY181_FIX_BENCH_MAC.md
?? DAY181_FIX_BENCH_MAC_SHELL.md
?? DAY181_FIX_DAEMON_STDOUT.md
?? DAY181_TASK_BENCH_MAC.md
?? analyze_rotation_log06.py
?? archive/
?? block_positions.csv
?? calibrate_homography.py.bak_DAY168_pre_unified
?? calibrate_visual_servo.py
?? calibrate_z_axis_DAY189.py
?? calibrate_z_axis_DAY191_descend.py
?? calibration_reference.md
?? calibration_visual_servo_20260428_184513.csv
?? calibration_visual_servo_20260428_190234.csv
?? calibration_visual_servo_20260428_190453.csv
?? calibration_visual_servo_20260428_191234.csv
?? calibration_z_axis_DAY189_20260505_184248.csv
?? calibration_z_axis_DAY189_20260505_184444.csv
?? calibration_z_axis_DAY189_20260505_185644.csv
?? calibration_z_axis_DAY191_descend_pose_20260506_192217.csv
?? calibration_z_axis_DAY191_descend_pose_20260621_173245.csv
?? calibration_z_axis_DAY191_descend_pose_20260621_173839.csv
?? calibration_z_axis_DAY191_descend_pose_20260621_174508.csv
?? camera_check.py
?? camera_judge.py
?? capture_top_frames.py
?? capture_top_frames_log06.py
?? capture_top_frames_log07.py
?? capture_top_frames_log08.py
?? capture_white_box_templates.py
?? check_camera.py
?? claude_code_reports/
?? close_gripper.py
?? collect_block_positions.py
?? debug_auto/
?? debug_calib/
?? debug_camera_orientation.py
?? debug_detection.png
?? debug_detection.py
?? debug_mat_corner/
?? debug_mat_corners.py
?? debug_noise_test/
?? debug_snapshots/
?? debug_visual_servo/
?? detect_block_position.py
?? detect_blue_markers.py
?? detect_cover_corners_log07.py
?? detect_cover_edges_log07.py
?? detect_on_mat.py
?? detection_noise_test.py
?? diag_stage2_send.py
?? docs/diff_20261019_items1-8.txt
?? docs/diff_20261019_minabort.txt
?? docs/diff_20261019_r10_gripper.txt
?? docs/diff_20261019_r10fix.txt
?? docs/diff_20261019_r11fix.txt
?? docs/diff_20261019_shoulderfix.txt
?? docs/investigation_20261019_stageC_daemon_latency.md
?? docs/procedure_20261019_stageC_record_teach_demo.md
?? docs/review_request_20261018_wpsr_grip_push_hold.md
?? docs/review_request_20261019_r11_mainline_alignment.md
?? docs/review_request_20261019_record_teach_demo.md
?? docs/review_request_20261101_servo_check.md
?? docs/review_request_20261101_servo_check_r2.md
?? docs/review_result_20261018_wpsr_grip_push_hold_codex.md
?? docs/review_result_20261019_r11_codex.md
?? docs/review_result_20261019_r11b_codex.md
?? docs/review_result_20261019_r12_codex.md
?? docs/review_result_20261019_r13_codex.md
?? docs/review_result_20261019_record_teach_demo_codex.md
?? docs/review_result_20261019_record_teach_demo_codex_r10.md
?? docs/review_result_20261019_record_teach_demo_codex_r10b.md
?? docs/review_result_20261019_record_teach_demo_codex_r2.md
?? docs/review_result_20261019_record_teach_demo_codex_r3.md
?? docs/review_result_20261019_record_teach_demo_codex_r4.md
?? docs/review_result_20261019_record_teach_demo_codex_r6.md
?? docs/review_result_20261019_record_teach_demo_codex_r7.md
?? docs/review_result_20261019_record_teach_demo_codex_r8.md
?? docs/review_result_20261019_record_teach_demo_codex_r9.md
?? docs/review_result_20261101_servo_check_codex.md
?? dryrun_check.py
?? dynamic_pick_correct_20260428_121924.csv
?? dynamic_pick_correct_20260428_124241.csv
?? dynamic_pick_verify_20260428_105412.csv
?? dynamic_pick_verify_auto_20260428_111229.csv
?? dynamic_pick_verify_auto_20260428_111649.csv
?? dynamic_pick_verify_auto_20260428_113234.csv
?? dynamic_tracking_limits/VLM_REPO_INVENTORY.md
?? dynamic_tracking_limits/diag/j4_home_only.py
?? dynamic_tracking_limits/diag/j4_probe.py.bak_DAY239_pre_oneway
?? dynamic_tracking_limits/diag/logs/
?? dynamic_tracking_limits/drag_teaching/_archive/
?? dynamic_tracking_limits/drag_teaching/check_teaching_pose.py
?? dynamic_tracking_limits/drag_teaching/grasp_lift_pick_then_place.py
?? dynamic_tracking_limits/drag_teaching/grasp_lift_test.py
?? dynamic_tracking_limits/drag_teaching/record_teach_demo.py
?? dynamic_tracking_limits/drag_teaching/record_teach_demo.py.bak_pre_req121_20261108
?? dynamic_tracking_limits/drag_teaching/record_teach_demo.py.bak_pre_req152_20261111
?? dynamic_tracking_limits/drag_teaching/record_teach_demo.py.bak_pre_req156_20261112
?? dynamic_tracking_limits/drag_teaching/replay_z_postures.py
?? dynamic_tracking_limits/drag_teaching/replay_z_postures.py.bak_DAY243_pre_none_safe
?? dynamic_tracking_limits/drag_teaching/replay_z_simple.py
?? dynamic_tracking_limits/logs/j0_sweep/_INDEX.md
?? dynamic_tracking_limits/logs/j0_sweep/j0_pick_sweep20_01.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_pick_sweep20_02.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_pick_sweep20_03.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_adopted/
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_01.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_05.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_08.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_09.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_10.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_pick_11.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_01.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_02.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_03.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_04.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_05.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_06.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_07.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_08.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_09.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_10.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_11.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_12.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_13.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_14.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_15.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_16.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_17.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_18.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_19.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_20.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_21.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_22.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_approach_place_23.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_classified/
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_01.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_02.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_03.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_04.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_05.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_06.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_07.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_08.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_09.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_10.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_11.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_12.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_13.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_14.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_15.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_16.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_17.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_18.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_19.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_20.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_21.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_22.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_23.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_24.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_25.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_simple_01.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_pick_simple_02.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_01.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_02.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_03.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_04.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_05.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_06.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_07.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_08.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_09.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_10.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_11.json
?? dynamic_tracking_limits/logs/j0_sweep/j0_sweep_place_12.json
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_side_1.png
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_side_2.png
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_side_3.png
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_side_4.png
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_side_5.png
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_top_1.png
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_top_2.png
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_top_3.png
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_top_4.png
?? dynamic_tracking_limits/logs/place_capture_20260521_150159_top_5.png
?? dynamic_tracking_limits/logs/run_pick_place/
?? dynamic_tracking_limits/logs/vlm_framing_test/
?? dynamic_tracking_limits/place/diag_scripts/
?? dynamic_tracking_limits/place/place_modules/30mm
?? dynamic_tracking_limits/place/place_modules/J0_SWEEP_HOWTO.md
?? dynamic_tracking_limits/place/place_modules/_archive/
?? dynamic_tracking_limits/place/place_modules/corr_map_server.py
?? dynamic_tracking_limits/place/place_modules/diag_place_z_move.py
?? dynamic_tracking_limits/place/place_modules/handover_pose_step.py
?? dynamic_tracking_limits/place/place_modules/j0_lookup.py
?? dynamic_tracking_limits/place/place_modules/j4_isolation_test.py
?? dynamic_tracking_limits/place/place_modules/place_j0_sweep_20_scan.py
?? dynamic_tracking_limits/place/place_modules/preview_place_delta.py
?? dynamic_tracking_limits/place/place_modules/recorder.py.bak_20261015_pre_top_camera
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_20261015_pre_record_demo
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_20261016_pre_freeze_height
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY239_pre_observe_emit
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY239_pre_revert_skip6
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY239_pre_stage7_tol
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_block_place
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_blockbox_emit
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_codex_fix
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_dry_skip_ledger
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_in_box
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_ledger
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_place_skip_unknown
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_regrasp_block_sync
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_stage_emit
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_swept_tol
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_tip_measure
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY241_pre_verdict_emit
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY242_pre_aggregate
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY242_pre_caps
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY242_pre_tip_panel
?? dynamic_tracking_limits/place/place_modules/run_pick_place.py.bak_DAY243_pre_lift_back_tol
?? dynamic_tracking_limits/place/place_modules/static_corr_map/
?? dynamic_tracking_limits/place/place_modules/teach_place_poses.py
?? dynamic_tracking_limits/place/place_modules/vlm_framing_test.py
?? "dynamic_tracking_limits/place/place_modules/\347\240\264\347\266\273\351\226\276\345\200\244"
?? dynamic_tracking_limits/place/scan_input_place_lowz_DAY281.csv
?? dynamic_tracking_limits/place/templates/
?? dynamic_tracking_limits/place/templates_old_rough/
?? dynamic_tracking_limits/place/templates_skewed/
?? evaluate_matches_log07.py
?? experiments/grip_hold_capture_diag.py
?? experiments/hand_view_check.py
?? experiments/place_hole_fill_in_DAY265.py
?? experiments/place_hole_map_DAY265.py
?? experiments/place_hole_map_v3_merge_DAY265.py
?? experiments/place_seed_clusters_DAY265.py
?? fk_calibration_result_20260428_101335.csv
?? fk_calibration_result_20260428_102305.csv
?? fk_scan_calibration.csv
?? fk_scan_calibration.py
?? fk_scan_lowerleft_dense.csv
?? fk_scan_motion_based.csv.bak_DAY154
?? fk_scan_motion_based.csv.bak_DAY155
?? fk_scan_motion_based.csv.bak_DAY170_pre_overwrite_20260425_151008
?? fresh_mode_bench_mac.py
?? fresh_mode_bench_pi.py
?? fresh_mode_daemon.py
?? fresh_mode_sweep_pi.py
?? generate_grid_angles.py
?? grid_angles.csv
?? gripper_check.py
?? homography.npy.bak_20260420_181438
?? homography.npy.bak_20260424_194547
?? interpolate_motion.py
?? j0_send_test.py
?? judge_frame.jpg
?? logs/20260417_1500.md
?? logs/20260417_summary.md
?? logs/20260417_verify_y_fix.md
?? logs/20260803_0006.md
?? logs/20260807_0757.md
?? logs/20260807_0801.md
?? logs/20260807_0808.md
?? logs/20260807_0831.md
?? logs/20260807_0836.md
?? logs/20260807_0840.md
?? logs/20260807_0859.md
?? logs/20260807_0939.md
?? logs/20260807_0959.md
?? logs/20260807_1013.md
?? logs/20260807_1034.md
?? logs/20260807_1055.md
?? logs/20260807_1224.md
?? logs/20261018_1901.md
?? logs/20261019_1139.md
?? logs/20261019_1826.md
?? logs/20261019_1852.md
?? logs/20261019_1930.md
?? logs/20261021_0839.md
?? logs/20261021_0912.md
?? logs/20261029_2026.md
?? logs/20261030_1415.md
?? logs/20261030_1750.md
?? logs/20261101_1100.md
?? logs/20261109_1250.md
?? logs/20261109_1325.md
?? logs/20261109_1600.md
?? logs/20261109_1800.md
?? logs/20261109_2120.md
?? logs/20261110_1740.md
?? logs/20261110_2105.md
?? logs/20261110_2155.md
?? logs/20261110_2240.md
?? logs/20261111_1140.md
?? logs/20261112_1219.md
?? logs/20261113_2200.md
?? logs/20261114_0446.md
?? logs/20261114_0743.md
?? logs/20261114_1916.md
?? logs/20261114_1928.md
?? logs/20261114_1940.md
?? logs/20261114_2052.md
?? logs/20261114_2240.md
?? logs/20261114_2245.md
?? logs/20261114_2250.md
?? logs/20261114_2300.md
?? logs/20261114_2308.md
?? logs/20261114_2313.md
?? logs/20261114_2315.md
?? logs/20261114_2320.md
?? logs/20261114_2324.md
?? logs/20261114_2329.md
?? logs/DAY153_approach_addition.md
?? logs/DAY153_camera_index_fix.md
?? logs/DAY153_detection_debug.md
?? logs/DAY153_detection_fix.md
?? logs/DAY153_implementation_summary.md
?? logs/DAY153_pre_summary.md
?? logs/DAY153_self_check.md
?? logs/DAY154_place_dynamic.md
?? logs/DAY154_scan_setup.md
?? logs/DAY154_scan_verify.md
?? logs/DAY158_rename_summary.md
?? logs/DAY169_tipbrep_reader_creation.log
?? logs/DAY169_verify_lookup.log
?? logs/calib_frames/
?? logs/debug_frames/
?? logs/debug_side_white_mask_20260519_194345.jpg
?? logs/debug_side_white_mask_20260519_194408.jpg
?? logs/debug_side_white_mask_20260519_194441.jpg
?? logs/debug_side_white_mask_20260519_194458.jpg
?? logs/debug_side_white_mask_20260519_194518.jpg
?? logs/debug_side_white_mask_20260519_194543.jpg
?? logs/debug_side_white_mask_20260519_194606.jpg
?? logs/debug_side_white_mask_20260519_194620.jpg
?? logs/debug_side_white_mask_20260519_194624.jpg
?? logs/debug_side_white_mask_20260519_194642.jpg
?? logs/debug_white_score_DAY209_20260519_190850.jpg
?? logs/debug_white_score_DAY209_20260519_190915.jpg
?? logs/debug_white_score_DAY209_20260519_190928.jpg
?? logs/debug_white_score_DAY209_20260519_190942.jpg
?? logs/debug_white_score_DAY209_20260519_190957.jpg
?? logs/debug_white_score_DAY209_20260519_191117.jpg
?? logs/debug_white_score_DAY209_20260519_191130.jpg
?? logs/debug_white_score_DAY209_20260519_191142.jpg
?? logs/debug_white_score_DAY209_20260519_191154.jpg
?? logs/debug_white_score_DAY209_20260519_191337.jpg
?? logs/debug_white_score_DAY209_20260519_191347.jpg
?? logs/debug_white_score_DAY209_20260519_191358.jpg
?? logs/debug_white_score_DAY209_20260519_191413.jpg
?? logs/debug_white_score_DAY209_20260519_191424.jpg
?? logs/debug_white_score_DAY209_20260519_191435.jpg
?? logs/debug_white_score_DAY209_20260519_192857.jpg
?? logs/debug_white_score_DAY209_20260519_193136.jpg
?? logs/debug_white_score_DAY209_20260519_193202.jpg
?? logs/debug_white_score_DAY209_20260519_193228.jpg
?? logs/debug_white_score_DAY209_20260519_193254.jpg
?? logs/debug_white_score_DAY209_20260519_193318.jpg
?? logs/debug_white_score_DAY209_20260519_193348.jpg
?? logs/descend_log_20260602_183303.csv
?? logs/descend_log_20260602_183726.csv
?? logs/descend_log_20260602_184021.csv
?? logs/descend_log_20260602_184121.csv
?? logs/descend_log_20260602_184405.csv
?? logs/descend_log_20260602_195623.csv
?? logs/descend_log_20260602_200931.csv
?? logs/descend_log_20260602_201627.csv
?? logs/descend_log_20260603_103022.csv
?? logs/descend_log_20260603_121403.csv
?? logs/descend_log_20260603_121543.csv
?? logs/descend_log_20260603_122414.csv
?? logs/descend_log_20260603_122519.csv
?? logs/descend_log_20260603_130502.csv
?? logs/descend_log_20260603_135148.csv
?? logs/descend_log_20260603_142211.csv
?? logs/descend_log_20260603_142550.csv
?? logs/descend_log_20260603_142711.csv
?? logs/descend_log_20260603_143427.csv
?? logs/descend_log_20260603_164819.csv
?? logs/descend_log_20260603_172047.csv
?? logs/descend_log_20260603_172141.csv
?? logs/descend_log_20260603_181621.csv
?? logs/descend_log_20260603_181833.csv
?? logs/descend_log_20260603_182100.csv
?? logs/descend_log_20260603_182254.csv
?? logs/descend_log_20260603_182424.csv
?? logs/descend_log_20260603_182542.csv
?? logs/descend_log_20260603_182700.csv
?? logs/descend_log_20260603_182816.csv
?? logs/descend_log_20260603_182939.csv
?? logs/descend_log_20260603_183131.csv
?? logs/descend_log_20260604_100440.csv
?? logs/descend_log_20260604_100604.csv
?? logs/descend_log_20260604_100753.csv
?? logs/descend_log_20260604_100924.csv
?? logs/descend_log_20260604_101105.csv
?? logs/descend_log_20260604_101232.csv
?? logs/descend_log_20260604_102108.csv
?? logs/descend_log_20260604_103759.csv
?? logs/descend_log_20260604_105959.csv
?? logs/descend_log_20260606_191135.csv
?? logs/descend_log_20260606_191454.csv
?? logs/descend_log_20260606_191620.csv
?? logs/descend_log_20260606_191746.csv
?? logs/descend_log_20260606_194001.csv
?? logs/descend_log_20260606_194546.csv
?? logs/descend_log_20260606_201548.csv
?? logs/descend_log_20260606_201857.csv
?? logs/descend_log_20260606_202158.csv
?? logs/descend_log_20260606_202542.csv
?? logs/descend_log_20260606_202803.csv
?? logs/descend_log_20260606_203035.csv
?? logs/descend_log_20260606_203358.csv
?? logs/detect_place_sample_01_box_right_far.jpg
?? logs/detect_place_sample_02_box_right_far_v2.jpg
?? logs/detect_place_sample_03_box_left_far.jpg
?? logs/detect_place_sample_04_box_left_close.jpg
?? logs/detect_place_sample_05_correct_position.jpg
?? logs/joint_debug.md
?? logs/link6_debug.md
?? logs/lookup_test_20260417_1834.txt
?? logs/place_align_log_20260603_122421.csv
?? logs/place_align_log_20260603_122531.csv
?? logs/place_align_log_20260603_142602.csv
?? logs/place_align_log_20260603_143441.csv
?? logs/place_release_trials.csv
?? logs/place_test_20260519_210457.csv
?? logs/place_test_20260519_210457.txt
?? logs/place_test_20260519_211301.csv
?? logs/place_test_20260519_211301.txt
?? logs/place_test_20260519_211511.csv
?? logs/place_test_20260519_211511.txt
?? logs/place_test_20260519_211550.csv
?? logs/place_test_20260519_211550.txt
?? logs/place_test_20260519_211633.csv
?? logs/place_test_20260519_211633.txt
?? logs/place_test_20260519_211639.csv
?? logs/place_test_20260519_211639.txt
?? logs/place_test_20260519_211905.csv
?? logs/place_test_20260519_211905.txt
?? logs/place_test_20260519_212654.csv
?? logs/place_test_20260519_212654.txt
?? logs/place_test_20260519_212812.csv
?? logs/place_test_20260519_212812.txt
?? logs/place_test_20260519_213204.csv
?? logs/place_test_20260519_213204.txt
?? logs/place_test_20260519_213323.csv
?? logs/place_test_20260519_213323.txt
?? logs/place_test_20260519_213543.csv
?? logs/place_test_20260519_213543.txt
?? logs/place_test_20260519_213619.csv
?? logs/place_test_20260519_213619.txt
?? logs/place_test_20260519_213703.csv
?? logs/place_test_20260519_213703.txt
?? logs/place_test_20260519_213923.csv
?? logs/place_test_20260519_213923.txt
?? logs/place_test_20260519_214020.csv
?? logs/place_test_20260519_214020.txt
?? logs/place_test_20260519_214200.csv
?? logs/place_test_20260519_214200.txt
?? logs/place_test_20260520_101000.csv
?? logs/place_test_20260520_101000.txt
?? logs/place_test_20260520_101102.csv
?? logs/place_test_20260520_101102.txt
?? logs/place_test_20260520_101215.csv
?? logs/place_test_20260520_101215.txt
?? logs/place_test_20260520_101247.csv
?? logs/place_test_20260520_101247.txt
?? logs/place_test_20260520_103914.csv
?? logs/place_test_20260520_103914.txt
?? logs/place_test_20260520_103928.csv
?? logs/place_test_20260520_103928.txt
?? logs/place_test_20260520_104457.csv
?? logs/place_test_20260520_104457.txt
?? logs/place_test_20260520_105102.csv
?? logs/place_test_20260520_105102.txt
?? logs/place_test_20260520_105417.csv
?? logs/place_test_20260520_105417.txt
?? logs/place_test_20260520_105427.csv
?? logs/place_test_20260520_105427.txt
?? logs/place_test_20260520_105514.csv
?? logs/place_test_20260520_105514.txt
?? logs/place_test_20260520_105530.csv
?? logs/place_test_20260520_105530.txt
?? logs/place_test_20260520_105825.csv
?? logs/place_test_20260520_105825.txt
?? logs/place_test_20260520_110424.csv
?? logs/place_test_20260520_110424.txt
?? logs/place_test_20260520_110439.csv
?? logs/place_test_20260520_110439.txt
?? logs/place_test_20260520_110731.csv
?? logs/place_test_20260520_110731.txt
?? logs/place_test_20260520_111024.csv
?? logs/place_test_20260520_111024.txt
?? logs/place_test_20260520_111106.csv
?? logs/place_test_20260520_111106.txt
?? logs/place_test_20260520_111905.csv
?? logs/place_test_20260520_111905.txt
?? logs/place_test_20260520_111923.csv
?? logs/place_test_20260520_111923.txt
?? logs/place_test_20260520_112204.csv
?? logs/place_test_20260520_112204.txt
?? logs/place_test_20260520_112249.csv
?? logs/place_test_20260520_112249.txt
?? logs/place_test_20260520_112305.csv
?? logs/place_test_20260520_112305.txt
?? logs/place_test_20260520_112320.csv
?? logs/place_test_20260520_112320.txt
?? logs/place_test_20260520_112610.csv
?? logs/place_test_20260520_112610.txt
?? logs/place_test_20260520_112626.csv
?? logs/place_test_20260520_112626.txt
?? logs/place_test_20260520_112709.csv
?? logs/place_test_20260520_112709.txt
?? logs/place_test_20260520_112751.csv
?? logs/place_test_20260520_112751.txt
?? logs/place_test_20260520_112835.csv
?? logs/place_test_20260520_112835.txt
?? logs/place_test_20260520_113311.csv
?? logs/place_test_20260520_113311.txt
?? logs/place_test_20260520_113311_cleanup_home_side.png
?? logs/place_test_20260520_113311_cleanup_home_top.png
?? logs/place_test_20260520_113330.csv
?? logs/place_test_20260520_113330.txt
?? logs/place_test_20260520_113330_cleanup_home_side.png
?? logs/place_test_20260520_113330_cleanup_home_top.png
?? logs/place_test_20260520_113330_phase0_home_side.png
?? logs/place_test_20260520_113330_phase0_home_top.png
?? logs/place_test_20260520_113330_phase2_approach_side.png
?? logs/place_test_20260520_113330_phase2_approach_top.png
?? logs/place_test_20260520_113716.csv
?? logs/place_test_20260520_113716.txt
?? logs/place_test_20260520_113716_cleanup_home_side.png
?? logs/place_test_20260520_113716_cleanup_home_top.png
?? logs/place_test_20260520_113716_phase0_home_side.png
?? logs/place_test_20260520_113716_phase0_home_top.png
?? logs/place_test_20260520_113716_phase2_approach_side.png
?? logs/place_test_20260520_113716_phase2_approach_top.png
?? logs/place_test_20260520_113835.csv
?? logs/place_test_20260520_113835.txt
?? logs/place_test_20260520_113835_cleanup_home_side.png
?? logs/place_test_20260520_113835_cleanup_home_top.png
?? logs/place_test_20260520_113835_phase0_home_side.png
?? logs/place_test_20260520_113835_phase0_home_top.png
?? logs/place_test_20260520_113835_phase2_approach_side.png
?? logs/place_test_20260520_113835_phase2_approach_top.png
?? logs/place_test_20260520_114124.csv
?? logs/place_test_20260520_114124.txt
?? logs/place_test_20260520_114124_cleanup_home_side.png
?? logs/place_test_20260520_114124_cleanup_home_top.png
?? logs/place_test_20260520_114141.csv
?? logs/place_test_20260520_114141.txt
?? logs/place_test_20260520_114141_cleanup_home_side.png
?? logs/place_test_20260520_114141_cleanup_home_top.png
?? logs/place_test_20260520_114141_phase0_home_side.png
?? logs/place_test_20260520_114141_phase0_home_top.png
?? logs/place_test_20260520_114141_phase2_approach_side.png
?? logs/place_test_20260520_114141_phase2_approach_top.png
?? logs/place_test_20260520_114449.csv
?? logs/place_test_20260520_114449.txt
?? logs/place_test_20260520_114449_cleanup_home_side.png
?? logs/place_test_20260520_114449_cleanup_home_top.png
?? logs/place_test_20260520_114507.csv
?? logs/place_test_20260520_114507.txt
?? logs/place_test_20260520_114507_cleanup_home_side.png
?? logs/place_test_20260520_114507_cleanup_home_top.png
?? logs/place_test_20260520_114507_phase0_home_side.png
?? logs/place_test_20260520_114507_phase0_home_top.png
?? logs/place_test_20260520_114507_phase2_approach_side.png
?? logs/place_test_20260520_114507_phase2_approach_top.png
?? logs/place_test_20260520_114634.csv
?? logs/place_test_20260520_114634.txt
?? logs/place_test_20260520_114634_cleanup_home_side.png
?? logs/place_test_20260520_114634_cleanup_home_top.png
?? logs/place_test_20260520_114650.csv
?? logs/place_test_20260520_114650.txt
?? logs/place_test_20260520_114650_cleanup_home_side.png
?? logs/place_test_20260520_114650_cleanup_home_top.png
?? logs/place_test_20260520_114650_phase0_home_side.png
?? logs/place_test_20260520_114650_phase0_home_top.png
?? logs/place_test_20260520_114650_phase2_approach_side.png
?? logs/place_test_20260520_114650_phase2_approach_top.png
?? logs/place_test_20260520_114947.csv
?? logs/place_test_20260520_114947.txt
?? logs/place_test_20260520_114947_cleanup_home_side.png
?? logs/place_test_20260520_114947_cleanup_home_top.png
?? logs/place_test_20260520_115003.csv
?? logs/place_test_20260520_115003.txt
?? logs/place_test_20260520_115003_cleanup_home_side.png
?? logs/place_test_20260520_115003_cleanup_home_top.png
?? logs/place_test_20260520_115003_phase0_home_side.png
?? logs/place_test_20260520_115003_phase0_home_top.png
?? logs/place_test_20260520_115003_phase2_approach_side.png
?? logs/place_test_20260520_115003_phase2_approach_top.png
?? logs/place_test_20260520_115124.csv
?? logs/place_test_20260520_115124.txt
?? logs/place_test_20260520_115124_cleanup_home_side.png
?? logs/place_test_20260520_115124_cleanup_home_top.png
?? logs/place_test_20260520_115140.csv
?? logs/place_test_20260520_115140.txt
?? logs/place_test_20260520_115140_cleanup_home_side.png
?? logs/place_test_20260520_115140_cleanup_home_top.png
?? logs/place_test_20260520_115214.csv
?? logs/place_test_20260520_115214.txt
?? logs/place_test_20260520_115214_cleanup_home_side.png
?? logs/place_test_20260520_115214_cleanup_home_top.png
?? logs/place_test_20260520_115308.csv
?? logs/place_test_20260520_115308.txt
?? logs/place_test_20260520_115308_cleanup_home_side.png
?? logs/place_test_20260520_115308_cleanup_home_top.png
?? logs/place_test_20260520_115325.csv
?? logs/place_test_20260520_115325.txt
?? logs/place_test_20260520_115325_cleanup_home_side.png
?? logs/place_test_20260520_115325_cleanup_home_top.png
?? logs/place_test_20260520_115325_phase0_home_side.png
?? logs/place_test_20260520_115325_phase0_home_top.png
?? logs/place_test_20260520_115325_phase2_approach_side.png
?? logs/place_test_20260520_115325_phase2_approach_top.png
?? logs/place_test_20260520_115413.csv
?? logs/place_test_20260520_115413.txt
?? logs/place_test_20260520_115413_cleanup_home_side.png
?? logs/place_test_20260520_115413_cleanup_home_top.png
?? logs/place_test_20260520_115429.csv
?? logs/place_test_20260520_115429.txt
?? logs/place_test_20260520_115429_cleanup_home_side.png
?? logs/place_test_20260520_115429_cleanup_home_top.png
?? logs/place_test_20260520_115429_phase0_home_side.png
?? logs/place_test_20260520_115429_phase0_home_top.png
?? logs/place_test_20260520_115429_phase2_approach_side.png
?? logs/place_test_20260520_115429_phase2_approach_top.png
?? logs/place_test_20260520_115823.csv
?? logs/place_test_20260520_115823.txt
?? logs/place_test_20260520_115823_cleanup_home_side.png
?? logs/place_test_20260520_115823_cleanup_home_top.png
?? logs/place_test_20260520_115840.csv
?? logs/place_test_20260520_115840.txt
?? logs/place_test_20260520_115840_cleanup_home_side.png
?? logs/place_test_20260520_115840_cleanup_home_top.png
?? logs/place_test_20260520_115840_phase0_home_side.png
?? logs/place_test_20260520_115840_phase0_home_top.png
?? logs/place_test_20260520_115840_phase2_approach_side.png
?? logs/place_test_20260520_115840_phase2_approach_top.png
?? logs/place_test_20260520_115929.csv
?? logs/place_test_20260520_115929.txt
?? logs/place_test_20260520_115929_cleanup_home_side.png
?? logs/place_test_20260520_115929_cleanup_home_top.png
?? logs/place_test_20260520_115929_phase0_home_side.png
?? logs/place_test_20260520_115929_phase0_home_top.png
?? logs/place_test_20260520_115929_phase2_approach_side.png
?? logs/place_test_20260520_115929_phase2_approach_top.png
?? logs/place_test_20260520_120021.csv
?? logs/place_test_20260520_120021.txt
?? logs/place_test_20260520_120021_cleanup_home_side.png
?? logs/place_test_20260520_120021_cleanup_home_top.png
?? logs/place_test_20260520_120021_phase0_home_side.png
?? logs/place_test_20260520_120021_phase0_home_top.png
?? logs/place_test_20260520_120021_phase2_approach_side.png
?? logs/place_test_20260520_120021_phase2_approach_top.png
?? logs/place_test_20260520_120319.csv
?? logs/place_test_20260520_120319.txt
?? logs/place_test_20260520_120319_cleanup_home_side.png
?? logs/place_test_20260520_120319_cleanup_home_top.png
?? logs/place_test_20260520_120319_phase0_home_side.png
?? logs/place_test_20260520_120319_phase0_home_top.png
?? logs/place_test_20260520_120319_phase2_approach_side.png
?? logs/place_test_20260520_120319_phase2_approach_top.png
?? logs/place_test_20260520_120939.csv
?? logs/place_test_20260520_120939.txt
?? logs/place_test_20260520_120939_cleanup_home_side.png
?? logs/place_test_20260520_120939_cleanup_home_top.png
?? logs/place_test_20260520_120939_phase0_home_side.png
?? logs/place_test_20260520_120939_phase0_home_top.png
?? logs/place_test_20260520_120939_phase2_approach_side.png
?? logs/place_test_20260520_120939_phase2_approach_top.png
?? logs/place_test_20260520_121820.csv
?? logs/place_test_20260520_121820.txt
?? logs/place_test_20260520_121820_cleanup_home_side.png
?? logs/place_test_20260520_121820_cleanup_home_top.png
?? logs/place_test_20260520_121820_phase0_home_side.png
?? logs/place_test_20260520_121820_phase0_home_top.png
?? logs/place_test_20260520_121820_phase2_approach_side.png
?? logs/place_test_20260520_121820_phase2_approach_top.png
?? logs/place_test_20260520_121906.csv
?? logs/place_test_20260520_121906.txt
?? logs/place_test_20260520_121906_cleanup_home_side.png
?? logs/place_test_20260520_121906_cleanup_home_top.png
?? logs/place_test_20260520_121906_phase0_home_side.png
?? logs/place_test_20260520_121906_phase0_home_top.png
?? logs/place_test_20260520_121906_phase2_approach_side.png
?? logs/place_test_20260520_121906_phase2_approach_top.png
?? logs/place_test_20260520_143701.csv
?? logs/place_test_20260520_143701.txt
?? logs/place_test_20260520_143701_phase0_home_side.png
?? logs/place_test_20260520_143701_phase0_home_top.png
?? logs/place_test_20260520_143747.csv
?? logs/place_test_20260520_143747.txt
?? logs/place_trials.csv
?? logs/req186/
?? logs/shots_187/
?? logs/template_learning.log
?? logs/variation_comparison.md
?? logs/verdict_seed_ai_20261114.txt
?? logs/verdict_viewer_194_panel.png
?? logs/verdict_viewer_server.log
?? logs/xyz_track_test_20260518_193810.csv
?? logs/xyz_track_test_20260518_195725.csv
?? logs/xyz_track_test_20260518_200435.csv
?? logs/xyz_track_test_20260518_201641.csv
?? logs/xyz_track_test_20260518_202130.csv
?? logs/xyz_track_test_20260518_202831.csv
?? logs/xyz_track_test_20260518_203221.csv
?? logs/xyz_track_test_20260518_203408.csv
?? logs/xyz_track_test_20260518_204420.csv
?? logs/xyz_track_test_20260518_204557.csv
?? logs/xyz_track_test_20260518_205032.csv
?? logs/xyz_track_test_20260518_205427.csv
?? logs/xyz_track_test_20260518_205616.csv
?? logs/xyz_track_test_20260518_210647.csv
?? logs/xyz_track_test_20260518_211232.csv
?? logs/xyz_track_test_20260518_211353.csv
?? logs/xyz_track_test_20260518_211544.csv
?? logs/xyz_track_test_20260518_211703.csv
?? logs/xyz_track_test_20260518_211939.csv
?? logs/xyz_track_test_20260518_212236.csv
?? logs/xyz_track_test_20260518_212335.csv
?? logs/xyz_track_test_20260518_212447.csv
?? logs/xyz_track_test_20260518_212744.csv
?? logs/xyz_track_test_20260518_213019.csv
?? logs/xyz_track_test_20260518_213513.csv
?? logs/xyz_track_test_20260518_213656.csv
?? logs/xyz_track_test_20260518_213811.csv
?? logs/xyz_track_test_20260518_214452.csv
?? logs/xyz_track_test_20260518_214651.csv
?? logs/xyz_track_test_20260518_214851.csv
?? logs/xyz_track_test_20260518_215212.csv
?? logs/xyz_track_test_20260518_215532.csv
?? logs/xyz_track_test_20260518_221313.csv
?? logs/y_calibration_20260516_200819.csv
?? logs/y_calibration_20260516_201220.csv
?? logs/y_calibration_20260516_201452.csv
?? logs/y_calibration_20260516_201634.csv
?? logs/y_calibration_20260516_202140.csv
?? logs/y_calibration_low_20260516_203456.csv
?? logs/y_calibration_mid_20260516_204525.csv
?? mat_corner_detection_result.png
?? mat_rectified.png
?? mat_rectify.py
?? match_features_log07.py
?? measure_baseline_log08.py
?? measure_contours_log06.py
?? measure_rectified_log08.py
?? mecharm_daemon.py.QUARANTINE_send_coords_DAY287
?? mecharm_daemon.py.bak_pre_coords_20260711_213944
?? mecharm_daemon.py.pi_candidate_20261019_LOG352
?? mecharm_daemon.py.pi_candidate_v2_20261019_LOG352
?? mecharm_daemon.py.pi_deployed_20261019_LOG352
?? motion_completion_pi.py
?? move_to_home.py
?? move_to_pick.py
?? noise_test_20260502_125230.csv
?? noise_test_20260502_130537.csv
?? noise_test_20260502_130707.csv
?? noise_test_20260502_131309.csv
?? noise_test_20260502_131747.csv
?? noise_test_20260502_132515.csv
?? noise_test_20260502_132743.csv
?? observe/emit.py.bak_DAY239_pre_nonblocking
?? observe/emit.py.bak_DAY241_pre_block_place
?? observe/emit.py.bak_DAY241_pre_blockbox
?? observe/emit.py.bak_DAY241_pre_in_box
?? observe/emit.py.bak_DAY242_pre_caps
?? observe/emit.py.bak_DAY242_pre_tip_panel
?? observe/observe_server.py
?? observe/static/index.html.bak_DAY239_pre_glance_drilldown
?? observe/static/index.html.bak_DAY241_pre_arm_full_joints
?? observe/static/index.html.bak_DAY241_pre_dashboard_expand
?? observe/static/index.html.bak_DAY241_pre_gripper_coords
?? observe/static/index.html.bak_DAY241_pre_gripper_debounce
?? observe/static/index.html.bak_DAY241_pre_history
?? observe/static/index.html.bak_DAY241_pre_idle
?? observe/static/index.html.bak_DAY241_pre_inbox_latch
?? observe/static/index.html.bak_DAY241_pre_joints_glance
?? observe/static/index.html.bak_DAY241_pre_phase_latch
?? observe/static/index.html.bak_DAY241_pre_remove_arm
?? observe/static/index.html.bak_DAY241_pre_urdf_fk
?? observe/static/index.html.bak_DAY242_pre_caps
?? observe/static/index.html.bak_DAY242_pre_tip_panel
?? observe/static/index.html.bak_DAY247_pre_scrollfix
?? observe/static/index.html.bak_DAY247_pre_sidebarstretch
?? observe/static/index_pre_sidebar_20260620.html
?? observe/telemetry_probe.py
?? pi05/POWER_AB.md
?? pi05/build_deep_even10_v2.sh
?? pi05/build_demo_episodes.py.bak_pre_LOG352_20261019
?? pi05/diag_fill_flags.py
?? pi05/pos5_lift_compare.py
?? pi05/power_ab_compare.py
?? pi05/test_build_deep_even10_v2.py
?? pi05/test_pos5_lift_compare.py
?? pi05/test_power_ab.py
?? pi05/test_state_source.py
?? "pi05/verdict_viewer/\345\210\244\345\256\232\343\201\256\347\224\273\351\235\242\343\202\222\351\226\213\343\201\217.command"
?? pick_and_place_fixed.py
?? pick_cover_corners_log07.py
?? pick_sheet_corners_log08.py
?? pipeline_timeline.html
?? place_test.py
?? place_test.py.bak
?? place_test.py.bak2
?? place_test.py.bak3
?? positions_clean.json
?? positions_now.json
?? probe_idle_send.py
?? probe_wb.py
?? r2r2r_dryrun.py
?? r2r2r_loop.py.bak_DAY159_pre_2point
?? r2r2r_loop.py.bak_DAY159_pre_dynamic
?? r2r2r_loop.py.bak_DAY159_pre_phaseC
?? r2r2r_loop.py.bak_DAY166_pre_homography
?? r2r2r_loop.py.bak_DAY166_pre_template_restore
?? r2r2r_loop.py.bak_DAY166_pre_whitehsv
?? r2r2r_loop.py.bak_DAY168_pre_camera_autodetect
?? r2r2r_loop_v2.py
?? ransac_only_log07.py
?? recalibrate_homography.py.bak_DAY168_pre_index_fix
?? recalibrate_homography.py.bak_DAY168_pre_unified
?? recalibrate_homography.py.sed_bak
?? rectify_sheet_log08.py
?? rectify_sheets_log06.py
?? results/
?? run_pick_place.sh
?? sample_images/
?? show_camera.py
?? test_blue_detect.py
?? test_day170_only_day171.py
?? test_day170_speed50_day171.py
?? test_ee_offset.py
?? test_gripper_only.py
?? test_j2_range_day173.py
?? test_joint_range_day173.py
?? test_joint_range_day173_v2.py
?? test_lookup_9points.py
?? test_pick_2points_day171.py
?? test_pick_2points_day171_sync.py
?? test_pick_day175.py
?? test_pick_new_csv_day171.py
?? test_place_day175.py
?? test_place_detection_offline.py
?? test_sequence_day175.py
?? test_side_camera_tip_detection.py
?? test_side_white_mask.py
?? test_white_box_score.py
?? tools/gamepad_check.py
?? tools/pi/servo_check_pi.py
?? tools/servo_check.sh
?? tools/test_servo_check.sh
?? tools/test_servo_check_pi.py
?? verify_dynamic_pick.py
?? verify_dynamic_pick_auto.py
?? verify_dynamic_pick_auto_correct.py
?? verify_fk_calibration.py
?? verify_homography.py.bak_DAY168_pre_unified
?? verify_lowerleft_scan.py
?? verify_y_direction.py
?? vision/
?? visual_servo_20260502_084046.csv
?? visual_servo_20260502_181427.csv
?? visual_servo_20260502_183654.csv
?? visual_servo_20260502_205548.csv
?? visual_servo_20260502_211405.csv
?? visual_servo_20260503_071901.csv
?? visual_servo_20260503_073918.csv
?? visual_servo_20260503_083158.csv
?? visual_servo_20260506_082640.csv
?? visual_servo_20260506_082916.csv
?? visual_servo_20260506_194904.csv
?? visual_servo_20260514_223230.csv
?? visual_servo_20260514_224150.csv
?? visual_servo_20260514_224442.csv
?? visual_servo_20260514_225526.csv
?? visual_servo_20260514_233646.csv
?? visual_servo_20260515_212307.csv
?? visual_servo_pick.py.day180_backup
?? visual_servo_pick.py.day184_pre_debug_log
?? visual_servo_pick.py.day184_pre_descend_servo
?? visual_servo_pick.py.day184_pre_gripper_fix
?? visual_servo_pick.py.day184_pre_j1_gripper
?? visual_servo_pick.py.day184_pre_marker_fix
?? visual_servo_pick.py.day185_pre_2d_converge
?? visual_servo_pick.py.day185_pre_approach_height
?? visual_servo_pick.py.day185_pre_approach_redesign
?? visual_servo_pick.py.day185_pre_blue_fullscreen
?? visual_servo_pick.py.day185_pre_descend_fix
?? visual_servo_pick.py.day185_pre_dynamic
?? visual_servo_pick.py.day185_pre_fix_definitive
?? visual_servo_pick.py.day185_pre_j2_tune
?? visual_servo_pick.py.day185_pre_persist
?? visual_servo_pick.py.day185_pre_posture_unify
?? visual_servo_pick.py.day185_pre_revert
?? visual_servo_pick.py.day185_pre_sign_fix
?? visual_servo_pick.py.day185_pre_tight_threshold
?? visual_servo_pick.py.day185_pre_topmost
?? visual_servo_pick.py.day185_pre_visualize
?? visual_servo_pick.py.day185_pre_window_thread
?? visual_servo_pick.py.day186_pre_3joint_reach
?? visual_servo_pick.py.day186_pre_descend_j2_minus5
?? visual_servo_pick.py.day186_pre_descend_obs
?? visual_servo_pick.py.day186_pre_imwrite_off
?? visual_servo_pick.py.day186_pre_limit_disable
?? visual_servo_pick.py.day186_pre_loop_speedup
?? visual_servo_pick.py.day186_pre_nonblock
?? visual_servo_pick.py.day186_pre_normal_limit_disable
?? visual_servo_pick.py.day186_pre_post_descend_refine
?? visual_servo_pick.py.day186_pre_refine_mode
?? visual_servo_pick.py.day186_pre_send_interval
?? visual_servo_pick.py.day186_pre_sleep_removal
?? visual_servo_pick.py.day186_pre_ssh_merge
?? visual_servo_pick.py.day186_pre_ssh_persist
?? visual_servo_pick.py.day186_pre_z_tracking
?? visual_servo_pick.py.day188_pre_z_sign_fix
?? visual_servo_pick.py.day189_pre_daemon
?? visual_servo_pick_architecture_2026-05-15.json
?? xyz_track_design.md
?? xyz_track_test.py
?? y_calibration.py

codex
- **P2** — [diag_fill_flags.py:98](https://pixelstomotors.com/Users/shimazueiichi/r2r2r-scripts/pi05/diag_fill_flags.py:98)：対象エピソードが0件だと `rows[0]` で異常終了します。先に出力ディレクトリが作られるため、再実行も「出力先がもうある」で拒否されます。空の場合も固定の列名でCSVを出力するか、ディレクトリ作成前に終了してください。

本体の変更には、指定条件に反する不具合は見つかりませんでした。印は補間と同じ区間条件を使い、選別後の `idx` に対応しています。

純粋計算の4テストは成功。実データ再生成によるバイト一致テストは未実施です。既存データセットは変更していません。
tokens used
22,414
- **P2** — [diag_fill_flags.py:98](https://pixelstomotors.com/Users/shimazueiichi/r2r2r-scripts/pi05/diag_fill_flags.py:98)：対象エピソードが0件だと `rows[0]` で異常終了します。先に出力ディレクトリが作られるため、再実行も「出力先がもうある」で拒否されます。空の場合も固定の列名でCSVを出力するか、ディレクトリ作成前に終了してください。

本体の変更には、指定条件に反する不具合は見つかりませんでした。印は補間と同じ区間条件を使い、選別後の `idx` に対応しています。

純粋計算の4テストは成功。実データ再生成によるバイト一致テストは未実施です。既存データセットは変更していません。
```



## 依頼197：手教示の角度が0.32秒おきにしか読めない原因

手で教えたお手本の元の記録では、角度がふだん0.32秒おきにしか読めていませんでした。補正のお手本と同じ「0.25秒より長い間は抜け」の決まりで数えると、ほぼ全部のコマが抜けになります。印の線を決めるより、記録の作りを直すほうがデータの質に効くと考え、先に原因を調べました。調べるだけで、実機もコードも触っていません。Pi は電源が切れていて届かなかったので、手元の写しと git の履歴で調べています。

**原因は、手教示の記録に角度を記録するためだけの読み取りがないことでした。** 到達を確かめる「角度を1回読む → 0.3秒待つ」のついでに読んでいるので、0.32秒おきになります。故障ではなく、作りどおりの間隔です。

| 1秒を超える抜けの原因 | 抜けた時間に占める割合 | アームが動いた量に占める割合 |
|---|---|---|
| 爪の開け閉めを待つ間（開く約6.03秒・閉じる約2.03秒） | 62.4% | 1.0% |
| 動きを送ったあとの1秒の待ち（daemon が1秒寝てから返事をする） | 37.6% | 58.5% |

（手教示の `teach_pos1to4_deep_v1` の31本。`teach_v1` もほぼ同じ）

爪を待つ間はアームが止まっているので、学習への害は小さい。問題は、送ったあとの1秒の待ちです。ブロックへ降りる・持ち上げる・運ぶといった短い区間が、ほぼこの1秒の中で終わっていて、その間の角度は前後を結ぶ直線になっています。速さ20の加速と減速の形が、お手本から消えていました。

補正のお手本で11月6日の記録だけ補った値が2〜5%に減っていたのは、11月3日に Pi の daemon を pymycobot 2.9.6 で起動するようにして、送る命令の往復が中央値1.55秒から0.033秒に縮んだためでした。手教示の抜けは daemon の遅さではなく記録の作りから来ているので、この直しは効いていません（11月9日に撮った `teach_pos1to4_deep_v1` も間隔は同じ）。

直し方の案は3つ出ました。

| 案 | 中身 | 見込み | 関節の動きへの影響 |
|---|---|---|---|
| 案1 | 電流を記録している仕組みが0.1〜0.16秒おきに読んでいる角度を、記録にも書く | 読みの間隔は0.1〜0.16秒。送ったあとの1秒の抜けは残る | 変わらない（低い） |
| 案2 | 送ったあとの1秒の待ちを daemon から Mac に移し、その間も読む | 案1と合わせ、動いている間の抜けがほぼなくなる | 中。「送ったあとの待ち1.0秒は短くしない」の書き方を変えることになる |
| 案3 | 送ったあとの待ちを0にする | 抜けはなくなる | 中〜高。区間のつなぎが変わる。勧めない |

案1から作り、実機で1本、次に5本で確かめ、そのあとで案2を決めることにしました。scripted の記録で、人の判定を待っていた212秒の間に j4 が -87° から -60° に変わっていた件は、案1のあとに調べます。


### 依頼197 の依頼文

```markdown
---
作業フォルダ: /Users/shimazueiichi/r2r2r-scripts
上限時間: 90
---
# 依頼197：手教示の記録で、実測角が約 0.32 秒おきにしか読めていない原因を調べる

調べるだけ。実機は動かさない。コードも直さない（直し方の案を書くだけ）。Pi には ssh でファイルとログを読むだけ（daemon の再起動・設定の変更・送信はしない）。
エイイチの決め（2026-11-15）：手教示・scripted のデータに「埋めた値」の印を付ける線を決めるより、先に記録のほうを直す。依頼196 の報告で、手教示の元の記録は実測角がふだん約 0.32 秒おきにしか読めておらず、1 秒を超える抜けが全体の時間の 62%（scripted は 93%・最大 212 秒）を占めていると分かったため。

## 調べること
1. 手教示の記録（record_teach_demo.py と、そこから使う記録の部品・daemon の呼び出し）で、実測角を読む流れを図にする：どこで・何の命令で・どの間隔で読んでいるか、読みが何で待たされているか（daemon の 1 回の応答時間・sleep・ほかの命令との取り合い・ロック・カメラの読み込み など）
2. 実際の間隔を測る：teach_v1 と teach_pos1to4_deep_v1 の元の記録（runs/run_pick_place/{run_stem}/recording/states.csv など）から、読めた間隔の分布（中央値・90% 点・最大）と、長い抜けがどの段階（つかむ・運ぶ・放す・待ち など）で起きているかを数える
3. scripted_v1 の 212 秒の抜けなど、長い抜けの原因を 2〜3 本たどる
4. 補正の記録（runs/pi05_policy）では、2026-11-06 の 4 本だけ埋めた割合が 2〜5%（10/31・11/1 は 57〜96%）。11/1〜11/6 の間に何を変えて抜けが減ったのかを git log と記録から突き止め、手教示の記録にも同じ直し方が使えるかを書く
5. 直し方の案を 2〜3 個（ねらい・変える場所・見込める読み取り間隔・実機で確かめる手順・アームの動きに影響が出うる所）。案ごとに、物理的リスク（関節制御・姿勢系に触れるか）を書く

## 書くもの
- docs/investigation_20261115_teach_state_rate.md（調べた結果と案。図はテキストでよい）
- 測った数字の CSV は diag/teach_state_rate_20261115/ に（KIOXIA のマウントを確かめ、なければ止める）
- commit は docs の md だけを指定して（git add . と git clean は使わない）

## 報告に書くこと
- 0.32 秒おきの原因（1〜2 行で）
- 11/6 に補正の記録で抜けが減った理由
- 直し方の案の一覧と、私（エイイチ）が決めること
- 最後の 1 行に「判定：合格／止めた（決めてほしいことあり）／失敗」
```

### 依頼197 で Claude Code が返した報告

```text
# 結果：20261115_197_手教示の実測角が0.32秒おきの原因を調べる

- 状態：完了
- 始めた時刻：2026-11-15 06:17
- 終わった時刻：2026-11-15 06:25（7分）
- 作業フォルダ：/Users/shimazueiichi/r2r2r-scripts
- この続きを Claude Code で話すとき：作業フォルダで `claude --resume 9152168c-ddbb-4249-8e8f-392b44948ab6`

## Claude Code の報告

**やったこと**
- 手教示の記録が実測角を読む流れを、record_teach_demo.py の `_replay`・visual_servo_pick.py・daemon の写し（tools/pi/mecharm_daemon.py）でたどり、図にしました。
- 元の記録 states.csv から、読めた間隔を数えました。対象は teach_v1_trim2 の 19 本、teach_pos1to4_deep_v1 の 31 本、scripted_v1 の 20 本です。補正の記録は 12 本を日付ごとに数えました。
- Pi は ssh も ping も返りませんでした。電源が切れていると見られます。そのため Pi のファイルとログは読めておらず、手元の写しと git log で代わりに調べました。

**結果**
- 0.32 秒おきの原因：手教示の記録には、実測角を記録するためだけの読み取りがありません。到達の確かめの「get_angles を 1 回（約 0.02 秒）→ 0.3 秒寝る」に相乗りしているので 0.32 秒おきになります。本線の 3Hz に合わせた作りどおりで、故障ではありません。
- 1 秒を超える抜けは 2 種類だけで、どの本にもちょうど 11 個あります。1 秒を超える抜けは、手教示 2 組とも時間全体の 62% です。
  - 爪の待ち（開く約 6.03 秒・閉じる約 2.03 秒）：抜けた時間の 62% ですが、アームは止まっています。動いた量では 1% 未満です。
  - 送信の待ち（約 1.05 秒）：`wait=1.0` で daemon が 1 秒寝てから返事をするため、その間は読めません。抜けた時間では 38% ですが、アームが動いた量の 56〜59% がこの中に入っています。PICK への降下、持ち上げ、運ぶ動きなどです。
- 読めた間隔は次のとおりです（単位は秒）。

| データ | 中央値 | 90% 点 | 最大 |
|---|---|---|---|
| teach_v1_trim2 | 0.324 | 1.055 | 6.05 |
| teach_pos1to4_deep_v1 | 0.324 | 1.056 | 6.07 |
| scripted_v1 | 0.322 | 3.46 | 212.2 |

- scripted の長い抜けを 3 本たどりました。
  - 212 秒と 130 秒：人の判定の入力待ちです。212 秒の間に j4 が -87° から -60° に変わっていました。理由は記録からは分かりません。
  - 48 秒：つかみ直しで、もう一度位置を出し直している間です。
- 11/6 に補正の記録で抜けが減った理由：補正の記録は前から 10Hz の読み取りスレッドで読んでいました。抜けは、送る命令の往復が長い間、その読み取りが待たされて起きていました。
  - 11/3 に daemon を pymycobot 2.9.6 で起動するようにしました。send_angles の往復の中央値が 1.55 秒から 0.033 秒になり、これが主な理由です。
  - 11/5 に daemon の読み直しの間を 0.02 秒にしました。
  - その結果、1 秒を超える抜けは時間の 30〜60% から 6〜12% に減りました。
- 手教示には同じ直し方がそのままは効きません。11/9 撮影の deep_v1 も、10/19 撮影の teach_v1 と同じ間隔でした。手教示の抜けは daemon の遅さではなく、記録の作りから来ているためです。
- 直し方の案（どれもまだ作っていません）
  - 案 1：電流の記録スレッドが寝ている間に読んでいる角度を、states.csv にも書きます。読みの間隔は 0.1〜0.16 秒になる見込みです。送信の 1 秒の抜けは残ります。アームの動きは変わらず、物理的リスクは低いです。
  - 案 2：送信の 1 秒の待ちを daemon から Mac 側に移し、その間も読みます。待つ長さは同じです。案 1 と組み合わせ、動いている間の抜けがほぼなくなる見込みです。送った直後の 1 秒にシリアルを読むようになるので、物理的リスクは中です。
  - 案 3：送信の待ちを 0 にします。待ちを縮めることになり、区間のつなぎの時間が変わるので、物理的リスクは中〜高です。勧めません。

**変えたファイル**
- docs/investigation_20261115_teach_state_rate.md（このファイルだけを指定して commit 8ca1725）
- KIOXIA の diag/teach_state_rate_20261115/ に、数えた CSV 6 つ・スクリプト 3 本・README を置きました。commit していません。
- logs/20261115_0625.md に作業の記録を書きました。commit していません。

**決めてほしいこと**
1. どの案で直すか。勧めは案 1、その次に案 2 です。
2. 案 2 をするなら、「SENDWAIT 1.0 は短縮しない」の決まりを「daemon ではなく Mac 側で 1.0 秒待つ」に置き換えてよいか。
3. 案 1・案 2 で読む命令を、角度だけの get_angles（約 0.02 秒）にするか、電流も読む read_servo（約 0.08 秒）のままにするか。
4. 実機での確かめ（1 本、次に 5 本）をいつするか。その前に、Pi の daemon が 11/5 版かを確かめる必要があります。今日は Pi に届きませんでした。
5. 直した記録で撮り直すか。それとも今のお手本はそのまま使い、依頼 196 の印（動いた抜け・動かなかった抜け）で扱うか。
6. scripted の判定待ちの間に j4 が -87° から -60° に変わった件を調べるか。今回の範囲外です。

判定：止めた（決めてほしいことあり）
```

### 依頼197 のコードの差分（コミット 8ca1725）

~~~~diff
commit 8ca17252640adea5f263c5d8424669dbe4caa42b
Author: Eiichi Shimazu <studio@adaptdesign.jp>
Date:   Sun Nov 15 06:24:53 2026 +0900

    手教示の記録で実測角が約 0.32 秒おきにしか読めない原因を調べた結果と直し方の案 (依頼 197)
    
    docs/investigation_20261115_teach_state_rate.md だけ. コード・実機・Pi は触っていない (Pi は ssh・ping とも返らず読めていない).
    0.32 秒 = 到達の確かめの get_angles 1 回 + ARRIVAL_POLL_SLEEP 0.3. 1 秒超の抜けは爪の待ち (6.03 / 2.03 秒・止まっている) と
    送信の待ち (wait=1.0 で ≈1.05 秒・動いた量の 56〜59%) の 2 種類だけ (どの本も 11 個). 補正の記録は 11/3 の pymycobot 2.9.6 起動
    (send_angles 往復 1.55 → 0.033 秒) と 11/5 の daemon 読み直し 0.02 秒で抜けが減った. 案 1 (電流の記録スレッドの角度も書く) /
    案 2 (送信の待ちを Mac 側へ移して読む) / 案 3 (待ちを 0. 勧めない). 数えた CSV は KIOXIA diag/teach_state_rate_20261115/.
    
    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---
 docs/investigation_20261115_teach_state_rate.md | 203 ++++++++++++++++++++++++
 1 file changed, 203 insertions(+)

diff --git a/docs/investigation_20261115_teach_state_rate.md b/docs/investigation_20261115_teach_state_rate.md
new file mode 100644
index 0000000..09d11b5
--- /dev/null
+++ b/docs/investigation_20261115_teach_state_rate.md
@@ -0,0 +1,203 @@
+# 調べた結果：手教示の記録で実測角が約 0.32 秒おきにしか読めない原因（依頼 197・2026-11-15）
+
+調べるだけ。実機は動かしていない。コードは直していない。
+Pi は ssh・ping とも返らなかった（電源が切れていると見られる）ので、Pi のファイルとログは読めていない。
+daemon の中身は手元の写し（tools/pi/mecharm_daemon.py・git の履歴）と、記録に残った往復時間から読んだ。
+
+測った数字の CSV と、測るのに使ったスクリプト: `/Volumes/KIOXIA/r2r2r-data/diag/teach_state_rate_20261115/`（README あり）
+
+---
+
+## 0. まとめ
+
+- **0.32 秒おきの原因**: 手教示の記録には実測角を読むための専用の読み取りがない。読むのは
+  到達の確かめ（`_hold_until_arrival`）と、静止の確かめ（`_wait_until_still`）の中だけで、どちらも
+  「get_angles 1 回（約 0.02 秒）→ `time.sleep(0.3)`（`ARRIVAL_POLL_SLEEP = jss.POLL_SLEEP`）」をくり返すので 0.32 秒おきになる。
+  これは壊れているのではなく、本線（3Hz）に合わせた作りどおりの間隔。
+- **1 秒を超える抜け（時間の 62%）は 2 種類だけ**。どの本にもちょうど 11 個ある（爪 3 回 + 送信 8 回）。
+  1. 爪の待ち: 開く ≈6.03 秒（daemon の前の 2 秒 + Mac 側の 2 秒 + dwell 2 秒）、閉じる ≈2.03 秒（dwell 2 秒）。
+     「爪を動かした直後にシリアルを触らない」決まりで読まない。**抜けた時間の 62% だがアームは止まっている**（動いた量の 1% 未満）。
+  2. 送信の待ち ≈1.05 秒: `daemon_send_angles(..., wait=SEND_WAIT_SEC=1.0)` で daemon が 1 秒寝てから返事をするので、
+     Mac はその間何も読めない。**抜けた時間の 38% だが、アームが動いた量の 56〜59% がこの中に入っている**。
+     PICK への降下（平均 15〜19°）・持ち上げ（14〜18°）など短い区間は、ほぼ全部がこの 1 秒の中で終わる。
+- **11/6 に補正の記録で抜けが減った理由**: 補正の記録は前から 10Hz の読み取りスレッドで読んでいて、抜けは
+  「本体の daemon とのやりとりが長いあいだ鍵をつかんでいる」ことで起きていた。11/1 は send_angles 1 回の往復が
+  中央値 1.55 秒（pymycobot 4.0.4 が送るたびに返事を 0.5 秒 × 3 回待っていた）。11/3 に daemon を pymycobot 2.9.6 で
+  起動するようにし（15ca6a4）、11/5 に daemon の読み直しを 0.02 秒にして送ったあとの読みを 1 回だけにした（c7992ca）。
+  11/6 は往復が中央値 0.033 秒になり、1 秒を超える抜けが時間の 30〜60% → 6〜12% に減った。
+- **手教示には同じ直し方がそのままは効かない**。teach_pos1to4_deep_v1（11/9 撮影）は daemon の直しのあとだが、
+  間隔は teach_v1（10/19）と同じ（中央値 0.324・1 秒超 62%）。手教示の抜けは daemon の遅さではなく、記録の作り
+  （読み取りが 0.3 秒の到達確かめに相乗り・送信の 1 秒待ちの間は読まない）から来ているため。
+  効くのは補正の記録の「もう一方の部品」= 10Hz の読み取りスレッドと、送信の待ちを daemon に持たせない形。
+
+---
+
+## 1. 手教示の記録で実測角を読む流れ（record_teach_demo.py の `_replay`）
+
+```
+Mac（record_teach_demo.py）                                     Pi（mecharm_daemon.py・1 本のソケット）
+------------------------------------------------------------------------------------------------------
+[move 区間 × 8]  HOME / APPROACH_PICK / PICK / LIFT / APPROACH_PLACE / PLACE / RETREAT / HOME
+  recorder.stage(名前)  ── UDP 通知（recorder.py が states.csv に stage 行）
+  sampler.read(once=False) ─────────────────────────────→  get_angles（空なら 0.02 秒おきに 12 回まで読み直す）
+     └ 読めた角度を recorder.actual() で通知 → states.csv の actual 行        ≈0.02 秒
+  _send_angles_guarded → daemon_send_angles(wait=1.0) ───→  send_angles: 書く → sleep(1.0) → 1 回だけ読む（ログ用）
+     （この ≈1.03 秒は何も読まない）  ◀◀ 抜け ≈1.05 秒・アームは目標へ動いている
+  _hold_until_arrival:
+     loop: sampler.read(once=False) ───────────────────→  get_angles                         ≈0.02 秒
+           許容差に入ったら抜ける
+           _sleep_open(0.3)  ← ARRIVAL_POLL_SLEEP（電流の記録はこの間だけ read_servo を読む・角度は states.csv に書かない）
+                                ◀◀ ふだんの間隔 0.3 + 0.02 = 0.32 秒
+[gripper × 3]  open（HOME で）/ close（PICK で）/ open（PLACE で）
+  _wait_until_still: 上と同じ「読む → 0.3 秒寝る」を 3 回続けて静止するまで
+  recorder.pause_currents()
+  close: daemon_set_gripper_value ──────────────────────→  すぐ返る（≈0.01 秒）
+         time.sleep(2.0)（読まない）                                        ◀◀ 抜け ≈2.03 秒（アームは止まっている）
+  open:  daemon_set_gripper(0, wait=0) ─────────────────→  sleep(2) → set_gripper_state（≈2.01 秒）
+         time.sleep(2.0) → time.sleep(2.0)（読まない）                       ◀◀ 抜け ≈6.03 秒（アームは止まっている）
+  recorder.resume_currents()
+[HOME の settle]  sampler.sleep_with_reads: 1/3 秒ごとに get_angles_once 相当を読む（≈0.39 秒おき）
+```
+
+- 読みを待たせているもの: **自分の sleep（0.3 秒）**と、**daemon の送信の待ち（1.0 秒）**と、**爪の固定の待ち（2〜6 秒）**。
+  daemon の 1 回の応答（get_angles ≈0.02 秒）・ロック・カメラは間隔をほとんど決めていない。
+  - カメラは別のプロセス（recorder.py）で、角度の読みとは関係しない。
+  - ロック: 電流の記録スレッド（依頼 121）は本体が寝ている間だけ読む作り（`reads_only_while_main_sleeps: true`）で、
+    本体の読みは電流の記録を待たない。ただし電流スレッドが read_servo で読んだ角度は **states.csv に書いていない**
+    （currents.csv の時刻を決めるのに使うだけ）。11/9 の 1 本では read_servo が 93 回・中央値 0.16 秒おきに読めていた。
+- 設計の由来（コードのコメントより）: 10/19 に「0.1 秒ごとの補間送信」をやめて「区間ごとに 1 回送って到達を待つ」
+  （本線 run_pick_place.py と同じ）にしたとき、記録用の 3 tick に 1 回の読み（≈3.3Hz）がなくなり、
+  到達確かめのポーリング（0.3 秒）だけが残った。`ACTUAL_READ_TARGET_HZ = 3.0` は「これまでの 19 本と同程度の 3Hz 以上」。
+
+## 2. 実際の間隔（元の記録の states.csv の actual 行の間）
+
+`by_cause.csv` / `by_phase.csv` / `runs.csv`
+
+| データ | 本 | 間の数 | 中央値 | 90% 点 | 最大 | 1 秒超の数 | 1 秒超が時間に占める割合 |
+|---|---|---|---|---|---|---|---|
+| teach_v1_trim2（10/19） | 19 | 1,108 | 0.324 | 1.055 | 6.05 | 209（1 本 11） | 62.3%（428.5 / 687.9 秒） |
+| teach_pos1to4_deep_v1（11/9） | 31 | 1,808 | 0.324 | 1.056 | 6.07 | 341（1 本 11） | 62.4%（700.8 / 1123.2 秒） |
+| scripted_v1（10/15・16） | 20 | 1,706 | 0.322 | 3.46 | 212.2 | 387 | 92.7%（3322.8 / 3586.3 秒） |
+
+原因ごと（手教示の 2 つはほぼ同じなので deep_v1 の数。teach_v1 は括弧）:
+
+| 原因 | 数 | 中央値 | 時間 | 1 秒超の時間に占める割合 | アームが動いた量に占める割合 |
+|---|---|---|---|---|---|
+| 0.3 秒のポーリングの間 | 1,343 | 0.324 | 420 秒 | 0%（最大 0.41 秒） | 40.5%（42.6%） |
+| 送信の待ち（wait=1.0） | 248 | 1.052 | 263 秒 | 37.6%（37.4%） | **58.5%（56.4%）** |
+| 爪の待ち | 93 | 6.03 / 2.03 | 437 秒 | **62.4%（62.6%）** | 1.0%（0.9%） |
+| 段の切り替え | 124 | 0.020 | 2 秒 | 0% | 0.1% |
+
+「動いた量」= 間ごとの 6 軸の |Δ| の最大を足したもの（`teach_motion_by_cause.csv`）。
+
+段階ごとに見た送信の待ちの中の動き（deep_v1・1 回あたりの平均）: 近づく 27.8° / つかむ（PICK へ降りる）19.2° /
+持ち上げ 18.4° / 運ぶ 29.1° / 放す（PLACE へ降りる）21.8° / 離れる 21.9°。どれも 31 本すべてで 2° 以上動いている。
+1 秒の間を前後の実測でまっすぐ結ぶと、速度 20 の加速・減速の形が消える（特に PICK・PLACE の降下と持ち上げ）。
+
+## 3. 長い抜けの原因をたどった例（scripted_v1）
+
+scripted は run_pick_place.py（本線）の記録で、手教示とは別の作り。長い抜けの 3 本:
+
+1. **212.2 秒**（run_0001_20261016_190925・stage9b_judge_place → stage10）: 放したあとの判定。
+   swept_retreat（stage9b）を送って着いたあと、VLM の place の判定と **人の判定（`_ask_human_verdict` の input 待ち）**の間は
+   何も読まない。間の 2 行の実測で j4 が -87.18 → -60.02 に変わっている（待っている間に j4 が 27° 動いた。理由は記録からは分からない）。
+2. **129.9 秒**（run_0001_20261015_183310・stage6 → stage7）: 持ち上げたあとの pick の判定。同じく **人の判定待ち**（L4156）。
+3. **48.5 秒**（run_0001_20261015_182552・stage6_a2）: つかみ直し。持ち上げのあと regrasp_open（爪）→ retreat →
+   stage2_redetect（もう一度上カメラで位置を出す）までの間に読みがない。
+
+scripted の 1 秒超の時間の内訳: 段の切り替え（人の判定待ち・検出など）37.5% / 爪 35.1% / ポーリングの間 16.9% / 送信 10.6%。
+ポーリングの間の 1 秒超（90% 点 2.58 秒）は、当時の daemon の get_angles が動いている間に空で返り、0.2 秒おきに 12 回まで
+読み直していた分（最長 ≈2.6 秒。11/5 の c7992ca のコミットの説明と同じ）。手教示の 10/19 の記録にはこれが出ていない
+（ポーリングの間の最大 0.64 秒）。
+
+## 4. 補正の記録（runs/pi05_policy）で 11/6 に抜けが減った理由
+
+`corr_runs.csv`（依頼 196 の補正エピソードの元の run 12 本）
+
+| 日 | 本 | 実測角の間 中央値 | 1 秒超が時間に占める割合 | send_angles 1 回の往復（中央値） |
+|---|---|---|---|---|
+| 10/31 | 5 | 0.102 | 29〜60% | 記録なし（往復を残す仕組みは 10/31 19:46 の 1b47477 から） |
+| 11/1 | 3 | 0.102 | 32〜51% | **1.55 秒**（42〜59 回） |
+| 11/6 | 4 | 0.096〜0.100 | **6〜12%** | **0.033 秒**（39〜53 回） |
+
+- 補正の記録（policy_recorder.PolicyRecorder）は前から、本体と別の **10Hz の読み取りスレッド**で角度を読み、
+  `install_daemon_lock` の鍵で本体とソケットを分け合っている。本体が daemon とやりとりしている間、スレッドは鍵を待つ。
+- 11/1 の 1 本（190854）では、1 秒を超える抜け 62 個のうち 59 個が send_angles 1 回ずつに重なっていた（93.8 秒）。
+  残りは爪（set_gripper の daemon の前の 2 秒）。
+- 11/1 → 11/6 の間に変えたこと（git log）:
+  1. **11/3 15ca6a4**: daemon を pymycobot 2.9.6 で起動する（tools/pi/mecharm_daemon_start.sh）。10/31 に systemd で
+     起動するようにしてから 4.0.4 を読んでいて、送るたびに返事を 0.5 秒 × 3 回待ち 1 回 ≈1.6 秒かかっていた。**これが主因**。
+  2. **11/5 c7992ca / 617c3bd**: daemon の読み直しの間 0.2 → 0.02 秒、送ったあとのログ用の読みを 1 回だけに（tools/daemon_fast_read.sh）。
+  3. 11/5 cd2fb46 など: 補正をゲームパッド（send_angle の 1 刻み・stop）でするようにした。11/6 の 4 本はゲームパッドの補正。
+  run_policy_client.py の送信の待ちは 10/30（7aaf5df）から `SEND_WAIT = 0.0` で、10/31・11/1 も同じなので、11/6 の差の理由ではない。
+- 10/31 は往復の記録がないが、間の形（中央値 0.10 秒・最大 3.6 秒・1 秒超が 29〜60%）が 11/1 と同じなので、同じ理由と見ている（推定）。
+
+**手教示にも使えるか**: daemon 側の直し（1・2）は日付の上では 11/9 の deep_v1 より前に入っている。deep_v1 の送信の往復は
+1.03〜1.04 秒（wait 1.0 + 0.03 秒）で、4.0.4 で起動していた頃の 1.6 秒の上乗せは見えない。ただし 10/19 の teach_v1 も
+送信の間は 1.04〜1.09 秒で、手教示では daemon の直しの前後で数字がほとんど変わらない（送った 1 秒後にはアームが止まりかけで、
+読み直しがほとんど起きないため）。手教示に使えるのは補正の記録の作りのほう（10Hz の読み取りスレッド・送信の待ちを
+daemon に持たせない）で、それが次の案 1・2。Pi の daemon が今 11/5 版かは、Pi に届かず確かめられていない。
+
+## 5. 直し方の案
+
+どれもまだ作っていない。数字は見込み。3 案とも爪の待ち（2〜6 秒・読まない）は変えない（アームは止まっているので、
+前後の実測をまっすぐ結んでも正しい。依頼 196 の state_source では 2 =「動かなかった抜け」）。
+
+### 案 1: 電流の記録スレッドが読んだ角度も states.csv に書く（本体の動きは変えない）
+
+- ねらい: 0.3 秒の寝ている間に読む（すでに読んでいる）角度を、記録にも残す。
+- 変える場所: pi05/policy_recorder.py の `CurrentsRecorder`（read_servo で読んだ角度を recorder へ actual として通知する。
+  または record_teach_demo.py の `_Recorder` へ渡す口を足す）。記録の列は変えない。
+  読み取りを get_angles だけにすれば 1 回 ≈0.02 秒で、read_servo（≈0.08 秒）より多く読める。
+- 見込める間隔: ポーリングの間が 0.32 → 0.10〜0.16 秒（11/9 の電流の記録は寝ている間に中央値 0.16 秒おきに読めていた）。
+  **送信の 1 秒の抜けは残る**（送信は寝ている間ではないので読まない）。動いた量の 56〜59% は抜けたまま。
+- 実機で確かめる手順: HOME の近くで 1 本だけ `run`（いつもの手教示 1 本）→ states.csv の actual の間隔と、試行 JSON の
+  segments の到達時間・still_check の回数が、直す前の本と同じ形かを比べる。
+- アームの動きへの影響: 本体の送信・到達の確かめ・静止の確かめの回数と時刻は変わらない（電流スレッドの今の作りのまま）。
+- 物理的リスク: **低**。関節の指令・姿勢の判断には触れない。読むのは寝ている間だけで、爪の命令の前後は今どおり止める。
+
+### 案 2: 送信の 1 秒の待ちを daemon から Mac へ移し、その間も読む（案 1 と組み合わせる）
+
+- ねらい: 一番動いている 1 秒（送信の待ち）を読めるようにする。待つ長さは縮めない。
+- 変える場所: record_teach_demo.py の `_send_angles_guarded` を `daemon_send_angles(pose, speed, wait=0)` にし、
+  返ったあと Mac 側で `_sleep_open(recorder, SEND_WAIT_SEC)`（1.0 秒・この間は案 1 のスレッドが読む）をしてから
+  `_hold_until_arrival` に入る。爪の open で daemon の事後の待ちを Mac 側の `GRIPPER_OPEN_POST_SLEEP_SEC` に移したのと同じ形。
+  到達の確かめが始まる時刻（送ってから ≈1.03 秒後）と、本体の読みの回数は今と同じ。
+- 見込める間隔: 動いている間も 0.10〜0.16 秒おき。1 秒を超える抜けは爪の待ち（止まっている間）だけになり、
+  動いた量のうち抜けに入る分は 56〜59% → ほぼ 0（爪の待ちの 1% 未満）。
+- 実機で確かめる手順: (1) Pi の daemon が 11/5 版（`read_angles_once_for_log` がある・`GET_ANGLES_INTERVAL_SEC = 0.02`）かを読んで確かめる
+  （wait=0 で送ると、送った直後に daemon が 1 回読む。旧版だと動いている間に最長 2.6 秒読み直す）。
+  (2) 1 本だけ流し、送信の往復が 0.03 秒前後・send_angles が無視されていない（到達・再送の記録）・
+  1 秒の間に 3 回以上 actual があることを見る。(3) 5 本ほど流して、到達の時間・静止の確かめの回数・再送の回数が直す前の本と変わらないかを比べる。
+- アームの動きへの影響: 送る命令・速さ・目標・待つ長さは変えないが、**送ったあと 1 秒の間に get_angles（または read_servo）を
+  シリアルに出す**ようになる（今は daemon が寝ているので 1 秒間シリアルは静か）。動いている最中の読みで送信が無視される
+  ことが起きないかは、補正の記録（11/6 は動いている間も 10Hz で読み、送信の無視は記録上見えない）からは問題なさそうだが、手教示の流れでは確かめていない。
+- 物理的リスク: **中**。関節の指令の中身は変えないが、送信の直後の 1 秒のシリアルの使い方が変わる。本線と同じ「SENDWAIT = 1.0（DAY266: 短縮しない）」を
+  「daemon が待つ」から「Mac が待つ」に置き換えることになるので、決まりの読み方をエイイチが決める必要がある。
+
+### 案 3: 送信の待ちを 0 にし、到達の確かめのポーリングを送った直後から始める
+
+- ねらい: 一番小さい変更で送信の 1 秒の抜けを消す（run_policy_client.py が 10/30 から `SEND_WAIT = 0.0` でしているのと同じ）。
+- 変える場所: record_teach_demo.py の `_send_angles_guarded` の `wait=SEND_WAIT_SEC` → `wait=0`（Mac 側でも待たない）。
+- 見込める間隔: 動いている間も 0.32 秒おき（案 1 と組むと 0.10〜0.16 秒）。1 秒の抜けは消える。
+- 実機で確かめる手順: 案 2 と同じ。加えて、到達の確かめが送ってすぐ始まるので、到達の時間・「通過中に到達扱い」になる回数を比べる。
+- アームの動きへの影響: **到達の確かめが 1 秒早く始まる**。区間ごとの所要時間が短くなりうる（次の区間を早く送る）。
+  静止の確かめ（爪の前）は残るので爪の安全は変わらないが、PICK・PLACE への入り方の時間が今の 50 本と変わる。
+- 物理的リスク: **中〜高**。待つ長さを縮める（CLAUDE.md の「time.sleep() を削除・短縮しない」と DAY266 に当たる）。
+  動き方（区間のつなぎの時間）が変わるので、これまでのお手本と同じ動きのデータではなくなる。勧めない。
+
+### 勧める順
+
+案 1 → 案 2。案 1 だけなら動きは何も変わらず、ポーリングの間が 0.32 → 0.1〜0.16 秒になる。
+動いた量の半分以上がある送信の 1 秒を読むには案 2 が要る。
+
+## 6. エイイチが決めること
+
+1. どの案で直すか（勧め: 案 1、その次に案 2。案 3 は勧めない）。
+2. 案 2 をするなら: 「SENDWAIT = 1.0（短縮しない）」を「daemon ではなく Mac 側で 1.0 秒待つ（待つ長さは同じ）」に置き換えてよいか。
+   送った直後の 1 秒にシリアルを読むことになる。
+3. 案 1・2 で読む命令: 角度だけ（get_angles・≈0.02 秒・速い）にするか、電流も読む read_servo（≈0.08 秒）のままにするか。
+4. 実機での確かめ（1 本 → 5 本）をいつするか。その前に Pi の daemon が 11/5 版かを読むこと（今日は Pi に届かなかった）。
+5. 直した記録で撮り直すか、今のお手本（teach_v1・deep_v1）は今のまま使い、依頼 196 の印（動いた抜け / 動かなかった抜け）で扱うか。
+   今の手教示の抜けは「爪の待ち = 動かなかった抜け」と「送信の 1 秒 = 動いた抜け」にきれいに分かれる（どの本も 11 個）。
+6. scripted_v1 の人の判定待ち（最大 212 秒）の間の j4 の変化（-87 → -60）を調べるかどうか（今回の範囲外）。
~~~~


### 依頼197 の調べた結果（docs/investigation_20261115_teach_state_rate.md）

~~~~markdown
# 調べた結果：手教示の記録で実測角が約 0.32 秒おきにしか読めない原因（依頼 197・2026-11-15）

調べるだけ。実機は動かしていない。コードは直していない。
Pi は ssh・ping とも返らなかった（電源が切れていると見られる）ので、Pi のファイルとログは読めていない。
daemon の中身は手元の写し（tools/pi/mecharm_daemon.py・git の履歴）と、記録に残った往復時間から読んだ。

測った数字の CSV と、測るのに使ったスクリプト: `/Volumes/KIOXIA/r2r2r-data/diag/teach_state_rate_20261115/`（README あり）

---

## 0. まとめ

- **0.32 秒おきの原因**: 手教示の記録には実測角を読むための専用の読み取りがない。読むのは
  到達の確かめ（`_hold_until_arrival`）と、静止の確かめ（`_wait_until_still`）の中だけで、どちらも
  「get_angles 1 回（約 0.02 秒）→ `time.sleep(0.3)`（`ARRIVAL_POLL_SLEEP = jss.POLL_SLEEP`）」をくり返すので 0.32 秒おきになる。
  これは壊れているのではなく、本線（3Hz）に合わせた作りどおりの間隔。
- **1 秒を超える抜け（時間の 62%）は 2 種類だけ**。どの本にもちょうど 11 個ある（爪 3 回 + 送信 8 回）。
  1. 爪の待ち: 開く ≈6.03 秒（daemon の前の 2 秒 + Mac 側の 2 秒 + dwell 2 秒）、閉じる ≈2.03 秒（dwell 2 秒）。
     「爪を動かした直後にシリアルを触らない」決まりで読まない。**抜けた時間の 62% だがアームは止まっている**（動いた量の 1% 未満）。
  2. 送信の待ち ≈1.05 秒: `daemon_send_angles(..., wait=SEND_WAIT_SEC=1.0)` で daemon が 1 秒寝てから返事をするので、
     Mac はその間何も読めない。**抜けた時間の 38% だが、アームが動いた量の 56〜59% がこの中に入っている**。
     PICK への降下（平均 15〜19°）・持ち上げ（14〜18°）など短い区間は、ほぼ全部がこの 1 秒の中で終わる。
- **11/6 に補正の記録で抜けが減った理由**: 補正の記録は前から 10Hz の読み取りスレッドで読んでいて、抜けは
  「本体の daemon とのやりとりが長いあいだ鍵をつかんでいる」ことで起きていた。11/1 は send_angles 1 回の往復が
  中央値 1.55 秒（pymycobot 4.0.4 が送るたびに返事を 0.5 秒 × 3 回待っていた）。11/3 に daemon を pymycobot 2.9.6 で
  起動するようにし（15ca6a4）、11/5 に daemon の読み直しを 0.02 秒にして送ったあとの読みを 1 回だけにした（c7992ca）。
  11/6 は往復が中央値 0.033 秒になり、1 秒を超える抜けが時間の 30〜60% → 6〜12% に減った。
- **手教示には同じ直し方がそのままは効かない**。teach_pos1to4_deep_v1（11/9 撮影）は daemon の直しのあとだが、
  間隔は teach_v1（10/19）と同じ（中央値 0.324・1 秒超 62%）。手教示の抜けは daemon の遅さではなく、記録の作り
  （読み取りが 0.3 秒の到達確かめに相乗り・送信の 1 秒待ちの間は読まない）から来ているため。
  効くのは補正の記録の「もう一方の部品」= 10Hz の読み取りスレッドと、送信の待ちを daemon に持たせない形。

---

## 1. 手教示の記録で実測角を読む流れ（record_teach_demo.py の `_replay`）

```
Mac（record_teach_demo.py）                                     Pi（mecharm_daemon.py・1 本のソケット）
------------------------------------------------------------------------------------------------------
[move 区間 × 8]  HOME / APPROACH_PICK / PICK / LIFT / APPROACH_PLACE / PLACE / RETREAT / HOME
  recorder.stage(名前)  ── UDP 通知（recorder.py が states.csv に stage 行）
  sampler.read(once=False) ─────────────────────────────→  get_angles（空なら 0.02 秒おきに 12 回まで読み直す）
     └ 読めた角度を recorder.actual() で通知 → states.csv の actual 行        ≈0.02 秒
  _send_angles_guarded → daemon_send_angles(wait=1.0) ───→  send_angles: 書く → sleep(1.0) → 1 回だけ読む（ログ用）
     （この ≈1.03 秒は何も読まない）  ◀◀ 抜け ≈1.05 秒・アームは目標へ動いている
  _hold_until_arrival:
     loop: sampler.read(once=False) ───────────────────→  get_angles                         ≈0.02 秒
           許容差に入ったら抜ける
           _sleep_open(0.3)  ← ARRIVAL_POLL_SLEEP（電流の記録はこの間だけ read_servo を読む・角度は states.csv に書かない）
                                ◀◀ ふだんの間隔 0.3 + 0.02 = 0.32 秒
[gripper × 3]  open（HOME で）/ close（PICK で）/ open（PLACE で）
  _wait_until_still: 上と同じ「読む → 0.3 秒寝る」を 3 回続けて静止するまで
  recorder.pause_currents()
  close: daemon_set_gripper_value ──────────────────────→  すぐ返る（≈0.01 秒）
         time.sleep(2.0)（読まない）                                        ◀◀ 抜け ≈2.03 秒（アームは止まっている）
  open:  daemon_set_gripper(0, wait=0) ─────────────────→  sleep(2) → set_gripper_state（≈2.01 秒）
         time.sleep(2.0) → time.sleep(2.0)（読まない）                       ◀◀ 抜け ≈6.03 秒（アームは止まっている）
  recorder.resume_currents()
[HOME の settle]  sampler.sleep_with_reads: 1/3 秒ごとに get_angles_once 相当を読む（≈0.39 秒おき）
```

- 読みを待たせているもの: **自分の sleep（0.3 秒）**と、**daemon の送信の待ち（1.0 秒）**と、**爪の固定の待ち（2〜6 秒）**。
  daemon の 1 回の応答（get_angles ≈0.02 秒）・ロック・カメラは間隔をほとんど決めていない。
  - カメラは別のプロセス（recorder.py）で、角度の読みとは関係しない。
  - ロック: 電流の記録スレッド（依頼 121）は本体が寝ている間だけ読む作り（`reads_only_while_main_sleeps: true`）で、
    本体の読みは電流の記録を待たない。ただし電流スレッドが read_servo で読んだ角度は **states.csv に書いていない**
    （currents.csv の時刻を決めるのに使うだけ）。11/9 の 1 本では read_servo が 93 回・中央値 0.16 秒おきに読めていた。
- 設計の由来（コードのコメントより）: 10/19 に「0.1 秒ごとの補間送信」をやめて「区間ごとに 1 回送って到達を待つ」
  （本線 run_pick_place.py と同じ）にしたとき、記録用の 3 tick に 1 回の読み（≈3.3Hz）がなくなり、
  到達確かめのポーリング（0.3 秒）だけが残った。`ACTUAL_READ_TARGET_HZ = 3.0` は「これまでの 19 本と同程度の 3Hz 以上」。

## 2. 実際の間隔（元の記録の states.csv の actual 行の間）

`by_cause.csv` / `by_phase.csv` / `runs.csv`

| データ | 本 | 間の数 | 中央値 | 90% 点 | 最大 | 1 秒超の数 | 1 秒超が時間に占める割合 |
|---|---|---|---|---|---|---|---|
| teach_v1_trim2（10/19） | 19 | 1,108 | 0.324 | 1.055 | 6.05 | 209（1 本 11） | 62.3%（428.5 / 687.9 秒） |
| teach_pos1to4_deep_v1（11/9） | 31 | 1,808 | 0.324 | 1.056 | 6.07 | 341（1 本 11） | 62.4%（700.8 / 1123.2 秒） |
| scripted_v1（10/15・16） | 20 | 1,706 | 0.322 | 3.46 | 212.2 | 387 | 92.7%（3322.8 / 3586.3 秒） |

原因ごと（手教示の 2 つはほぼ同じなので deep_v1 の数。teach_v1 は括弧）:

| 原因 | 数 | 中央値 | 時間 | 1 秒超の時間に占める割合 | アームが動いた量に占める割合 |
|---|---|---|---|---|---|
| 0.3 秒のポーリングの間 | 1,343 | 0.324 | 420 秒 | 0%（最大 0.41 秒） | 40.5%（42.6%） |
| 送信の待ち（wait=1.0） | 248 | 1.052 | 263 秒 | 37.6%（37.4%） | **58.5%（56.4%）** |
| 爪の待ち | 93 | 6.03 / 2.03 | 437 秒 | **62.4%（62.6%）** | 1.0%（0.9%） |
| 段の切り替え | 124 | 0.020 | 2 秒 | 0% | 0.1% |

「動いた量」= 間ごとの 6 軸の |Δ| の最大を足したもの（`teach_motion_by_cause.csv`）。

段階ごとに見た送信の待ちの中の動き（deep_v1・1 回あたりの平均）: 近づく 27.8° / つかむ（PICK へ降りる）19.2° /
持ち上げ 18.4° / 運ぶ 29.1° / 放す（PLACE へ降りる）21.8° / 離れる 21.9°。どれも 31 本すべてで 2° 以上動いている。
1 秒の間を前後の実測でまっすぐ結ぶと、速度 20 の加速・減速の形が消える（特に PICK・PLACE の降下と持ち上げ）。

## 3. 長い抜けの原因をたどった例（scripted_v1）

scripted は run_pick_place.py（本線）の記録で、手教示とは別の作り。長い抜けの 3 本:

1. **212.2 秒**（run_0001_20261016_190925・stage9b_judge_place → stage10）: 放したあとの判定。
   swept_retreat（stage9b）を送って着いたあと、VLM の place の判定と **人の判定（`_ask_human_verdict` の input 待ち）**の間は
   何も読まない。間の 2 行の実測で j4 が -87.18 → -60.02 に変わっている（待っている間に j4 が 27° 動いた。理由は記録からは分からない）。
2. **129.9 秒**（run_0001_20261015_183310・stage6 → stage7）: 持ち上げたあとの pick の判定。同じく **人の判定待ち**（L4156）。
3. **48.5 秒**（run_0001_20261015_182552・stage6_a2）: つかみ直し。持ち上げのあと regrasp_open（爪）→ retreat →
   stage2_redetect（もう一度上カメラで位置を出す）までの間に読みがない。

scripted の 1 秒超の時間の内訳: 段の切り替え（人の判定待ち・検出など）37.5% / 爪 35.1% / ポーリングの間 16.9% / 送信 10.6%。
ポーリングの間の 1 秒超（90% 点 2.58 秒）は、当時の daemon の get_angles が動いている間に空で返り、0.2 秒おきに 12 回まで
読み直していた分（最長 ≈2.6 秒。11/5 の c7992ca のコミットの説明と同じ）。手教示の 10/19 の記録にはこれが出ていない
（ポーリングの間の最大 0.64 秒）。

## 4. 補正の記録（runs/pi05_policy）で 11/6 に抜けが減った理由

`corr_runs.csv`（依頼 196 の補正エピソードの元の run 12 本）

| 日 | 本 | 実測角の間 中央値 | 1 秒超が時間に占める割合 | send_angles 1 回の往復（中央値） |
|---|---|---|---|---|
| 10/31 | 5 | 0.102 | 29〜60% | 記録なし（往復を残す仕組みは 10/31 19:46 の 1b47477 から） |
| 11/1 | 3 | 0.102 | 32〜51% | **1.55 秒**（42〜59 回） |
| 11/6 | 4 | 0.096〜0.100 | **6〜12%** | **0.033 秒**（39〜53 回） |

- 補正の記録（policy_recorder.PolicyRecorder）は前から、本体と別の **10Hz の読み取りスレッド**で角度を読み、
  `install_daemon_lock` の鍵で本体とソケットを分け合っている。本体が daemon とやりとりしている間、スレッドは鍵を待つ。
- 11/1 の 1 本（190854）では、1 秒を超える抜け 62 個のうち 59 個が send_angles 1 回ずつに重なっていた（93.8 秒）。
  残りは爪（set_gripper の daemon の前の 2 秒）。
- 11/1 → 11/6 の間に変えたこと（git log）:
  1. **11/3 15ca6a4**: daemon を pymycobot 2.9.6 で起動する（tools/pi/mecharm_daemon_start.sh）。10/31 に systemd で
     起動するようにしてから 4.0.4 を読んでいて、送るたびに返事を 0.5 秒 × 3 回待ち 1 回 ≈1.6 秒かかっていた。**これが主因**。
  2. **11/5 c7992ca / 617c3bd**: daemon の読み直しの間 0.2 → 0.02 秒、送ったあとのログ用の読みを 1 回だけに（tools/daemon_fast_read.sh）。
  3. 11/5 cd2fb46 など: 補正をゲームパッド（send_angle の 1 刻み・stop）でするようにした。11/6 の 4 本はゲームパッドの補正。
  run_policy_client.py の送信の待ちは 10/30（7aaf5df）から `SEND_WAIT = 0.0` で、10/31・11/1 も同じなので、11/6 の差の理由ではない。
- 10/31 は往復の記録がないが、間の形（中央値 0.10 秒・最大 3.6 秒・1 秒超が 29〜60%）が 11/1 と同じなので、同じ理由と見ている（推定）。

**手教示にも使えるか**: daemon 側の直し（1・2）は日付の上では 11/9 の deep_v1 より前に入っている。deep_v1 の送信の往復は
1.03〜1.04 秒（wait 1.0 + 0.03 秒）で、4.0.4 で起動していた頃の 1.6 秒の上乗せは見えない。ただし 10/19 の teach_v1 も
送信の間は 1.04〜1.09 秒で、手教示では daemon の直しの前後で数字がほとんど変わらない（送った 1 秒後にはアームが止まりかけで、
読み直しがほとんど起きないため）。手教示に使えるのは補正の記録の作りのほう（10Hz の読み取りスレッド・送信の待ちを
daemon に持たせない）で、それが次の案 1・2。Pi の daemon が今 11/5 版かは、Pi に届かず確かめられていない。

## 5. 直し方の案

どれもまだ作っていない。数字は見込み。3 案とも爪の待ち（2〜6 秒・読まない）は変えない（アームは止まっているので、
前後の実測をまっすぐ結んでも正しい。依頼 196 の state_source では 2 =「動かなかった抜け」）。

### 案 1: 電流の記録スレッドが読んだ角度も states.csv に書く（本体の動きは変えない）

- ねらい: 0.3 秒の寝ている間に読む（すでに読んでいる）角度を、記録にも残す。
- 変える場所: pi05/policy_recorder.py の `CurrentsRecorder`（read_servo で読んだ角度を recorder へ actual として通知する。
  または record_teach_demo.py の `_Recorder` へ渡す口を足す）。記録の列は変えない。
  読み取りを get_angles だけにすれば 1 回 ≈0.02 秒で、read_servo（≈0.08 秒）より多く読める。
- 見込める間隔: ポーリングの間が 0.32 → 0.10〜0.16 秒（11/9 の電流の記録は寝ている間に中央値 0.16 秒おきに読めていた）。
  **送信の 1 秒の抜けは残る**（送信は寝ている間ではないので読まない）。動いた量の 56〜59% は抜けたまま。
- 実機で確かめる手順: HOME の近くで 1 本だけ `run`（いつもの手教示 1 本）→ states.csv の actual の間隔と、試行 JSON の
  segments の到達時間・still_check の回数が、直す前の本と同じ形かを比べる。
- アームの動きへの影響: 本体の送信・到達の確かめ・静止の確かめの回数と時刻は変わらない（電流スレッドの今の作りのまま）。
- 物理的リスク: **低**。関節の指令・姿勢の判断には触れない。読むのは寝ている間だけで、爪の命令の前後は今どおり止める。

### 案 2: 送信の 1 秒の待ちを daemon から Mac へ移し、その間も読む（案 1 と組み合わせる）

- ねらい: 一番動いている 1 秒（送信の待ち）を読めるようにする。待つ長さは縮めない。
- 変える場所: record_teach_demo.py の `_send_angles_guarded` を `daemon_send_angles(pose, speed, wait=0)` にし、
  返ったあと Mac 側で `_sleep_open(recorder, SEND_WAIT_SEC)`（1.0 秒・この間は案 1 のスレッドが読む）をしてから
  `_hold_until_arrival` に入る。爪の open で daemon の事後の待ちを Mac 側の `GRIPPER_OPEN_POST_SLEEP_SEC` に移したのと同じ形。
  到達の確かめが始まる時刻（送ってから ≈1.03 秒後）と、本体の読みの回数は今と同じ。
- 見込める間隔: 動いている間も 0.10〜0.16 秒おき。1 秒を超える抜けは爪の待ち（止まっている間）だけになり、
  動いた量のうち抜けに入る分は 56〜59% → ほぼ 0（爪の待ちの 1% 未満）。
- 実機で確かめる手順: (1) Pi の daemon が 11/5 版（`read_angles_once_for_log` がある・`GET_ANGLES_INTERVAL_SEC = 0.02`）かを読んで確かめる
  （wait=0 で送ると、送った直後に daemon が 1 回読む。旧版だと動いている間に最長 2.6 秒読み直す）。
  (2) 1 本だけ流し、送信の往復が 0.03 秒前後・send_angles が無視されていない（到達・再送の記録）・
  1 秒の間に 3 回以上 actual があることを見る。(3) 5 本ほど流して、到達の時間・静止の確かめの回数・再送の回数が直す前の本と変わらないかを比べる。
- アームの動きへの影響: 送る命令・速さ・目標・待つ長さは変えないが、**送ったあと 1 秒の間に get_angles（または read_servo）を
  シリアルに出す**ようになる（今は daemon が寝ているので 1 秒間シリアルは静か）。動いている最中の読みで送信が無視される
  ことが起きないかは、補正の記録（11/6 は動いている間も 10Hz で読み、送信の無視は記録上見えない）からは問題なさそうだが、手教示の流れでは確かめていない。
- 物理的リスク: **中**。関節の指令の中身は変えないが、送信の直後の 1 秒のシリアルの使い方が変わる。本線と同じ「SENDWAIT = 1.0（DAY266: 短縮しない）」を
  「daemon が待つ」から「Mac が待つ」に置き換えることになるので、決まりの読み方をエイイチが決める必要がある。

### 案 3: 送信の待ちを 0 にし、到達の確かめのポーリングを送った直後から始める

- ねらい: 一番小さい変更で送信の 1 秒の抜けを消す（run_policy_client.py が 10/30 から `SEND_WAIT = 0.0` でしているのと同じ）。
- 変える場所: record_teach_demo.py の `_send_angles_guarded` の `wait=SEND_WAIT_SEC` → `wait=0`（Mac 側でも待たない）。
- 見込める間隔: 動いている間も 0.32 秒おき（案 1 と組むと 0.10〜0.16 秒）。1 秒の抜けは消える。
- 実機で確かめる手順: 案 2 と同じ。加えて、到達の確かめが送ってすぐ始まるので、到達の時間・「通過中に到達扱い」になる回数を比べる。
- アームの動きへの影響: **到達の確かめが 1 秒早く始まる**。区間ごとの所要時間が短くなりうる（次の区間を早く送る）。
  静止の確かめ（爪の前）は残るので爪の安全は変わらないが、PICK・PLACE への入り方の時間が今の 50 本と変わる。
- 物理的リスク: **中〜高**。待つ長さを縮める（CLAUDE.md の「time.sleep() を削除・短縮しない」と DAY266 に当たる）。
  動き方（区間のつなぎの時間）が変わるので、これまでのお手本と同じ動きのデータではなくなる。勧めない。

### 勧める順

案 1 → 案 2。案 1 だけなら動きは何も変わらず、ポーリングの間が 0.32 → 0.1〜0.16 秒になる。
動いた量の半分以上がある送信の 1 秒を読むには案 2 が要る。

## 6. エイイチが決めること

1. どの案で直すか（勧め: 案 1、その次に案 2。案 3 は勧めない）。
2. 案 2 をするなら: 「SENDWAIT = 1.0（短縮しない）」を「daemon ではなく Mac 側で 1.0 秒待つ（待つ長さは同じ）」に置き換えてよいか。
   送った直後の 1 秒にシリアルを読むことになる。
3. 案 1・2 で読む命令: 角度だけ（get_angles・≈0.02 秒・速い）にするか、電流も読む read_servo（≈0.08 秒）のままにするか。
4. 実機での確かめ（1 本 → 5 本）をいつするか。その前に Pi の daemon が 11/5 版かを読むこと（今日は Pi に届かなかった）。
5. 直した記録で撮り直すか、今のお手本（teach_v1・deep_v1）は今のまま使い、依頼 196 の印（動いた抜け / 動かなかった抜け）で扱うか。
   今の手教示の抜けは「爪の待ち = 動かなかった抜け」と「送信の 1 秒 = 動いた抜け」にきれいに分かれる（どの本も 11 個）。
6. scripted_v1 の人の判定待ち（最大 212 秒）の間の j4 の変化（-87 → -60）を調べるかどうか（今回の範囲外）。
~~~~


### 依頼197 の測った数字（diag/teach_state_rate_20261115/）


#### README.md

```markdown
# teach_state_rate_20261115 (依頼 197)

手教示・scripted の元の記録 (runs/run_pick_place/{run}/recording/states.csv) と, 補正の記録 (runs/pi05_policy) の
実測角 (actual) の読めた間隔を数えた。読むだけ。どのデータも書き換えていない。報告: docs/investigation_20261115_teach_state_rate.md

- measure_gaps.py → gaps.csv (間 1 つごと) / runs.csv (本ごと) / by_cause.csv (原因ごと) / by_phase.csv (段階ごと)
  - 対象は datasets/mecharm_redblock_box_{teach_v1_trim2, teach_pos1to4_deep_v1, scripted_v1}/index.json で used の本
  - cause: gripper = 間に爪の命令の行がある / send = 送信をはさむ (手教示は stage 行の直後の読みから次の読みまで, scripted は commanded 行) /
    stage_change = 段の切り替えだけ (scripted では人の判定待ちなど) / poll = ほかに何もない読みと読みの間
  - phase: approach / grasp (PICK・爪を閉じる) / carry_lift / carry / release (PLACE・爪を開く) / retreat / home
- measure_motion_in_gaps.py → teach_motion_by_cause.csv (間ごとの 6 軸 |Δ| の最大を原因ごとに足した「動いた量」)
- measure_corr.py → corr_runs.csv (依頼 196 の補正エピソードの元の run ごとの間隔と, send_angles 1 回の daemon 往復 rpc_sec)
- 流し方: cd /tmp && python3 -I /Volumes/KIOXIA/r2r2r-data/diag/teach_state_rate_20261115/measure_gaps.py (ほかの 2 本も同じ。motion は gaps.csv を先に作る)
```


#### by_cause.csv

```csv
dataset,cause,n,median,p90,max,time_sec,time_share,long_n,long_time_sec,share_of_long_time
teach_v1_trim2,gripper,57,6.0315,6.0423,6.053,268.06,0.3897,57,268.06,0.6256
teach_v1_trim2,poll,823,0.3224,0.3922,0.642,257.95,0.375,0,0.0,0.0
teach_v1_trim2,send,152,1.0508,1.0781,1.088,160.45,0.2332,152,160.45,0.3744
teach_v1_trim2,stage_change,76,0.0199,0.0225,0.029,1.47,0.0021,0,0.0,0.0
teach_v1_trim2,ALL,1108,0.3237,1.0545,6.053,687.93,1.0,209,428.51,1.0
teach_pos1to4_deep_v1,gripper,93,6.0322,6.0428,6.066,437.32,0.3893,93,437.32,0.624
teach_pos1to4_deep_v1,poll,1343,0.3236,0.3922,0.412,420.05,0.374,0,0.0,0.0
teach_pos1to4_deep_v1,send,248,1.0517,1.0736,2.244,263.46,0.2346,248,263.46,0.376
teach_pos1to4_deep_v1,stage_change,124,0.02,0.0234,0.032,2.39,0.0021,0,0.0,0.0
teach_pos1to4_deep_v1,ALL,1808,0.324,1.0555,6.066,1123.22,1.0,341,700.78,1.0
scripted_v1,gripper,64,17.8522,32.9023,48.453,1164.87,0.3248,64,1164.87,0.3506
scripted_v1,poll,1277,0.322,2.5847,2.856,808.39,0.2254,216,560.56,0.1687
scripted_v1,send,278,0.0219,4.144,29.804,362.29,0.101,65,352.8,0.1062
scripted_v1,stage_change,87,0.4919,33.5179,212.204,1250.76,0.3488,42,1244.55,0.3746
scripted_v1,ALL,1706,0.3219,3.4589,212.204,3586.3,1.0,387,3322.78,1.0
```


#### by_phase.csv

```csv
dataset,phase,n,median,p90,max,time_sec,time_share,long_n,long_time_sec,share_of_long_time
teach_v1_trim2,approach,240,0.3222,0.3348,1.085,85.68,0.1245,19,20.0,0.0467
teach_v1_trim2,carry,133,0.3219,1.0483,1.088,51.11,0.0743,19,20.11,0.0469
teach_v1_trim2,carry_lift,85,0.322,1.0492,1.085,35.64,0.0518,19,20.09,0.0469
teach_v1_trim2,grasp,141,0.3233,2.0292,2.046,86.23,0.1253,38,58.74,0.1371
teach_v1_trim2,home,357,0.3913,1.0501,6.053,255.37,0.3712,57,154.76,0.3612
teach_v1_trim2,release,114,0.3237,6.0319,6.052,153.52,0.2232,38,134.77,0.3145
teach_v1_trim2,retreat,38,0.5341,1.0601,1.075,20.39,0.0296,19,20.03,0.0467
teach_v1_trim2,ALL,1108,0.3237,1.0545,6.053,687.93,1.0,209,428.51,1.0
teach_pos1to4_deep_v1,approach,396,0.3233,0.3325,1.085,141.17,0.1257,31,32.74,0.0467
teach_pos1to4_deep_v1,carry,240,0.3225,1.0477,1.089,90.88,0.0809,31,32.78,0.0468
teach_pos1to4_deep_v1,carry_lift,98,0.3232,1.052,1.076,44.76,0.0398,31,32.56,0.0465
teach_pos1to4_deep_v1,grasp,188,0.324,2.0309,2.044,127.57,0.1136,62,96.28,0.1374
teach_pos1to4_deep_v1,home,595,0.3884,1.0535,6.066,420.09,0.374,93,252.72,0.3606
teach_pos1to4_deep_v1,release,229,0.3237,6.0322,6.052,265.49,0.2364,62,221.03,0.3154
teach_pos1to4_deep_v1,retreat,62,0.5342,1.0615,1.073,33.27,0.0296,31,32.67,0.0466
teach_pos1to4_deep_v1,ALL,1808,0.324,1.0555,6.066,1123.22,1.0,341,700.78,1.0
scripted_v1,approach,157,0.3217,2.597,28.665,108.47,0.0302,22,83.47,0.0251
scripted_v1,carry,82,0.162,2.5962,28.125,82.85,0.0231,20,77.26,0.0233
scripted_v1,carry_lift,334,0.322,2.6253,129.918,651.6,0.1817,42,567.03,0.1706
scripted_v1,grasp,92,0.3226,4.1921,4.305,151.46,0.0422,44,149.38,0.045
scripted_v1,home,208,0.3221,5.3222,34.253,737.8,0.2057,29,681.76,0.2052
scripted_v1,other:STAGE6_A2,14,0.322,17.3113,48.453,79.34,0.0221,4,77.31,0.0233
scripted_v1,other:STAGE6_A3,8,0.3217,3.869,6.744,10.71,0.003,2,9.38,0.0028
scripted_v1,release,564,0.3201,4.4268,212.204,1625.76,0.4533,186,1578.11,0.4749
scripted_v1,retreat,247,0.3218,2.6052,2.677,138.32,0.0386,38,99.09,0.0298
scripted_v1,ALL,1706,0.3219,3.4589,212.204,3586.3,1.0,387,3322.78,1.0
```


#### teach_motion_by_cause.csv

```csv
dataset,cause,phase,n,time_sec,motion_deg_sum,motion_share,mean_motion_deg,n_moved_ge_2deg
teach_v1_trim2,gripper,,57,268.06,48.8,0.0094,0.86,2
teach_v1_trim2,poll,,823,257.95,2199.0,0.4256,2.67,240
teach_v1_trim2,send,approach,19,20.0,525.9,0.1018,27.68,19
teach_v1_trim2,send,carry,19,20.11,545.9,0.1056,28.73,19
teach_v1_trim2,send,carry_lift,19,20.09,260.0,0.0503,13.68,19
teach_v1_trim2,send,grasp,19,20.09,285.8,0.0553,15.04,19
teach_v1_trim2,send,home,38,40.07,596.1,0.1154,15.69,22
teach_v1_trim2,send,release,19,20.06,351.4,0.068,18.5,19
teach_v1_trim2,send,retreat,19,20.03,349.3,0.0676,18.38,19
teach_v1_trim2,stage_change,,76,1.47,5.0,0.001,0.07,0
teach_pos1to4_deep_v1,gripper,,93,437.32,86.0,0.0096,0.93,12
teach_pos1to4_deep_v1,poll,,1343,420.05,3612.1,0.4046,2.69,398
teach_pos1to4_deep_v1,send,approach,31,32.74,862.2,0.0966,27.81,31
teach_pos1to4_deep_v1,send,carry,31,32.79,903.2,0.1012,29.14,31
teach_pos1to4_deep_v1,send,carry_lift,31,32.56,571.0,0.064,18.42,31
teach_pos1to4_deep_v1,send,grasp,31,33.28,595.7,0.0667,19.22,31
teach_pos1to4_deep_v1,send,home,62,65.54,938.4,0.1051,15.13,31
teach_pos1to4_deep_v1,send,release,31,33.89,674.3,0.0755,21.75,31
teach_pos1to4_deep_v1,send,retreat,31,32.67,677.6,0.0759,21.86,31
teach_pos1to4_deep_v1,stage_change,,124,2.39,7.5,0.0008,0.06,0
```


#### corr_runs.csv

```csv
run,date,n_actual,span_sec,median,p90,max,gt_0p25_time_share,gt_1s_time_share,send_angles_n,send_angles_rpc_median,send_angles_rpc_max,rpc_cmds
pi05_20261031_175527,20261031,1758,254.74,0.1019,0.1047,3.631,0.3462,0.3462,0,,,
pi05_20261031_180435,20261031,915,183.47,0.1019,0.1092,3.592,0.56,0.56,0,,,
pi05_20261031_181946,20261031,2448,330.45,0.1019,0.1042,3.594,0.2892,0.2892,0,,,
pi05_20261031_182545,20261031,2405,362.19,0.1019,0.1045,3.612,0.3761,0.3761,0,,,
pi05_20261031_184016,20261031,721,154.57,0.1019,0.1112,3.582,0.595,0.595,0,,,
pi05_20261101_190347,20261101,2118,266.66,0.1019,0.1032,3.641,0.3157,0.3157,48,1.545,1.633,send_angles:48;set_gripper:2;set_gripper_value:1
pi05_20261101_190854,20261101,1355,201.77,0.1013,0.1036,3.591,0.5085,0.5085,59,1.552,2.313,send_angles:59;set_gripper:2;set_gripper_value:1
pi05_20261101_192101,20261101,1101,160.94,0.1017,0.103,3.601,0.4778,0.4778,42,1.572,1.632,send_angles:42;set_gripper:2;set_gripper_value:2
pi05_20261106_183926,20261106,2138,192.1,0.0996,0.1042,3.429,0.0599,0.0561,53,0.034,0.142,send_angle:13;send_angles:53;set_gripper:2;set_gripper_value:1;stop:4
pi05_20261106_184452,20261106,1071,91.85,0.0959,0.1044,3.262,0.1249,0.1149,39,0.035,0.137,send_angle:16;send_angles:39;set_gripper:2;set_gripper_value:1;stop:4
pi05_20261106_184650,20261106,1216,107.73,0.0976,0.1045,3.321,0.1116,0.0992,46,0.033,0.138,send_angle:7;send_angles:46;set_gripper:2;set_gripper_value:2;stop:3
pi05_20261106_184906,20261106,993,86.51,0.0961,0.1043,3.35,0.1307,0.1234,40,0.034,0.142,send_angle:8;send_angles:40;set_gripper:2;set_gripper_value:2;stop:2
```


#### runs.csv

```csv
dataset,run,n_actual,span_sec,median,p90,max,long_gt1s_count,long_time_share,mean_hz
teach_v1_trim2,run_0001_20261019_183454,59,36.169,0.3255,1.0516,6.048,11,0.6237,1.604
teach_v1_trim2,run_0001_20261019_191257,54,34.549,0.3266,1.0671,6.041,11,0.6537,1.534
teach_v1_trim2,run_0001_20261019_191347,63,37.35,0.3232,1.0491,6.052,11,0.6028,1.66
teach_v1_trim2,run_0001_20261019_191441,86,44.771,0.3232,1.0482,6.038,11,0.5032,1.899
teach_v1_trim2,run_0001_20261019_191541,60,36.373,0.3239,1.0524,6.042,11,0.6194,1.622
teach_v1_trim2,run_0001_20261019_191635,61,36.635,0.3232,1.0486,6.042,11,0.6145,1.638
teach_v1_trim2,run_0001_20261019_192343,53,34.236,0.3248,1.061,6.04,11,0.6597,1.519
teach_v1_trim2,run_0001_20261019_192438,57,35.419,0.324,1.0493,6.045,11,0.6361,1.581
teach_v1_trim2,run_0001_20261019_192539,57,35.479,0.3246,1.0503,6.053,11,0.636,1.578
teach_v1_trim2,run_0001_20261019_192633,56,35.093,0.3223,1.0652,6.032,11,0.6432,1.567
teach_v1_trim2,run_0001_20261019_193404,62,36.999,0.3238,1.0479,6.038,11,0.6079,1.649
teach_v1_trim2,run_0001_20261019_193459,61,36.724,0.3235,1.0639,6.032,11,0.6148,1.634
teach_v1_trim2,run_0001_20261019_193617,61,36.738,0.3239,1.0477,6.049,11,0.6134,1.633
teach_v1_trim2,run_0001_20261019_193825,75,41.259,0.3222,1.055,6.032,11,0.5478,1.794
teach_v1_trim2,run_0001_20261019_193932,60,36.36,0.323,1.05,6.031,11,0.6197,1.623
teach_v1_trim2,run_0001_20261019_194818,51,33.886,0.3252,1.0583,6.042,11,0.6666,1.476
teach_v1_trim2,run_0001_20261019_194913,51,33.455,0.3235,1.0537,6.042,11,0.6734,1.495
teach_v1_trim2,run_0001_20261019_195023,50,33.227,0.3239,1.0648,6.031,11,0.6797,1.475
teach_v1_trim2,run_0001_20261019_195120,50,33.211,0.3231,1.063,6.042,11,0.6802,1.475
teach_pos1to4_deep_v1,run_0001_20261109_094839,66,38.424,0.3242,1.0568,6.042,11,0.5872,1.692
teach_pos1to4_deep_v1,run_0001_20261109_095308,63,37.329,0.3233,1.0544,6.048,11,0.6048,1.661
teach_pos1to4_deep_v1,run_0001_20261109_095810,63,37.279,0.3238,1.0478,6.043,11,0.6039,1.663
teach_pos1to4_deep_v1,run_0001_20261109_095948,65,37.998,0.3241,1.0499,6.039,11,0.593,1.684
teach_pos1to4_deep_v1,run_0001_20261109_100126,64,37.645,0.3239,1.0518,6.041,11,0.5986,1.674
teach_pos1to4_deep_v1,run_0001_20261109_100307,60,36.393,0.3244,1.0524,6.034,11,0.6189,1.621
teach_pos1to4_deep_v1,run_0001_20261109_100444,64,37.65,0.3229,1.0468,6.043,11,0.5979,1.673
teach_pos1to4_deep_v1,run_0001_20261109_100716,60,36.521,0.3239,1.0588,6.066,11,0.6194,1.616
teach_pos1to4_deep_v1,run_0001_20261109_101157,65,38.007,0.324,1.0546,6.04,11,0.5933,1.684
teach_pos1to4_deep_v1,run_0001_20261109_102109,60,36.472,0.3246,1.0588,6.037,11,0.619,1.618
teach_pos1to4_deep_v1,run_0001_20261109_102248,62,37.052,0.3243,1.0481,6.043,11,0.608,1.646
teach_pos1to4_deep_v1,run_0001_20261109_102431,63,37.36,0.3227,1.0592,6.041,11,0.6051,1.66
teach_pos1to4_deep_v1,run_0001_20261109_103049,64,37.69,0.3239,1.0556,6.033,11,0.5983,1.672
teach_pos1to4_deep_v1,run_0001_20261109_103804,58,35.735,0.324,1.0545,6.038,11,0.6311,1.595
teach_pos1to4_deep_v1,run_0001_20261109_103943,61,36.682,0.324,1.0538,6.044,11,0.6141,1.636
teach_pos1to4_deep_v1,run_0001_20261109_104110,64,37.667,0.3241,1.0477,6.034,11,0.5967,1.673
teach_pos1to4_deep_v1,run_0001_20261109_104517,59,36.057,0.324,1.0602,6.033,11,0.6254,1.609
teach_pos1to4_deep_v1,run_0001_20261109_123756,54,34.389,0.3239,1.052,6.034,11,0.6557,1.541
teach_pos1to4_deep_v1,run_0001_20261109_123848,56,35.046,0.3242,1.0506,6.044,11,0.6421,1.569
teach_pos1to4_deep_v1,run_0001_20261109_124032,54,34.379,0.3223,1.0586,6.042,11,0.6555,1.542
teach_pos1to4_deep_v1,run_0001_20261109_124117,53,34.111,0.3236,1.0522,6.037,11,0.6611,1.524
teach_pos1to4_deep_v1,run_0001_20261109_124207,54,34.349,0.3232,1.0573,6.039,11,0.6563,1.543
teach_pos1to4_deep_v1,run_0001_20261109_124256,55,34.758,0.325,1.053,6.046,11,0.6487,1.554
teach_pos1to4_deep_v1,run_0001_20261109_124438,54,35.703,0.325,1.0585,6.044,11,0.6645,1.484
teach_pos1to4_deep_v1,run_0001_20261109_124817,56,35.161,0.324,1.0612,6.032,11,0.6423,1.564
teach_pos1to4_deep_v1,run_0001_20261109_124920,54,34.558,0.3241,1.0604,6.052,11,0.6537,1.534
teach_pos1to4_deep_v1,run_0001_20261109_130542,59,36.128,0.3244,1.0567,6.059,11,0.6246,1.605
teach_pos1to4_deep_v1,run_0001_20261109_130723,57,35.467,0.3243,1.052,6.042,11,0.6359,1.579
teach_pos1to4_deep_v1,run_0001_20261109_130824,57,35.99,0.3224,1.0585,6.04,11,0.6431,1.556
teach_pos1to4_deep_v1,run_0001_20261109_130929,57,35.44,0.3233,1.0601,6.042,11,0.637,1.58
teach_pos1to4_deep_v1,run_0001_20261109_131103,58,35.785,0.3241,1.0505,6.042,11,0.6293,1.593
scripted_v1,run_0001_20261015_173315,49,107.699,0.2509,4.3059,31.252,16,0.9685,0.446
scripted_v1,run_0001_20261015_175333,75,124.599,0.322,2.6453,31.352,16,0.8998,0.594
scripted_v1,run_0001_20261015_181752,49,175.523,0.322,4.3118,45.693,17,0.9734,0.273
scripted_v1,run_0001_20261015_182056,77,116.704,0.3219,2.6212,33.404,16,0.8994,0.651
scripted_v1,run_0001_20261015_182552,152,281.907,0.3219,2.6617,48.453,33,0.9129,0.536
scripted_v1,run_0001_20261015_183310,134,293.119,0.3219,2.5921,129.918,21,0.9091,0.454
scripted_v1,run_0001_20261015_185536,131,157.857,0.322,2.6139,31.482,23,0.8419,0.824
scripted_v1,run_0001_20261015_193907,82,143.674,0.3218,4.104,32.403,20,0.9239,0.564
scripted_v1,run_0001_20261015_194135,56,153.948,0.1018,4.3983,31.831,21,0.9846,0.357
scripted_v1,run_0001_20261015_194420,80,120.303,0.322,2.6066,31.55,18,0.9032,0.657
scripted_v1,run_0001_20261016_175444,92,140.545,0.3217,2.6631,32.911,21,0.9082,0.647
scripted_v1,run_0001_20261016_175708,65,179.461,0.2549,4.165,56.782,21,0.9722,0.357
scripted_v1,run_0001_20261016_180013,87,134.667,0.3219,3.3843,32.783,21,0.9162,0.639
scripted_v1,run_0001_20261016_184725,59,210.314,0.1153,4.1496,81.064,19,0.9833,0.276
scripted_v1,run_0001_20261016_185201,63,181.669,0.322,4.1844,40.383,17,0.9473,0.341
scripted_v1,run_0001_20261016_190925,102,367.113,0.322,2.667,212.204,21,0.9505,0.275
scripted_v1,run_0001_20261016_191539,81,235.814,0.3218,4.0774,91.713,20,0.9544,0.339
scripted_v1,run_0001_20261016_191942,113,150.762,0.322,2.5832,31.843,13,0.819,0.743
scripted_v1,run_0001_20261016_192229,120,139.553,0.322,2.5787,32.362,16,0.8035,0.853
scripted_v1,run_0001_20261016_194238,59,171.072,0.1219,3.0872,54.122,17,0.9751,0.339
```


#### measure_gaps.py

```python
"""依頼 197: 元の記録 states.csv の実測角 (actual) の間隔を数える. 読むだけ.
python3 measure_gaps.py  → 同じフォルダに gaps.csv / runs.csv / by_cause.csv / by_stage.csv
"""
import csv, json, os, sys
from collections import defaultdict
import numpy as np

ROOT = "/Volumes/KIOXIA/r2r2r-data"
OUT = os.path.dirname(os.path.abspath(__file__))
SETS = ["teach_v1_trim2", "teach_pos1to4_deep_v1", "scripted_v1"]
LONG = 1.0

def phase_of(stage):
    s = (stage or "").upper()
    if "LIFT" in s or s == "STAGE6": return "carry_lift"
    if "RETREAT" in s or s.startswith("STAGE10"): return "retreat"
    if "APPROACH_PLACE" in s or s.startswith("STAGE7"): return "carry"
    if s in ("PICK",) or s.startswith("STAGE4") or s.startswith("STAGE5"): return "grasp"
    if "PLACE" in s or s.startswith("STAGE8") or s.startswith("STAGE9"): return "release"
    if "APPROACH_PICK" in s or s.startswith("STAGE3"): return "approach"
    if "HOME" in s or s in ("STAGE1", "STAGE2") or s.startswith("STAGE11") or s.startswith("STAGE12"): return "home"
    return "other:" + s

def load(run):
    p = f"{ROOT}/runs/run_pick_place/{run}/recording/states.csv"
    rows = list(csv.DictReader(open(p)))
    for r in rows: r["ts"] = float(r["ts"])
    return rows

def classify(rows, ds):
    """actual の 1 つの間ごとに, 間の中で起きたこと (原因) を決める."""
    acts = [i for i, r in enumerate(rows) if r["event_type"] == "actual" and r["j0"] != ""]
    out = []
    for a, b in zip(acts, acts[1:]):
        ra, rb = rows[a], rows[b]
        mid = rows[a + 1:b]
        types = [m["event_type"] for m in mid]
        # 直前の actual が stage 行のすぐあと (=送信前の読み) か
        prev = rows[a - 1]["event_type"] if a > 0 else ""
        if "gripper_cmd" in types or "gripper" in types:
            cause = "gripper"
        elif "commanded" in types:
            cause = "send"
        elif ds != "scripted_v1" and prev == "stage":
            cause = "send"          # record_teach_demo: stage → 送信前の読み → 送信 (wait=1.0)
        elif "stage" in types:
            cause = "stage_change"
        else:
            cause = "poll"
        out.append(dict(t0=ra["ts"], t1=rb["ts"], gap=rb["ts"] - ra["ts"], stage=ra["stage"],
                        phase=phase_of(ra["stage"]), cause=cause, between=";".join(types)))
    return out

def q(v, p): return float(np.percentile(v, p)) if len(v) else float("nan")

gap_rows, run_rows = [], []
for ds in SETS:
    idx = json.load(open(f"{ROOT}/datasets/mecharm_redblock_box_{ds}/index.json"))
    runs = [k for k, v in idx.items() if v.get("used")]
    for run in runs:
        g = classify(load(run), ds)
        for x in g: x.update(dataset=ds, run=run); gap_rows.append(x)
        v = np.array([x["gap"] for x in g])
        tot = v.sum()
        run_rows.append(dict(dataset=ds, run=run, n_actual=len(v) + 1, span_sec=round(tot, 3),
                             median=round(q(v, 50), 4), p90=round(q(v, 90), 4), max=round(v.max(), 3),
                             long_gt1s_count=int((v > LONG).sum()),
                             long_time_share=round(v[v > LONG].sum() / tot, 4),
                             mean_hz=round(len(v) / tot, 3)))

with open(f"{OUT}/gaps.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=["dataset", "run", "t0", "t1", "gap", "stage", "phase", "cause", "between"])
    w.writeheader(); [w.writerow({**x, "gap": round(x["gap"], 4)}) for x in gap_rows]
with open(f"{OUT}/runs.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=list(run_rows[0].keys())); w.writeheader(); w.writerows(run_rows)

def agg(key, fname):
    rows = []
    for ds in SETS:
        G = [x for x in gap_rows if x["dataset"] == ds]
        T = sum(x["gap"] for x in G)
        LT = sum(x["gap"] for x in G if x["gap"] > LONG)
        groups = defaultdict(list)
        for x in G: groups[x[key]].append(x["gap"])
        for k, v in sorted(groups.items()):
            v = np.array(v); lv = v[v > LONG]
            rows.append(dict(dataset=ds, **{key: k}, n=len(v), median=round(q(v, 50), 4), p90=round(q(v, 90), 4),
                             max=round(v.max(), 3), time_sec=round(v.sum(), 2), time_share=round(v.sum() / T, 4),
                             long_n=len(lv), long_time_sec=round(lv.sum(), 2),
                             share_of_long_time=round(lv.sum() / LT, 4) if LT else 0))
        v = np.array([x["gap"] for x in G])
        rows.append(dict(dataset=ds, **{key: "ALL"}, n=len(v), median=round(q(v, 50), 4), p90=round(q(v, 90), 4),
                         max=round(v.max(), 3), time_sec=round(T, 2), time_share=1.0,
                         long_n=int((v > LONG).sum()), long_time_sec=round(LT, 2), share_of_long_time=1.0))
    with open(f"{OUT}/{fname}", "w", newline="") as f:
        w = csv.DictWriter(f, fieldnames=list(rows[0].keys())); w.writeheader(); w.writerows(rows)
    return rows

for r in agg("cause", "by_cause.csv"): print(r)
print()
for r in agg("phase", "by_phase.csv"): print(r)
```


#### measure_motion_in_gaps.py

```python
"""依頼 197: 手教示の元の記録で, 実測角の間ごとの動いた量 (6 軸の |Δ| の最大) を原因ごとに足す. 読むだけ.
gaps.csv (measure_gaps.py の出力) の t0/t1 と states.csv の角度を突き合わせる."""
import csv, os
from collections import defaultdict
ROOT = "/Volumes/KIOXIA/r2r2r-data"
OUT = os.path.dirname(os.path.abspath(__file__))
G = list(csv.DictReader(open(f"{OUT}/gaps.csv")))
cache = {}
def angles(run):
    if run not in cache:
        cache[run] = {round(float(r["ts"]), 6): [float(r[f"j{i}"]) for i in range(6)]
                      for r in csv.DictReader(open(f"{ROOT}/runs/run_pick_place/{run}/recording/states.csv"))
                      if r["event_type"] == "actual" and r["j0"] != ""}
    return cache[run]
agg = defaultdict(lambda: [0, 0.0, 0.0, 0])   # n, time, motion_deg, n_moving(>=2deg)
rows = []
for g in G:
    if not g["dataset"].startswith("teach"): continue
    A = angles(g["run"])
    a, b = A[round(float(g["t0"]), 6)], A[round(float(g["t1"]), 6)]
    d = max(abs(x - y) for x, y in zip(a, b))
    k = (g["dataset"], g["cause"], g["phase"] if g["cause"] == "send" else "")
    s = agg[k]; s[0] += 1; s[1] += float(g["gap"]); s[2] += d; s[3] += d >= 2.0
for ds in ("teach_v1_trim2", "teach_pos1to4_deep_v1"):
    tot = sum(v[2] for k, v in agg.items() if k[0] == ds)
    for k, v in sorted(agg.items()):
        if k[0] != ds: continue
        rows.append(dict(dataset=ds, cause=k[1], phase=k[2], n=v[0], time_sec=round(v[1], 2),
                         motion_deg_sum=round(v[2], 1), motion_share=round(v[2] / tot, 4),
                         mean_motion_deg=round(v[2] / v[0], 2), n_moved_ge_2deg=v[3]))
with open(f"{OUT}/teach_motion_by_cause.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=list(rows[0].keys())); w.writeheader(); w.writerows(rows)
for r in rows: print(r)
```


#### measure_corr.py

```python
"""依頼 197 の 4: 補正の記録 (runs/pi05_policy) の実測角の間隔と, daemon とのやりとり 1 回の長さを日付ごとに数える. 読むだけ.
対象は依頼 196 の episodes.csv に出てくる補正エピソード (元の run を丸ごと数える)."""
import csv, os, re
from collections import defaultdict
import numpy as np
ROOT = "/Volumes/KIOXIA/r2r2r-data"
OUT = os.path.dirname(os.path.abspath(__file__))
runs = sorted({r["run_stem"] for r in csv.DictReader(open(f"{ROOT}/diag/fill_flags_20261114/episodes.csv"))})
rows = []
for run in runs:
    S = list(csv.DictReader(open(f"{ROOT}/runs/pi05_policy/{run}/recording/states.csv")))
    act = np.array([float(r["ts"]) for r in S if r["event_type"] == "actual" and r["j0"] != ""])
    g = np.diff(act)
    rpc = defaultdict(list)
    for r in S:
        m = re.search(r"rpc_sec=([0-9.]+)", r["note"] or "")
        if not m: continue
        c = re.search(r"cmd=(\w+)", r["note"]); cmd = c.group(1) if c else r["event_type"]
        rpc[cmd].append(float(m.group(1)))
    sa = np.array(rpc.get("send_angles", []))
    rows.append(dict(run=run, date=run[5:13], n_actual=len(act), span_sec=round(act[-1] - act[0], 2),
                     median=round(float(np.median(g)), 4), p90=round(float(np.percentile(g, 90)), 4),
                     max=round(float(g.max()), 3), gt_0p25_time_share=round(g[g > 0.25].sum() / g.sum(), 4),
                     gt_1s_time_share=round(g[g > 1.0].sum() / g.sum(), 4),
                     send_angles_n=len(sa), send_angles_rpc_median=(round(float(np.median(sa)), 3) if len(sa) else ""),
                     send_angles_rpc_max=(round(float(sa.max()), 3) if len(sa) else ""),
                     rpc_cmds=";".join(f"{k}:{len(v)}" for k, v in sorted(rpc.items()))))
with open(f"{OUT}/corr_runs.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=list(rows[0].keys())); w.writeheader(); w.writerows(rows)
for r in rows: print(r)
```


#### gaps.csv

```csv
dataset,run,t0,t1,gap,stage,phase,cause,between
teach_v1_trim2,run_0001_20261019_183454,1792402495.353289,1792402496.404509,1.0512,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_183454,1792402496.404509,1792402496.788903,0.3844,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402496.788903,1792402497.180892,0.392,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402497.180892,1792402497.591577,0.4107,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402497.591577,1792402497.993632,0.4021,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402497.993632,1792402498.405059,0.4114,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402498.405059,1792402498.806889,0.4018,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402498.806889,1792402499.198426,0.3915,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402499.198426,1792402499.596827,0.3984,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402499.596827,1792402499.833045,0.2362,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402499.833045,1792402499.852812,0.0198,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402499.852812,1792402500.172845,0.32,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402500.172845,1792402500.498907,0.3261,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402500.498907,1792402500.820245,0.3213,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402500.820245,1792402506.862212,6.042,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_183454,1792402506.862212,1792402507.90876,1.0465,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_183454,1792402507.90876,1792402508.236781,0.328,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402508.236781,1792402508.557335,0.3206,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402508.557335,1792402508.882243,0.3249,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402508.882243,1792402509.208906,0.3267,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402509.208906,1792402509.544872,0.336,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402509.544872,1792402509.879701,0.3348,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402509.879701,1792402510.210684,0.331,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402510.210684,1792402510.532827,0.3221,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402510.532827,1792402510.85427,0.3214,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402510.85427,1792402511.176403,0.3221,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402511.176403,1792402511.500662,0.3243,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402511.500662,1792402511.820215,0.3196,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402511.820215,1792402512.144717,0.3245,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402512.144717,1792402512.164946,0.0202,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_183454,1792402512.164946,1792402513.217399,1.0525,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_183454,1792402513.217399,1792402513.236976,0.0196,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402513.236976,1792402513.562995,0.326,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402513.562995,1792402513.87418,0.3112,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402513.87418,1792402514.196352,0.3222,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402514.196352,1792402516.242287,2.0459,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_183454,1792402516.242287,1792402517.29328,1.051,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_183454,1792402517.29328,1792402517.312636,0.0194,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_183454,1792402517.312636,1792402518.37261,1.06,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_183454,1792402518.37261,1792402518.690369,0.3178,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402518.690369,1792402519.011974,0.3216,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402519.011974,1792402519.334866,0.3229,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402519.334866,1792402519.656603,0.3217,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402519.656603,1792402519.978419,0.3218,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402519.978419,1792402519.99663,0.0182,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_183454,1792402519.99663,1792402521.044877,1.0482,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_183454,1792402521.044877,1792402521.064586,0.0197,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402521.064586,1792402521.397739,0.3332,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402521.397739,1792402521.731893,0.3342,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402521.731893,1792402522.063926,0.332,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402522.063926,1792402528.112184,6.0483,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_183454,1792402528.112184,1792402529.160551,1.0484,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_183454,1792402529.160551,1792402529.184317,0.0238,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_183454,1792402529.184317,1792402530.248366,1.064,HOME,home,send,
teach_v1_trim2,run_0001_20261019_183454,1792402530.248366,1792402530.56647,0.3181,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402530.56647,1792402530.889353,0.3229,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402530.889353,1792402531.211175,0.3218,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_183454,1792402531.211175,1792402531.522533,0.3114,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404778.890762,1792404779.962287,1.0715,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_191257,1792404779.962287,1792404780.364555,0.4023,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404780.364555,1792404780.755994,0.3914,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404780.755994,1792404781.148044,0.3921,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404781.148044,1792404781.550027,0.402,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404781.550027,1792404781.946194,0.3962,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404781.946194,1792404782.338241,0.392,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404782.338241,1792404782.736585,0.3983,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404782.736585,1792404783.117993,0.3814,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404783.117993,1792404783.354084,0.2361,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404783.354084,1792404783.374116,0.02,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404783.374116,1792404783.694695,0.3206,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404783.694695,1792404784.016204,0.3215,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404784.016204,1792404784.337869,0.3217,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404784.337869,1792404790.359355,6.0215,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191257,1792404790.359355,1792404791.403988,1.0446,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_191257,1792404791.403988,1792404791.737366,0.3334,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404791.737366,1792404792.069276,0.3319,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404792.069276,1792404792.401813,0.3325,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404792.401813,1792404792.722054,0.3202,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404792.722054,1792404792.735026,0.013,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_191257,1792404792.735026,1792404793.785666,1.0506,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_191257,1792404793.785666,1792404793.805686,0.02,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404793.805686,1792404794.129703,0.324,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404794.129703,1792404794.457662,0.328,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404794.457662,1792404794.781919,0.3243,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404794.781919,1792404796.817869,2.0359,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191257,1792404796.817869,1792404797.902222,1.0844,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_191257,1792404797.902222,1792404798.234119,0.3319,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404798.234119,1792404798.556346,0.3222,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404798.556346,1792404798.877911,0.3216,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404798.877911,1792404799.20978,0.3319,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404799.20978,1792404799.533542,0.3238,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404799.533542,1792404799.554051,0.0205,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_191257,1792404799.554051,1792404800.613462,1.0594,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_191257,1792404800.613462,1792404800.929668,0.3162,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404800.929668,1792404801.251743,0.3221,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404801.251743,1792404801.574,0.3223,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404801.574,1792404801.895868,0.3219,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404801.895868,1792404802.217794,0.3219,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404802.217794,1792404802.54145,0.3237,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404802.54145,1792404802.561812,0.0204,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_191257,1792404802.561812,1792404803.630695,1.0689,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_191257,1792404803.630695,1792404803.652858,0.0222,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404803.652858,1792404803.981375,0.3285,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404803.981375,1792404804.308013,0.3266,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404804.308013,1792404804.624163,0.3161,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404804.624163,1792404810.665497,6.0413,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191257,1792404810.665497,1792404811.713053,1.0476,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_191257,1792404811.713053,1792404811.736946,0.0239,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_191257,1792404811.736946,1792404812.797091,1.0601,HOME,home,send,
teach_v1_trim2,run_0001_20261019_191257,1792404812.797091,1792404813.119216,0.3221,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191257,1792404813.119216,1792404813.440119,0.3209,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404828.788634,1792404829.832885,1.0443,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_191347,1792404829.832885,1792404830.223119,0.3902,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404830.223119,1792404830.615396,0.3923,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404830.615396,1792404831.00874,0.3933,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404831.00874,1792404831.409445,0.4007,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404831.409445,1792404831.801131,0.3917,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404831.801131,1792404832.193204,0.3921,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404832.193204,1792404832.585058,0.3919,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404832.585058,1792404832.985532,0.4005,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404832.985532,1792404833.218036,0.2325,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404833.218036,1792404833.238779,0.0207,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404833.238779,1792404833.564576,0.3258,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404833.564576,1792404833.885898,0.3213,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404833.885898,1792404834.207044,0.3211,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404834.207044,1792404840.238762,6.0317,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191347,1792404840.238762,1792404841.292939,1.0542,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_191347,1792404841.292939,1792404841.614956,0.322,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404841.614956,1792404841.939997,0.325,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404841.939997,1792404842.258961,0.319,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404842.258961,1792404842.581312,0.3224,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404842.581312,1792404842.893169,0.3119,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404842.893169,1792404843.215098,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404843.215098,1792404843.536952,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404843.536952,1792404843.860137,0.3232,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404843.860137,1792404844.180967,0.3208,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404844.180967,1792404844.504144,0.3232,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404844.504144,1792404844.836405,0.3323,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404844.836405,1792404845.168531,0.3321,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404845.168531,1792404845.190353,0.0218,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_191347,1792404845.190353,1792404846.239534,1.0492,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_191347,1792404846.239534,1792404846.259444,0.0199,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404846.259444,1792404846.576921,0.3175,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404846.576921,1792404846.899936,0.323,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404846.899936,1792404847.22363,0.3237,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404847.22363,1792404849.252847,2.0292,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191347,1792404849.252847,1792404850.299547,1.0467,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_191347,1792404850.299547,1792404850.631837,0.3323,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404850.631837,1792404850.962685,0.3308,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404850.962685,1792404851.294509,0.3318,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404851.294509,1792404851.615603,0.3211,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404851.615603,1792404851.936839,0.3212,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404851.936839,1792404851.955404,0.0186,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_191347,1792404851.955404,1792404853.003789,1.0484,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_191347,1792404853.003789,1792404853.326072,0.3223,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404853.326072,1792404853.646847,0.3208,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404853.646847,1792404853.968819,0.322,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404853.968819,1792404854.29233,0.3235,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404854.29233,1792404854.613647,0.3213,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404854.613647,1792404854.924951,0.3113,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404854.924951,1792404854.943344,0.0184,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_191347,1792404854.943344,1792404856.003463,1.0601,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_191347,1792404856.003463,1792404856.023588,0.0201,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404856.023588,1792404856.345609,0.322,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404856.345609,1792404856.678451,0.3328,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404856.678451,1792404857.010316,0.3319,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404857.010316,1792404863.062162,6.0518,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191347,1792404863.062162,1792404864.110987,1.0488,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_191347,1792404864.110987,1792404864.131023,0.02,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_191347,1792404864.131023,1792404865.180498,1.0495,HOME,home,send,
teach_v1_trim2,run_0001_20261019_191347,1792404865.180498,1792404865.503281,0.3228,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404865.503281,1792404865.824647,0.3214,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191347,1792404865.824647,1792404866.138528,0.3139,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404882.470409,1792404883.518824,1.0484,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_191441,1792404883.518824,1792404883.911288,0.3925,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404883.911288,1792404884.302225,0.3909,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404884.302225,1792404884.6939,0.3917,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404884.6939,1792404885.076579,0.3827,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404885.076579,1792404885.468521,0.3919,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404885.468521,1792404885.870698,0.4022,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404885.870698,1792404886.264851,0.3942,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404886.264851,1792404886.66996,0.4051,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404886.66996,1792404886.906974,0.237,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404886.906974,1792404886.919326,0.0124,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404886.919326,1792404887.230178,0.3109,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404887.230178,1792404887.554141,0.324,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404887.554141,1792404887.877995,0.3239,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404887.877995,1792404893.916113,6.0381,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191441,1792404893.916113,1792404894.973732,1.0576,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_191441,1792404894.973732,1792404895.292201,0.3185,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404895.292201,1792404895.613929,0.3217,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404895.613929,1792404895.936711,0.3228,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404895.936711,1792404896.258232,0.3215,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404896.258232,1792404896.580078,0.3218,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404896.580078,1792404896.902239,0.3222,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404896.902239,1792404897.225793,0.3236,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404897.225793,1792404897.546034,0.3202,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404897.546034,1792404897.879534,0.3335,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404897.879534,1792404898.211666,0.3321,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404898.211666,1792404898.544993,0.3333,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404898.544993,1792404898.564822,0.0198,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_191441,1792404898.564822,1792404899.613556,1.0487,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_191441,1792404899.613556,1792404899.933572,0.32,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404899.933572,1792404900.252066,0.3185,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404900.252066,1792404900.573897,0.3218,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404900.573897,1792404900.897676,0.3238,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404900.897676,1792404901.217905,0.3202,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404901.217905,1792404901.5407,0.3228,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404901.5407,1792404901.862405,0.3217,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404901.862405,1792404902.18402,0.3216,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404902.18402,1792404902.509458,0.3254,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404902.509458,1792404902.82957,0.3201,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404902.82957,1792404903.153516,0.3239,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404903.153516,1792404903.471999,0.3185,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404903.471999,1792404903.805377,0.3334,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404903.805377,1792404904.137544,0.3322,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404904.137544,1792404904.45867,0.3211,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404904.45867,1792404904.781403,0.3227,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404904.781403,1792404905.101956,0.3206,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404905.101956,1792404905.121377,0.0194,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404905.121377,1792404905.436608,0.3152,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404905.436608,1792404905.7579,0.3213,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404905.7579,1792404906.081406,0.3235,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404906.081406,1792404906.405344,0.3239,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404906.405344,1792404908.433908,2.0286,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191441,1792404908.433908,1792404909.51636,1.0825,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_191441,1792404909.51636,1792404909.839763,0.3234,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404909.839763,1792404910.165281,0.3255,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404910.165281,1792404910.484354,0.3191,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404910.484354,1792404910.805744,0.3214,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404910.805744,1792404911.128052,0.3223,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404911.128052,1792404911.449763,0.3217,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404911.449763,1792404911.771799,0.322,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404911.771799,1792404912.093752,0.322,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404912.093752,1792404912.417584,0.3238,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404912.417584,1792404912.727736,0.3102,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404912.727736,1792404913.049714,0.322,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404913.049714,1792404913.069229,0.0195,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_191441,1792404913.069229,1792404914.117172,1.0479,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_191441,1792404914.117172,1792404914.437272,0.3201,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404914.437272,1792404914.771129,0.3339,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404914.771129,1792404915.10051,0.3294,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404915.10051,1792404915.423873,0.3234,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404915.423873,1792404915.751132,0.3273,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404915.751132,1792404916.078149,0.327,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404916.078149,1792404916.101173,0.023,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_191441,1792404916.101173,1792404917.153634,1.0525,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_191441,1792404917.153634,1792404917.172929,0.0193,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404917.172929,1792404917.487873,0.3149,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404917.487873,1792404917.809682,0.3218,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404917.809682,1792404918.133022,0.3233,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404918.133022,1792404924.163493,6.0305,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191441,1792404924.163493,1792404925.208298,1.0448,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_191441,1792404925.208298,1792404925.2201,0.0118,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_191441,1792404925.2201,1792404926.26856,1.0485,HOME,home,send,
teach_v1_trim2,run_0001_20261019_191441,1792404926.26856,1792404926.585468,0.3169,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404926.585468,1792404926.908711,0.3232,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191441,1792404926.908711,1792404927.240914,0.3322,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404942.9181,1792404943.963907,1.0458,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_191541,1792404943.963907,1792404944.353787,0.3899,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404944.353787,1792404944.745237,0.3915,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404944.745237,1792404945.146109,0.4009,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404945.146109,1792404945.550862,0.4048,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404945.550862,1792404945.951845,0.401,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404945.951845,1792404946.333283,0.3814,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404946.333283,1792404946.715464,0.3822,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404946.715464,1792404947.10813,0.3927,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404947.10813,1792404947.33582,0.2277,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404947.33582,1792404947.355768,0.0199,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404947.355768,1792404947.675792,0.32,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404947.675792,1792404947.999823,0.324,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404947.999823,1792404948.317162,0.3173,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404948.317162,1792404954.359036,6.0419,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191541,1792404954.359036,1792404955.411415,1.0524,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_191541,1792404955.411415,1792404955.735852,0.3244,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404955.735852,1792404956.059511,0.3237,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404956.059511,1792404956.379039,0.3195,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404956.379039,1792404956.701134,0.3221,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404956.701134,1792404957.034515,0.3334,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404957.034515,1792404957.36573,0.3312,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404957.36573,1792404957.695306,0.3296,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404957.695306,1792404958.019642,0.3243,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404958.019642,1792404958.341034,0.3214,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404958.341034,1792404958.66311,0.3221,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404958.66311,1792404958.987297,0.3242,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404958.987297,1792404959.007303,0.02,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_191541,1792404959.007303,1792404960.067581,1.0603,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_191541,1792404960.067581,1792404960.087283,0.0197,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404960.087283,1792404960.411397,0.3241,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404960.411397,1792404960.727607,0.3162,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404960.727607,1792404961.048766,0.3212,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404961.048766,1792404963.091835,2.0431,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191541,1792404963.091835,1792404964.13484,1.043,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_191541,1792404964.13484,1792404964.45934,0.3245,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404964.45934,1792404964.779923,0.3206,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404964.779923,1792404965.101165,0.3212,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404965.101165,1792404965.423311,0.3221,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404965.423311,1792404965.443153,0.0198,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_191541,1792404965.443153,1792404966.495759,1.0526,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_191541,1792404966.495759,1792404966.811811,0.3161,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404966.811811,1792404967.133071,0.3213,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404967.133071,1792404967.454871,0.3218,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404967.454871,1792404967.779136,0.3243,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404967.779136,1792404968.103071,0.3239,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404968.103071,1792404968.422991,0.3199,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404968.422991,1792404968.44289,0.0199,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_191541,1792404968.44289,1792404969.502391,1.0595,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_191541,1792404969.502391,1792404969.53438,0.032,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404969.53438,1792404969.851263,0.3169,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404969.851263,1792404970.172537,0.3213,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404970.172537,1792404970.495577,0.323,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404970.495577,1792404976.526706,6.0311,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191541,1792404976.526706,1792404977.578711,1.052,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_191541,1792404977.578711,1792404977.598578,0.0199,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_191541,1792404977.598578,1792404978.647089,1.0485,HOME,home,send,
teach_v1_trim2,run_0001_20261019_191541,1792404978.647089,1792404978.968577,0.3215,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191541,1792404978.968577,1792404979.290613,0.322,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792404996.690044,1792404997.741933,1.0519,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_191635,1792404997.741933,1792404998.1379,0.396,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792404998.1379,1792404998.547798,0.4099,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792404998.547798,1792404998.949513,0.4017,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792404998.949513,1792404999.340921,0.3914,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792404999.340921,1792404999.732249,0.3913,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792404999.732249,1792405000.104122,0.3719,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405000.104122,1792405000.501741,0.3976,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405000.501741,1792405000.898225,0.3965,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405000.898225,1792405001.130199,0.232,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405001.130199,1792405001.149729,0.0195,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405001.149729,1792405001.47372,0.324,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405001.47372,1792405001.796057,0.3223,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405001.796057,1792405002.108785,0.3127,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405002.108785,1792405008.150966,6.0422,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191635,1792405008.150966,1792405009.197544,1.0466,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_191635,1792405009.197544,1792405009.517528,0.32,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405009.517528,1792405009.838162,0.3206,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405009.838162,1792405010.168825,0.3307,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405010.168825,1792405010.493694,0.3249,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405010.493694,1792405010.825734,0.332,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405010.825734,1792405011.146718,0.321,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405011.146718,1792405011.458288,0.3116,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405011.458288,1792405011.777392,0.3191,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405011.777392,1792405012.102173,0.3248,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405012.102173,1792405012.424141,0.322,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405012.424141,1792405012.441321,0.0172,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_191635,1792405012.441321,1792405013.489935,1.0486,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_191635,1792405013.489935,1792405013.509117,0.0192,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405013.509117,1792405013.834362,0.3252,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405013.834362,1792405014.156387,0.322,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405014.156387,1792405014.478065,0.3217,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405014.478065,1792405016.52154,2.0435,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191635,1792405016.52154,1792405017.569117,1.0476,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_191635,1792405017.569117,1792405017.892993,0.3239,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405017.892993,1792405018.207937,0.3149,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405018.207937,1792405018.529936,0.322,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405018.529936,1792405018.853174,0.3232,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405018.853174,1792405019.177008,0.3238,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405019.177008,1792405019.495951,0.3189,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405019.495951,1792405019.513091,0.0171,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_191635,1792405019.513091,1792405020.561831,1.0487,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_191635,1792405020.561831,1792405020.885074,0.3232,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405020.885074,1792405021.205893,0.3208,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405021.205893,1792405021.529126,0.3232,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405021.529126,1792405021.858828,0.3297,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405021.858828,1792405022.181888,0.3231,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405022.181888,1792405022.494045,0.3122,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405022.494045,1792405022.513131,0.0191,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_191635,1792405022.513131,1792405023.561087,1.048,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_191635,1792405023.561087,1792405023.580796,0.0197,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405023.580796,1792405023.900717,0.3199,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405023.900717,1792405024.215941,0.3152,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405024.215941,1792405024.54095,0.325,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405024.54095,1792405030.57975,6.0388,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_191635,1792405030.57975,1792405031.624152,1.0444,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_191635,1792405031.624152,1792405031.636189,0.012,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_191635,1792405031.636189,1792405032.688477,1.0523,HOME,home,send,
teach_v1_trim2,run_0001_20261019_191635,1792405032.688477,1792405033.002166,0.3137,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_191635,1792405033.002166,1792405033.3248,0.3226,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405424.521421,1792405425.569231,1.0478,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_192343,1792405425.569231,1792405425.954269,0.385,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405425.954269,1792405426.353264,0.399,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405426.353264,1792405426.748328,0.3951,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405426.748328,1792405427.149416,0.4011,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405427.149416,1792405427.541918,0.3925,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405427.541918,1792405427.943645,0.4017,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405427.943645,1792405428.333177,0.3895,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405428.333177,1792405428.739049,0.4059,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405428.739049,1792405428.978559,0.2395,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405428.978559,1792405428.998133,0.0196,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405428.998133,1792405429.339967,0.3418,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405429.339967,1792405429.666362,0.3264,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405429.666362,1792405429.987564,0.3212,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405429.987564,1792405436.019146,6.0316,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192343,1792405436.019146,1792405437.080796,1.0617,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_192343,1792405437.080796,1792405437.405366,0.3246,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405437.405366,1792405437.728372,0.323,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405437.728372,1792405438.049563,0.3212,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405438.049563,1792405438.372966,0.3234,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405438.372966,1792405438.693639,0.3207,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405438.693639,1792405439.015558,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405439.015558,1792405439.34068,0.3251,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405439.34068,1792405439.664635,0.324,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405439.664635,1792405439.991504,0.3269,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405439.991504,1792405440.316741,0.3252,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405440.316741,1792405440.34549,0.0287,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_192343,1792405440.34549,1792405441.399913,1.0544,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_192343,1792405441.399913,1792405441.415075,0.0152,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405441.415075,1792405441.733216,0.3181,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405441.733216,1792405442.055619,0.3224,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405442.055619,1792405442.380581,0.325,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405442.380581,1792405444.409806,2.0292,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192343,1792405444.409806,1792405445.464483,1.0547,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_192343,1792405445.464483,1792405445.485076,0.0206,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_192343,1792405445.485076,1792405446.570354,1.0853,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_192343,1792405446.570354,1792405446.902791,0.3324,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405446.902791,1792405447.223822,0.321,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405447.223822,1792405447.545278,0.3215,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405447.545278,1792405447.867181,0.3219,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405447.867181,1792405447.888351,0.0212,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_192343,1792405447.888351,1792405448.940233,1.0519,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_192343,1792405448.940233,1792405448.960236,0.02,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405448.960236,1792405449.280219,0.32,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405449.280219,1792405449.5995,0.3193,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405449.5995,1792405449.9242,0.3247,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405449.9242,1792405455.963788,6.0396,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192343,1792405455.963788,1792405457.011995,1.0482,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_192343,1792405457.011995,1792405457.031981,0.02,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_192343,1792405457.031981,1792405458.111902,1.0799,HOME,home,send,
teach_v1_trim2,run_0001_20261019_192343,1792405458.111902,1792405458.435103,0.3232,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192343,1792405458.435103,1792405458.757057,0.322,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405479.223461,1792405480.27119,1.0477,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_192438,1792405480.27119,1792405480.660577,0.3894,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405480.660577,1792405481.04262,0.382,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405481.04262,1792405481.442602,0.4,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405481.442602,1792405481.848626,0.406,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405481.848626,1792405482.255149,0.4065,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405482.255149,1792405482.641532,0.3864,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405482.641532,1792405483.032704,0.3912,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405483.032704,1792405483.434711,0.402,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405483.434711,1792405483.666774,0.2321,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405483.666774,1792405483.686922,0.0201,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405483.686922,1792405484.006995,0.3201,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405484.006995,1792405484.330977,0.324,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405484.330977,1792405484.654928,0.324,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405484.654928,1792405490.696574,6.0416,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192438,1792405490.696574,1792405491.742725,1.0462,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_192438,1792405491.742725,1792405492.062525,0.3198,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405492.062525,1792405492.384447,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405492.384447,1792405492.706923,0.3225,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405492.706923,1792405493.028531,0.3216,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405493.028531,1792405493.361991,0.3335,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405493.361991,1792405493.694226,0.3322,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405493.694226,1792405494.03105,0.3368,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405494.03105,1792405494.347692,0.3166,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405494.347692,1792405494.668693,0.321,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405494.668693,1792405494.991778,0.3231,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405494.991778,1792405495.312479,0.3207,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405495.312479,1792405495.330774,0.0183,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_192438,1792405495.330774,1792405496.390385,1.0596,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_192438,1792405496.390385,1792405496.410401,0.02,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405496.410401,1792405496.72248,0.3121,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405496.72248,1792405497.045111,0.3226,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405497.045111,1792405497.366846,0.3217,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405497.366846,1792405499.408862,2.042,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192438,1792405499.408862,1792405500.458306,1.0494,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_192438,1792405500.458306,1792405500.774393,0.3161,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405500.774393,1792405501.098402,0.324,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405501.098402,1792405501.118373,0.02,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_192438,1792405501.118373,1792405502.170146,1.0518,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_192438,1792405502.170146,1792405502.494667,0.3245,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405502.494667,1792405502.818209,0.3235,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405502.818209,1792405503.138694,0.3205,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405503.138694,1792405503.460377,0.3217,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405503.460377,1792405503.478162,0.0178,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_192438,1792405503.478162,1792405504.526707,1.0485,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_192438,1792405504.526707,1792405504.546172,0.0195,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405504.546172,1792405504.870658,0.3245,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405504.870658,1792405505.191238,0.3206,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405505.191238,1792405505.51591,0.3247,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405505.51591,1792405511.561189,6.0453,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192438,1792405511.561189,1792405512.610305,1.0491,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_192438,1792405512.610305,1792405512.629698,0.0194,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_192438,1792405512.629698,1792405513.677881,1.0482,HOME,home,send,
teach_v1_trim2,run_0001_20261019_192438,1792405513.677881,1792405514.001776,0.3239,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405514.001776,1792405514.330235,0.3285,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192438,1792405514.330235,1792405514.642248,0.312,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405540.990745,1792405542.036733,1.046,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_192539,1792405542.036733,1792405542.43555,0.3988,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405542.43555,1792405542.827948,0.3924,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405542.827948,1792405543.209591,0.3816,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405543.209591,1792405543.601592,0.392,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405543.601592,1792405543.996666,0.3951,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405543.996666,1792405544.386212,0.3895,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405544.386212,1792405544.777751,0.3915,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405544.777751,1792405545.169444,0.3917,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405545.169444,1792405545.396608,0.2272,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405545.396608,1792405545.416597,0.02,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405545.416597,1792405545.740596,0.324,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405545.740596,1792405546.064991,0.3244,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405546.064991,1792405546.389617,0.3246,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405546.389617,1792405552.442137,6.0525,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192539,1792405552.442137,1792405553.485498,1.0434,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_192539,1792405553.485498,1792405553.807419,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405553.807419,1792405554.132359,0.3249,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405554.132359,1792405554.452395,0.32,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405554.452395,1792405554.773197,0.3208,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405554.773197,1792405555.096273,0.3231,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405555.096273,1792405555.417422,0.3211,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405555.417422,1792405555.740522,0.3231,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405555.740522,1792405556.06205,0.3215,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405556.06205,1792405556.383645,0.3216,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405556.383645,1792405556.705488,0.3218,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405556.705488,1792405556.7242,0.0187,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_192539,1792405556.7242,1792405557.802699,1.0785,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_192539,1792405557.802699,1792405557.824762,0.0221,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405557.824762,1792405558.156598,0.3318,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405558.156598,1792405558.489082,0.3325,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405558.489082,1792405558.809593,0.3205,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405558.809593,1792405560.84145,2.0319,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192539,1792405560.84145,1792405561.885966,1.0445,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_192539,1792405561.885966,1792405562.207398,0.3214,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405562.207398,1792405562.529345,0.3219,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405562.529345,1792405562.851308,0.322,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405562.851308,1792405562.867831,0.0165,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_192539,1792405562.867831,1792405563.955923,1.0881,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_192539,1792405563.955923,1792405564.290879,0.335,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405564.290879,1792405564.627174,0.3363,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405564.627174,1792405564.943809,0.3166,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405564.943809,1792405565.265195,0.3214,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405565.265195,1792405565.284007,0.0188,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_192539,1792405565.284007,1792405566.332064,1.0481,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_192539,1792405566.332064,1792405566.35169,0.0196,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405566.35169,1792405566.676233,0.3245,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405566.676233,1792405566.9974,0.3212,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405566.9974,1792405567.319234,0.3218,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405567.319234,1792405573.35115,6.0319,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192539,1792405573.35115,1792405574.403492,1.0523,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_192539,1792405574.403492,1792405574.423461,0.02,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_192539,1792405574.423461,1792405575.471663,1.0482,HOME,home,send,
teach_v1_trim2,run_0001_20261019_192539,1792405575.471663,1792405575.804546,0.3329,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405575.804546,1792405576.136676,0.3321,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192539,1792405576.136676,1792405576.470022,0.3333,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405594.747511,1792405595.794651,1.0471,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_192633,1792405595.794651,1792405596.190736,0.3961,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405596.190736,1792405596.582617,0.3919,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405596.582617,1792405596.974662,0.392,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405596.974662,1792405597.367071,0.3924,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405597.367071,1792405597.759378,0.3923,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405597.759378,1792405598.150737,0.3914,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405598.150737,1792405598.551488,0.4008,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405598.551488,1792405598.956103,0.4046,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405598.956103,1792405599.185426,0.2293,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405599.185426,1792405599.207364,0.0219,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405599.207364,1792405599.537317,0.33,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405599.537317,1792405599.864218,0.3269,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405599.864218,1792405600.185262,0.321,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405600.185262,1792405606.21705,6.0318,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192633,1792405606.21705,1792405607.262238,1.0452,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_192633,1792405607.262238,1792405607.586217,0.324,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405607.586217,1792405607.904517,0.3183,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405607.904517,1792405608.226166,0.3216,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405608.226166,1792405608.548536,0.3224,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405608.548536,1792405608.870737,0.3222,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405608.870737,1792405609.182888,0.3122,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405609.182888,1792405609.494527,0.3116,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405609.494527,1792405609.816472,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405609.816472,1792405610.128375,0.3119,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405610.128375,1792405610.450689,0.3223,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405610.450689,1792405610.470005,0.0193,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_192633,1792405610.470005,1792405611.547975,1.078,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_192633,1792405611.547975,1792405611.561765,0.0138,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405611.561765,1792405611.881136,0.3194,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405611.881136,1792405612.202581,0.3214,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405612.202581,1792405612.524666,0.3221,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405612.524666,1792405614.556441,2.0318,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192633,1792405614.556441,1792405615.600268,1.0438,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_192633,1792405615.600268,1792405615.922787,0.3225,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405615.922787,1792405616.244147,0.3214,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405616.244147,1792405616.57247,0.3283,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405616.57247,1792405616.59702,0.0245,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_192633,1792405616.59702,1792405617.683586,1.0866,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_192633,1792405617.683586,1792405618.005251,0.3217,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405618.005251,1792405618.326213,0.321,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405618.326213,1792405618.648376,0.3222,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405618.648376,1792405618.973833,0.3255,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405618.973833,1792405618.993775,0.0199,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_192633,1792405618.993775,1792405620.041853,1.0481,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_192633,1792405620.041853,1792405620.061706,0.0199,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405620.061706,1792405620.380215,0.3185,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405620.380215,1792405620.692612,0.3124,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405620.692612,1792405621.014245,0.3216,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405621.014245,1792405627.046152,6.0319,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_192633,1792405627.046152,1792405628.106787,1.0606,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_192633,1792405628.106787,1792405628.122988,0.0162,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_192633,1792405628.122988,1792405629.191276,1.0683,HOME,home,send,
teach_v1_trim2,run_0001_20261019_192633,1792405629.191276,1792405629.523497,0.3322,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_192633,1792405629.523497,1792405629.840745,0.3172,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406045.321464,1792406046.373593,1.0521,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_193404,1792406046.373593,1792406046.781771,0.4082,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406046.781771,1792406047.186509,0.4047,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406047.186509,1792406047.588675,0.4022,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406047.588675,1792406047.97961,0.3909,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406047.97961,1792406048.371611,0.392,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406048.371611,1792406048.762971,0.3914,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406048.762971,1792406049.154583,0.3916,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406049.154583,1792406049.549492,0.3949,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406049.549492,1792406049.778922,0.2294,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406049.778922,1792406049.797388,0.0185,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406049.797388,1792406050.113115,0.3157,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406050.113115,1792406050.43495,0.3218,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406050.43495,1792406050.753316,0.3184,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406050.753316,1792406056.788972,6.0357,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193404,1792406056.788972,1792406057.83702,1.048,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_193404,1792406057.83702,1792406058.15482,0.3178,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406058.15482,1792406058.473308,0.3185,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406058.473308,1792406058.798885,0.3256,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406058.798885,1792406059.132436,0.3336,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406059.132436,1792406059.464453,0.332,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406059.464453,1792406059.789266,0.3248,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406059.789266,1792406060.107678,0.3184,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406060.107678,1792406060.42879,0.3211,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406060.42879,1792406060.750941,0.3222,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406060.750941,1792406061.073306,0.3224,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406061.073306,1792406061.392867,0.3196,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406061.392867,1792406061.71674,0.3239,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406061.71674,1792406061.736864,0.0201,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_193404,1792406061.736864,1792406062.783593,1.0467,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_193404,1792406062.783593,1792406062.795678,0.0121,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406062.795678,1792406063.117321,0.3216,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406063.117321,1792406063.438792,0.3215,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406063.438792,1792406063.760698,0.3219,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406063.760698,1792406065.797692,2.037,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193404,1792406065.797692,1792406066.846549,1.0489,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_193404,1792406066.846549,1792406067.158621,0.3121,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406067.158621,1792406067.48057,0.3219,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406067.48057,1792406067.504762,0.0242,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_193404,1792406067.504762,1792406068.552633,1.0479,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_193404,1792406068.552633,1792406068.869043,0.3164,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406068.869043,1792406069.190712,0.3217,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406069.190712,1792406069.512461,0.3217,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406069.512461,1792406069.836652,0.3242,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406069.836652,1792406070.160533,0.3239,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406070.160533,1792406070.478774,0.3182,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406070.478774,1792406070.800712,0.3219,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406070.800712,1792406071.134364,0.3337,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406071.134364,1792406071.162581,0.0282,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_193404,1792406071.162581,1792406072.208602,1.046,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_193404,1792406072.208602,1792406072.228358,0.0198,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406072.228358,1792406072.552993,0.3246,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406072.552993,1792406072.87658,0.3236,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406072.87658,1792406073.200389,0.3238,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406073.200389,1792406079.23839,6.038,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193404,1792406079.23839,1792406080.284131,1.0457,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_193404,1792406080.284131,1792406080.304257,0.0201,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_193404,1792406080.304257,1792406081.348222,1.044,HOME,home,send,
teach_v1_trim2,run_0001_20261019_193404,1792406081.348222,1792406081.670445,0.3222,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406081.670445,1792406081.996114,0.3257,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193404,1792406081.996114,1792406082.32007,0.324,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406100.45307,1792406101.496078,1.043,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_193459,1792406101.496078,1792406101.88811,0.392,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406101.88811,1792406102.287305,0.3992,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406102.287305,1792406102.682124,0.3948,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406102.682124,1792406103.07407,0.3919,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406103.07407,1792406103.466203,0.3921,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406103.466203,1792406103.857876,0.3917,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406103.857876,1792406104.250834,0.393,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406104.250834,1792406104.632018,0.3812,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406104.632018,1792406104.866112,0.2341,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406104.866112,1792406104.887414,0.0213,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406104.887414,1792406105.211158,0.3237,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406105.211158,1792406105.52994,0.3188,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406105.52994,1792406105.852118,0.3222,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406105.852118,1792406111.884461,6.0323,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193459,1792406111.884461,1792406112.956553,1.0721,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_193459,1792406112.956553,1792406113.280593,0.324,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406113.280593,1792406113.591916,0.3113,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406113.591916,1792406113.903904,0.312,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406113.903904,1792406114.226966,0.3231,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406114.226966,1792406114.547918,0.321,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406114.547918,1792406114.866891,0.319,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406114.866891,1792406115.190769,0.3239,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406115.190769,1792406115.503953,0.3132,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406115.503953,1792406115.825898,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406115.825898,1792406116.148395,0.3225,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406116.148395,1792406116.459729,0.3113,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406116.459729,1792406116.781879,0.3221,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406116.781879,1792406117.10684,0.325,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406117.10684,1792406117.126957,0.0201,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_193459,1792406117.126957,1792406118.19862,1.0717,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_193459,1792406118.19862,1792406118.220545,0.0219,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406118.220545,1792406118.555533,0.335,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406118.555533,1792406118.88189,0.3264,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406118.88189,1792406119.19837,0.3165,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406119.19837,1792406121.229585,2.0312,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193459,1792406121.229585,1792406122.278401,1.0488,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_193459,1792406122.278401,1792406122.298465,0.0201,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_193459,1792406122.298465,1792406123.358488,1.06,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_193459,1792406123.358488,1792406123.682778,0.3243,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406123.682778,1792406124.012658,0.3299,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406124.012658,1792406124.34738,0.3347,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406124.34738,1792406124.679383,0.332,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406124.679383,1792406124.999979,0.3206,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406124.999979,1792406125.321825,0.3218,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406125.321825,1792406125.643645,0.3218,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406125.643645,1792406125.965778,0.3221,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406125.965778,1792406125.982357,0.0166,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_193459,1792406125.982357,1792406127.042769,1.0604,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_193459,1792406127.042769,1792406127.062277,0.0195,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406127.062277,1792406127.385552,0.3233,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406127.385552,1792406127.708263,0.3227,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406127.708263,1792406128.030114,0.3219,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406128.030114,1792406134.061574,6.0315,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193459,1792406134.061574,1792406135.125354,1.0638,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_193459,1792406135.125354,1792406135.142068,0.0167,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_193459,1792406135.142068,1792406136.206701,1.0646,HOME,home,send,
teach_v1_trim2,run_0001_20261019_193459,1792406136.206701,1792406136.544921,0.3382,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406136.544921,1792406136.866151,0.3212,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193459,1792406136.866151,1792406137.177553,0.3114,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406178.645274,1792406179.700084,1.0548,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_193617,1792406179.700084,1792406180.090706,0.3906,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406180.090706,1792406180.492802,0.4021,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406180.492802,1792406180.885556,0.3928,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406180.885556,1792406181.286828,0.4013,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406181.286828,1792406181.67865,0.3918,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406181.67865,1792406182.072344,0.3937,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406182.072344,1792406182.464231,0.3919,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406182.464231,1792406182.875419,0.4112,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406182.875419,1792406183.107372,0.232,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406183.107372,1792406183.128575,0.0212,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406183.128575,1792406183.450764,0.3222,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406183.450764,1792406183.773526,0.3228,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406183.773526,1792406184.095172,0.3216,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406184.095172,1792406190.126424,6.0313,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193617,1792406190.126424,1792406191.171997,1.0456,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_193617,1792406191.171997,1792406191.492606,0.3206,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406191.492606,1792406191.815936,0.3233,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406191.815936,1792406192.136605,0.3207,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406192.136605,1792406192.459038,0.3224,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406192.459038,1792406192.780994,0.322,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406192.780994,1792406193.102792,0.3218,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406193.102792,1792406193.424724,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406193.424724,1792406193.748091,0.3234,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406193.748091,1792406194.068397,0.3203,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406194.068397,1792406194.399239,0.3308,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406194.399239,1792406194.734107,0.3349,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406194.734107,1792406195.066019,0.3319,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406195.066019,1792406195.397251,0.3312,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406195.397251,1792406195.419269,0.022,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_193617,1792406195.419269,1792406196.471903,1.0526,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_193617,1792406196.471903,1792406196.49175,0.0198,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406196.49175,1792406196.815642,0.3239,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406196.815642,1792406197.135738,0.3201,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406197.135738,1792406197.455665,0.3199,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406197.455665,1792406199.492524,2.0369,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193617,1792406199.492524,1792406200.575277,1.0828,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_193617,1792406200.575277,1792406200.589652,0.0144,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_193617,1792406200.589652,1792406201.633448,1.0438,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_193617,1792406201.633448,1792406201.954554,0.3211,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406201.954554,1792406202.279555,0.325,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406202.279555,1792406202.603489,0.3239,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406202.603489,1792406202.923499,0.32,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406202.923499,1792406203.247547,0.324,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406203.247547,1792406203.571478,0.3239,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406203.571478,1792406203.88644,0.315,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406203.88644,1792406204.208839,0.3224,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406204.208839,1792406204.220245,0.0114,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_193617,1792406204.220245,1792406205.267425,1.0472,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_193617,1792406205.267425,1792406205.28759,0.0202,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406205.28759,1792406205.616053,0.3285,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406205.616053,1792406205.940517,0.3245,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406205.940517,1792406206.263621,0.3231,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406206.263621,1792406212.313116,6.0495,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193617,1792406212.313116,1792406213.358731,1.0456,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_193617,1792406213.358731,1792406213.372383,0.0137,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_193617,1792406213.372383,1792406214.419051,1.0467,HOME,home,send,
teach_v1_trim2,run_0001_20261019_193617,1792406214.419051,1792406214.738982,0.3199,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406214.738982,1792406215.06299,0.324,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193617,1792406215.06299,1792406215.382987,0.32,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406306.115126,1792406307.196273,1.0811,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_193825,1792406307.196273,1792406307.587437,0.3912,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406307.587437,1792406307.979584,0.3921,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406307.979584,1792406308.370722,0.3911,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406308.370722,1792406308.763736,0.393,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406308.763736,1792406309.154787,0.3911,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406309.154787,1792406309.546479,0.3917,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406309.546479,1792406309.938599,0.3921,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406309.938599,1792406310.33077,0.3922,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406310.33077,1792406310.563278,0.2325,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406310.563278,1792406310.578136,0.0149,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406310.578136,1792406310.896464,0.3183,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406310.896464,1792406311.21979,0.3233,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406311.21979,1792406311.540483,0.3207,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406311.540483,1792406317.57278,6.0323,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193825,1792406317.57278,1792406318.657662,1.0849,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_193825,1792406318.657662,1792406318.989718,0.3321,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406318.989718,1792406319.309916,0.3202,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406319.309916,1792406319.632372,0.3225,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406319.632372,1792406319.955329,0.323,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406319.955329,1792406320.277092,0.3218,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406320.277092,1792406320.598396,0.3213,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406320.598396,1792406320.923095,0.3247,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406320.923095,1792406321.243143,0.32,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406321.243143,1792406321.564408,0.3213,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406321.564408,1792406321.886383,0.322,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406321.886383,1792406322.208465,0.3221,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406322.208465,1792406322.530434,0.322,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406322.530434,1792406322.550979,0.0205,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_193825,1792406322.550979,1792406323.59896,1.048,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_193825,1792406323.59896,1792406323.919101,0.3201,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406323.919101,1792406324.251217,0.3321,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406324.251217,1792406324.573933,0.3227,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406324.573933,1792406324.905988,0.3321,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406324.905988,1792406325.237798,0.3318,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406325.237798,1792406325.570086,0.3323,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406325.570086,1792406325.900482,0.3304,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406325.900482,1792406326.223071,0.3226,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406326.223071,1792406326.544374,0.3213,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406326.544374,1792406326.56275,0.0184,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406326.56275,1792406326.882963,0.3202,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406326.882963,1792406327.206736,0.3238,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406327.206736,1792406327.522496,0.3158,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406327.522496,1792406329.554531,2.032,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193825,1792406329.554531,1792406330.614687,1.0602,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_193825,1792406330.614687,1792406330.938573,0.3239,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406330.938573,1792406331.265707,0.3271,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406331.265707,1792406331.584242,0.3185,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406331.584242,1792406331.906582,0.3223,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406331.906582,1792406332.228152,0.3216,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406332.228152,1792406332.550181,0.322,APPROACH_PICK_LIFT,carry_lift,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406332.550181,1792406332.570679,0.0205,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_193825,1792406332.570679,1792406333.618696,1.048,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_193825,1792406333.618696,1792406333.942515,0.3238,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406333.942515,1792406334.26013,0.3176,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406334.26013,1792406334.582023,0.3219,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406334.582023,1792406334.904526,0.3225,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406334.904526,1792406335.226041,0.3215,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406335.226041,1792406335.548067,0.322,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406335.548067,1792406335.870164,0.3221,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406335.870164,1792406336.191978,0.3218,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406336.191978,1792406336.210286,0.0183,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_193825,1792406336.210286,1792406337.287984,1.0777,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_193825,1792406337.287984,1792406337.306311,0.0183,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406337.306311,1792406337.625351,0.319,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406337.625351,1792406337.944555,0.3192,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406337.944555,1792406338.256179,0.3116,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406338.256179,1792406344.287962,6.0318,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193825,1792406344.287962,1792406345.345972,1.058,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_193825,1792406345.345972,1792406345.365972,0.02,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_193825,1792406345.365972,1792406346.413944,1.048,HOME,home,send,
teach_v1_trim2,run_0001_20261019_193825,1792406346.413944,1792406346.730608,0.3167,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406346.730608,1792406347.052077,0.3215,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193825,1792406347.052077,1792406347.374012,0.3219,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406373.745189,1792406374.792942,1.0478,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_193932,1792406374.792942,1792406375.192899,0.4,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406375.192899,1792406375.579456,0.3866,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406375.579456,1792406375.972151,0.3927,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406375.972151,1792406376.363507,0.3914,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406376.363507,1792406376.75532,0.3918,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406376.75532,1792406377.152809,0.3975,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406377.152809,1792406377.549898,0.3971,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406377.549898,1792406377.940789,0.3909,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406377.940789,1792406378.184775,0.244,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406378.184775,1792406378.2069,0.0221,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406378.2069,1792406378.54076,0.3339,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406378.54076,1792406378.859903,0.3191,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406378.859903,1792406379.182569,0.3227,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406379.182569,1792406385.213694,6.0311,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193932,1792406385.213694,1792406386.272487,1.0588,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_193932,1792406386.272487,1792406386.596521,0.324,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406386.596521,1792406386.91121,0.3147,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406386.91121,1792406387.223094,0.3119,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406387.223094,1792406387.544449,0.3214,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406387.544449,1792406387.867442,0.323,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406387.867442,1792406388.189312,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406388.189312,1792406388.501323,0.312,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406388.501323,1792406388.823146,0.3218,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406388.823146,1792406389.1452,0.3221,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406389.1452,1792406389.468493,0.3233,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406389.468493,1792406389.797039,0.3285,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406389.797039,1792406390.133063,0.336,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406390.133063,1792406390.154627,0.0216,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_193932,1792406390.154627,1792406391.200335,1.0457,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_193932,1792406391.200335,1792406391.220295,0.02,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406391.220295,1792406391.541114,0.3208,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406391.541114,1792406391.864389,0.3233,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406391.864389,1792406392.188352,0.324,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406392.188352,1792406394.217268,2.0289,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193932,1792406394.217268,1792406395.26411,1.0468,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_193932,1792406395.26411,1792406395.284344,0.0202,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_193932,1792406395.284344,1792406396.36242,1.0781,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_193932,1792406396.36242,1792406396.679814,0.3174,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406396.679814,1792406397.001152,0.3213,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406397.001152,1792406397.323058,0.3219,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406397.323058,1792406397.644963,0.3219,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406397.644963,1792406397.964018,0.3191,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406397.964018,1792406398.288049,0.324,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406398.288049,1792406398.608108,0.3201,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406398.608108,1792406398.923247,0.3151,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406398.923247,1792406398.94413,0.0209,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_193932,1792406398.94413,1792406399.989064,1.0449,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_193932,1792406399.989064,1792406400.008155,0.0191,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406400.008155,1792406400.323009,0.3149,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406400.323009,1792406400.647933,0.3249,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406400.647933,1792406400.971945,0.324,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406400.971945,1792406406.998873,6.0269,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_193932,1792406406.998873,1792406408.074345,1.0755,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_193932,1792406408.074345,1792406408.096786,0.0224,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_193932,1792406408.096786,1792406409.143556,1.0468,HOME,home,send,
teach_v1_trim2,run_0001_20261019_193932,1792406409.143556,1792406409.46094,0.3174,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406409.46094,1792406409.783917,0.323,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_193932,1792406409.783917,1792406410.104831,0.3209,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406899.793666,1792406900.84083,1.0472,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_194818,1792406900.84083,1792406901.238544,0.3977,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406901.238544,1792406901.630541,0.392,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406901.630541,1792406902.032444,0.4019,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406902.032444,1792406902.434362,0.4019,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406902.434362,1792406902.837882,0.4035,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406902.837882,1792406903.239766,0.4019,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406903.239766,1792406903.641819,0.4021,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406903.641819,1792406904.033045,0.3912,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406904.033045,1792406904.264434,0.2314,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406904.264434,1792406904.286371,0.0219,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406904.286371,1792406904.608321,0.3219,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406904.608321,1792406904.932538,0.3242,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406904.932538,1792406905.574334,0.6418,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406905.574334,1792406911.616263,6.0419,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_194818,1792406911.616263,1792406912.67061,1.0543,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_194818,1792406912.67061,1792406912.992137,0.3215,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406912.992137,1792406913.314192,0.3221,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406913.314192,1792406913.625906,0.3117,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406913.625906,1792406913.956301,0.3304,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406913.956301,1792406914.280606,0.3243,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406914.280606,1792406914.602109,0.3215,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406914.602109,1792406914.935483,0.3334,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406914.935483,1792406915.266652,0.3312,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406915.266652,1792406915.592884,0.3262,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406915.592884,1792406915.911437,0.3186,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406915.911437,1792406915.923114,0.0117,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_194818,1792406915.923114,1792406916.976516,1.0534,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_194818,1792406916.976516,1792406916.996083,0.0196,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406916.996083,1792406917.320625,0.3245,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406917.320625,1792406917.644104,0.3235,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406917.644104,1792406917.963988,0.3199,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406917.963988,1792406920.006137,2.0421,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_194818,1792406920.006137,1792406921.087255,1.0811,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_194818,1792406921.087255,1792406921.105788,0.0185,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_194818,1792406921.105788,1792406922.156401,1.0506,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_194818,1792406922.156401,1792406922.477937,0.3215,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406922.477937,1792406922.495897,0.018,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_194818,1792406922.495897,1792406923.551945,1.056,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_194818,1792406923.551945,1792406923.571832,0.0199,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406923.571832,1792406923.888,0.3162,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406923.888,1792406924.211817,0.3238,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406924.211817,1792406924.533308,0.3215,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406924.533308,1792406930.564585,6.0313,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_194818,1792406930.564585,1792406931.615479,1.0509,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_194818,1792406931.615479,1792406931.635423,0.0199,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_194818,1792406931.635423,1792406932.713961,1.0785,HOME,home,send,
teach_v1_trim2,run_0001_20261019_194818,1792406932.713961,1792406933.039774,0.3258,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406933.039774,1792406933.358514,0.3187,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_194818,1792406933.358514,1792406933.679896,0.3214,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406954.198115,1792406955.251479,1.0534,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_194913,1792406955.251479,1792406955.643509,0.392,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406955.643509,1792406956.04692,0.4034,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406956.04692,1792406956.448997,0.4021,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406956.448997,1792406956.847696,0.3987,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406956.847696,1792406957.241885,0.3942,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406957.241885,1792406957.623458,0.3816,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406957.623458,1792406958.015367,0.3919,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406958.015367,1792406958.414514,0.3991,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406958.414514,1792406958.649389,0.2349,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406958.649389,1792406958.666618,0.0172,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406958.666618,1792406958.990516,0.3239,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406958.990516,1792406959.305415,0.3149,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406959.305415,1792406959.627366,0.322,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406959.627366,1792406965.669764,6.0424,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_194913,1792406965.669764,1792406966.718291,1.0485,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_194913,1792406966.718291,1792406967.042153,0.3239,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406967.042153,1792406967.366217,0.3241,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406967.366217,1792406967.689382,0.3232,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406967.689382,1792406968.022802,0.3334,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406968.022802,1792406968.354744,0.3319,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406968.354744,1792406968.675527,0.3208,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406968.675527,1792406968.997941,0.3224,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406968.997941,1792406969.319373,0.3214,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406969.319373,1792406969.641098,0.3217,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406969.641098,1792406969.963306,0.3222,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406969.963306,1792406969.982011,0.0187,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_194913,1792406969.982011,1792406971.039051,1.057,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_194913,1792406971.039051,1792406971.058029,0.019,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406971.058029,1792406971.373016,0.315,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406971.373016,1792406971.695789,0.3228,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406971.695789,1792406972.017168,0.3214,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406972.017168,1792406974.039117,2.0219,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_194913,1792406974.039117,1792406975.08585,1.0467,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_194913,1792406975.08585,1792406975.106183,0.0203,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_194913,1792406975.106183,1792406976.149136,1.043,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_194913,1792406976.149136,1792406976.461027,0.3119,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406976.461027,1792406976.477768,0.0167,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_194913,1792406976.477768,1792406977.527234,1.0495,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_194913,1792406977.527234,1792406977.53959,0.0124,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406977.53959,1792406977.861317,0.3217,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406977.861317,1792406978.183146,0.3218,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406978.183146,1792406978.505038,0.3219,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406978.505038,1792406984.546991,6.042,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_194913,1792406984.546991,1792406985.622293,1.0753,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_194913,1792406985.622293,1792406985.644409,0.0221,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_194913,1792406985.644409,1792406986.693456,1.049,HOME,home,send,
teach_v1_trim2,run_0001_20261019_194913,1792406986.693456,1792406987.00885,0.3154,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406987.00885,1792406987.333903,0.3251,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_194913,1792406987.333903,1792406987.652893,0.319,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407024.436688,1792407025.484511,1.0478,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_195023,1792407025.484511,1792407025.883868,0.3994,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407025.883868,1792407026.279628,0.3958,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407026.279628,1792407026.68164,0.402,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407026.68164,1792407027.085152,0.4035,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407027.085152,1792407027.484353,0.3992,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407027.484353,1792407027.876548,0.3922,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407027.876548,1792407028.268289,0.3917,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407028.268289,1792407028.650135,0.3818,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407028.650135,1792407028.883768,0.2336,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407028.883768,1792407028.903758,0.02,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407028.903758,1792407029.226162,0.3224,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407029.226162,1792407029.547913,0.3218,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407029.547913,1792407029.871998,0.3241,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407029.871998,1792407035.902514,6.0305,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_195023,1792407035.902514,1792407036.947558,1.045,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_195023,1792407036.947558,1792407037.257995,0.3104,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407037.257995,1792407037.579464,0.3215,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407037.579464,1792407037.89953,0.3201,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407037.89953,1792407038.21943,0.3199,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407038.21943,1792407038.544291,0.3249,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407038.544291,1792407038.869226,0.3249,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407038.869226,1792407039.227945,0.3587,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407039.227945,1792407039.552365,0.3244,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407039.552365,1792407039.874173,0.3218,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407039.874173,1792407039.891347,0.0172,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_195023,1792407039.891347,1792407040.949919,1.0586,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_195023,1792407040.949919,1792407040.967361,0.0174,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407040.967361,1792407041.291288,0.3239,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407041.291288,1792407041.605993,0.3147,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407041.605993,1792407041.928007,0.322,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407041.928007,1792407043.959963,2.032,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_195023,1792407043.959963,1792407045.045312,1.0853,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_195023,1792407045.045312,1792407045.067813,0.0225,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_195023,1792407045.067813,1792407046.119897,1.0521,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_195023,1792407046.119897,1792407046.443377,0.3235,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407046.443377,1792407046.463192,0.0198,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_195023,1792407046.463192,1792407047.523104,1.0599,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_195023,1792407047.523104,1792407047.543534,0.0204,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407047.543534,1792407047.861935,0.3184,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407047.861935,1792407048.184415,0.3225,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407048.184415,1792407048.506442,0.322,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407048.506442,1792407054.537604,6.0312,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_195023,1792407054.537604,1792407055.594851,1.0572,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_195023,1792407055.594851,1792407055.614878,0.02,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_195023,1792407055.614878,1792407056.699049,1.0842,HOME,home,send,
teach_v1_trim2,run_0001_20261019_195023,1792407056.699049,1792407057.020248,0.3212,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407057.020248,1792407057.342459,0.3222,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_195023,1792407057.342459,1792407057.66389,0.3214,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407081.193858,1792407082.253842,1.06,HOME_START,home,send,
teach_v1_trim2,run_0001_20261019_195120,1792407082.253842,1792407082.637564,0.3837,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407082.637564,1792407083.033695,0.3961,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407083.033695,1792407083.391822,0.3581,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407083.391822,1792407083.784035,0.3922,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407083.784035,1792407084.175289,0.3913,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407084.175289,1792407084.567388,0.3921,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407084.567388,1792407084.965675,0.3983,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407084.965675,1792407085.355115,0.3894,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407085.355115,1792407085.637694,0.2826,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407085.637694,1792407085.657626,0.0199,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407085.657626,1792407085.98866,0.331,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407085.98866,1792407086.320669,0.332,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407086.320669,1792407086.64161,0.3209,HOME_START,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407086.64161,1792407092.683464,6.0419,HOME_START,home,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_195120,1792407092.683464,1792407093.727059,1.0436,APPROACH_PICK,approach,send,
teach_v1_trim2,run_0001_20261019_195120,1792407093.727059,1792407094.045684,0.3186,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407094.045684,1792407094.361143,0.3155,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407094.361143,1792407094.684259,0.3231,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407094.684259,1792407095.005044,0.3208,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407095.005044,1792407095.327204,0.3222,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407095.327204,1792407095.649555,0.3224,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407095.649555,1792407095.971165,0.3216,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407095.971165,1792407096.293109,0.3219,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407096.293109,1792407096.617241,0.3241,APPROACH_PICK,approach,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407096.617241,1792407096.637246,0.02,APPROACH_PICK,approach,stage_change,stage
teach_v1_trim2,run_0001_20261019_195120,1792407096.637246,1792407097.712303,1.0751,PICK,grasp,send,
teach_v1_trim2,run_0001_20261019_195120,1792407097.712303,1792407097.734448,0.0221,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407097.734448,1792407098.066475,0.332,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407098.066475,1792407098.396647,0.3302,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407098.396647,1792407098.719469,0.3228,PICK,grasp,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407098.719469,1792407100.751066,2.0316,PICK,grasp,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_195120,1792407100.751066,1792407101.796933,1.0459,APPROACH_PICK_LIFT,carry_lift,send,
teach_v1_trim2,run_0001_20261019_195120,1792407101.796933,1792407101.816995,0.0201,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_v1_trim2,run_0001_20261019_195120,1792407101.816995,1792407102.871528,1.0545,APPROACH_PLACE,carry,send,
teach_v1_trim2,run_0001_20261019_195120,1792407102.871528,1792407103.192983,0.3215,APPROACH_PLACE,carry,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407103.192983,1792407103.213004,0.02,APPROACH_PLACE,carry,stage_change,stage
teach_v1_trim2,run_0001_20261019_195120,1792407103.213004,1792407104.296878,1.0839,PLACE,release,send,
teach_v1_trim2,run_0001_20261019_195120,1792407104.296878,1792407104.311391,0.0145,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407104.311391,1792407104.622878,0.3115,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407104.622878,1792407104.944894,0.322,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407104.944894,1792407105.267005,0.3221,PLACE,release,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407105.267005,1792407111.308759,6.0418,PLACE,release,gripper,gripper_cmd;stage
teach_v1_trim2,run_0001_20261019_195120,1792407111.308759,1792407112.368589,1.0598,APPROACH_PLACE_RETREAT,retreat,send,
teach_v1_trim2,run_0001_20261019_195120,1792407112.368589,1792407112.388512,0.0199,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_v1_trim2,run_0001_20261019_195120,1792407112.388512,1792407113.439515,1.051,HOME,home,send,
teach_v1_trim2,run_0001_20261019_195120,1792407113.439515,1792407113.760713,0.3212,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407113.760713,1792407114.082901,0.3222,HOME,home,poll,
teach_v1_trim2,run_0001_20261019_195120,1792407114.082901,1792407114.404711,0.3218,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185320.088553,1794185321.152368,1.0638,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185321.152368,1794185321.552762,0.4004,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185321.552762,1794185321.944748,0.392,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185321.944748,1794185322.332736,0.388,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185322.332736,1794185322.732733,0.4,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185322.732733,1794185323.122708,0.39,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185323.122708,1794185323.522756,0.4,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185323.522756,1794185323.922608,0.3999,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185323.922608,1794185324.32885,0.4062,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185324.32885,1794185324.57409,0.2452,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185324.57409,1794185324.606028,0.0319,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185324.606028,1794185324.927159,0.3211,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185324.927159,1794185325.253727,0.3266,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185325.253727,1794185325.572954,0.3192,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185325.572954,1794185331.615005,6.0421,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185331.615005,1794185332.679141,1.0641,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185332.679141,1794185333.004846,0.3257,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185333.004846,1794185333.325063,0.3202,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185333.325063,1794185333.648695,0.3236,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185333.648695,1794185333.975428,0.3267,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185333.975428,1794185334.294943,0.3195,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185334.294943,1794185334.620311,0.3254,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185334.620311,1794185334.940348,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185334.940348,1794185335.264842,0.3245,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185335.264842,1794185335.584997,0.3202,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185335.584997,1794185335.915443,0.3304,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185335.915443,1794185336.246387,0.3309,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185336.246387,1794185336.577321,0.3309,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185336.577321,1794185336.895567,0.3182,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185336.895567,1794185336.917624,0.0221,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185336.917624,1794185337.968309,1.0507,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185337.968309,1794185337.988317,0.02,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185337.988317,1794185338.312179,0.3239,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185338.312179,1794185338.632271,0.3201,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185338.632271,1794185338.957064,0.3248,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185338.957064,1794185340.988871,2.0318,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185340.988871,1794185342.049801,1.0609,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185342.049801,1794185342.071793,0.022,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185342.071793,1794185343.120449,1.0487,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185343.120449,1794185343.441097,0.3206,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185343.441097,1794185343.764713,0.3236,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185343.764713,1794185344.088371,0.3237,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185344.088371,1794185344.41255,0.3242,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185344.41255,1794185344.736282,0.3237,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185344.736282,1794185345.05121,0.3149,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185345.05121,1794185345.072234,0.021,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185345.072234,1794185346.120405,1.0482,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185346.120405,1794185346.444479,0.3241,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185346.444479,1794185346.768331,0.3239,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185346.768331,1794185347.088405,0.3201,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185347.088405,1794185347.413261,0.3249,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185347.413261,1794185347.744692,0.3314,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185347.744692,1794185347.776672,0.032,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185347.776672,1794185348.09337,0.3167,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185348.09337,1794185348.414174,0.3208,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185348.414174,1794185348.733701,0.3195,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185348.733701,1794185354.775573,6.0419,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185354.775573,1794185355.836396,1.0608,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185355.836396,1794185355.856262,0.0199,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185355.856262,1794185356.905534,1.0493,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185356.905534,1794185357.217807,0.3123,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185357.217807,1794185357.538117,0.3203,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185357.538117,1794185357.864431,0.3263,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185357.864431,1794185358.187891,0.3235,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_094839,1794185358.187891,1794185358.512276,0.3244,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185589.265655,1794185590.317652,1.052,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185590.317652,1794185590.707899,0.3902,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185590.707899,1794185591.107959,0.4001,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185591.107959,1794185591.497952,0.39,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185591.497952,1794185591.890336,0.3924,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185591.890336,1794185592.287951,0.3976,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185592.287951,1794185592.674337,0.3864,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185592.674337,1794185593.068461,0.3941,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185593.068461,1794185593.45888,0.3904,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185593.45888,1794185593.690071,0.2312,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185593.690071,1794185593.710173,0.0201,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185593.710173,1794185594.034218,0.324,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185594.034218,1794185594.358439,0.3242,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185594.358439,1794185594.682164,0.3237,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185594.682164,1794185600.730025,6.0479,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185600.730025,1794185601.774906,1.0449,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185601.774906,1794185602.090155,0.3152,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185602.090155,1794185602.410222,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185602.410222,1794185602.734148,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185602.734148,1794185603.0544,0.3203,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185603.0544,1794185603.378239,0.3238,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185603.378239,1794185603.700537,0.3223,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185603.700537,1794185604.020081,0.3195,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185604.020081,1794185604.342378,0.3223,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185604.342378,1794185604.660908,0.3185,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185604.660908,1794185604.980469,0.3196,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185604.980469,1794185605.302227,0.3218,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185605.302227,1794185605.626249,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185605.626249,1794185605.646204,0.02,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185605.646204,1794185606.712914,1.0667,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185606.712914,1794185606.73487,0.022,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185606.73487,1794185607.052464,0.3176,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185607.052464,1794185607.374265,0.3218,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185607.374265,1794185607.692901,0.3186,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185607.692901,1794185609.724357,2.0315,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185609.724357,1794185610.779043,1.0547,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185610.779043,1794185610.790469,0.0114,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185610.790469,1794185611.86318,1.0727,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185611.86318,1794185612.182376,0.3192,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185612.182376,1794185612.506751,0.3244,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185612.506751,1794185612.826542,0.3198,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185612.826542,1794185613.146688,0.3201,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185613.146688,1794185613.466948,0.3203,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185613.466948,1794185613.786879,0.3199,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185613.786879,1794185613.807091,0.0202,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185613.807091,1794185614.854434,1.0473,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185614.854434,1794185615.179413,0.325,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185615.179413,1794185615.502205,0.3228,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185615.502205,1794185615.828606,0.3264,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185615.828606,1794185616.148163,0.3196,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185616.148163,1794185616.458915,0.3108,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185616.458915,1794185616.4711,0.0122,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185616.4711,1794185616.788567,0.3175,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185616.788567,1794185617.115265,0.3267,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185617.115265,1794185617.449668,0.3344,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185617.449668,1794185623.490801,6.0411,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185623.490801,1794185624.564119,1.0733,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185624.564119,1794185624.58063,0.0165,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185624.58063,1794185625.626344,1.0457,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185625.626344,1794185625.951862,0.3255,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185625.951862,1794185626.272907,0.321,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095308,1794185626.272907,1794185626.594398,0.3215,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185891.734041,1794185892.779997,1.046,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185892.779997,1794185893.163932,0.3839,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185893.163932,1794185893.55367,0.3897,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185893.55367,1794185893.947999,0.3943,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185893.947999,1794185894.339902,0.3919,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185894.339902,1794185894.735978,0.3961,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185894.735978,1794185895.130317,0.3943,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185895.130317,1794185895.525144,0.3948,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185895.525144,1794185895.923692,0.3985,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185895.923692,1794185896.154061,0.2304,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185896.154061,1794185896.166361,0.0123,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185896.166361,1794185896.484437,0.3181,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185896.484437,1794185896.807907,0.3235,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185896.807907,1794185897.127921,0.32,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185897.127921,1794185903.166081,6.0382,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185903.166081,1794185904.224407,1.0583,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185904.224407,1794185904.54819,0.3238,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185904.54819,1794185904.866541,0.3184,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185904.866541,1794185905.186176,0.3196,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185905.186176,1794185905.508032,0.3219,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185905.508032,1794185905.828094,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185905.828094,1794185906.152043,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185906.152043,1794185906.471888,0.3198,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185906.471888,1794185906.786119,0.3142,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185906.786119,1794185907.117389,0.3313,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185907.117389,1794185907.446714,0.3293,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185907.446714,1794185907.76646,0.3197,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185907.76646,1794185907.778518,0.0121,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185907.778518,1794185908.822124,1.0436,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185908.822124,1794185908.840078,0.018,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185908.840078,1794185909.160002,0.3199,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185909.160002,1794185909.484042,0.324,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185909.484042,1794185909.808492,0.3245,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185909.808492,1794185911.840197,2.0317,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185911.840197,1794185912.910947,1.0707,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185912.910947,1794185912.928742,0.0178,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185912.928742,1794185913.970167,1.0414,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185913.970167,1794185914.282151,0.312,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185914.282151,1794185914.600114,0.318,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185914.600114,1794185914.922431,0.3223,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185914.922431,1794185915.244037,0.3216,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185915.244037,1794185915.56406,0.32,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185915.56406,1794185915.888098,0.324,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185915.888098,1794185915.908017,0.0199,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185915.908017,1794185916.9585,1.0505,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185916.9585,1794185917.280385,0.3219,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185917.280385,1794185917.604652,0.3243,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185917.604652,1794185917.930025,0.3254,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185917.930025,1794185918.261156,0.3311,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185918.261156,1794185918.59318,0.332,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185918.59318,1794185918.615719,0.0225,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185918.615719,1794185918.934264,0.3185,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185918.934264,1794185919.256127,0.3219,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185919.256127,1794185919.574619,0.3185,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185919.574619,1794185925.617278,6.0427,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185925.617278,1794185926.660588,1.0433,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185926.660588,1794185926.68023,0.0196,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185926.68023,1794185927.728199,1.048,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185927.728199,1794185928.052287,0.3241,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185928.052287,1794185928.369379,0.3171,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185928.369379,1794185928.688729,0.3194,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095810,1794185928.688729,1794185929.012553,0.3238,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185989.538345,1794185990.588534,1.0502,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185990.588534,1794185990.982456,0.3939,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185990.982456,1794185991.376546,0.3941,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185991.376546,1794185991.772898,0.3964,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185991.772898,1794185992.160587,0.3877,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185992.160587,1794185992.549371,0.3888,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185992.549371,1794185992.942418,0.393,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185992.942418,1794185993.322861,0.3804,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185993.322861,1794185993.720488,0.3976,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185993.720488,1794185993.952232,0.2317,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185993.952232,1794185993.975568,0.0233,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185993.975568,1794185994.303763,0.3282,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185994.303763,1794185994.633702,0.3299,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185994.633702,1794185994.956273,0.3226,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794185994.956273,1794186000.995121,6.0388,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186000.995121,1794186002.03907,1.0439,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186002.03907,1794186002.354853,0.3158,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186002.354853,1794186002.676609,0.3218,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186002.676609,1794186002.99662,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186002.99662,1794186003.320647,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186003.320647,1794186003.640558,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186003.640558,1794186003.965117,0.3246,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186003.965117,1794186004.28865,0.3235,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186004.28865,1794186004.612592,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186004.612592,1794186004.935091,0.3225,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186004.935091,1794186005.255178,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186005.255178,1794186005.576702,0.3215,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186005.576702,1794186005.900567,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186005.900567,1794186005.9205,0.0199,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186005.9205,1794186006.985932,1.0654,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186006.985932,1794186007.009282,0.0234,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186007.009282,1794186007.338303,0.329,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186007.338303,1794186007.667981,0.3297,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186007.667981,1794186007.987494,0.3195,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186007.987494,1794186010.018686,2.0312,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186010.018686,1794186011.063747,1.0451,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186011.063747,1794186011.07536,0.0116,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186011.07536,1794186012.118646,1.0433,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186012.118646,1794186012.441099,0.3225,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186012.441099,1794186012.761072,0.32,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186012.761072,1794186013.089486,0.3284,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186013.089486,1794186013.415919,0.3264,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186013.415919,1794186013.750729,0.3348,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186013.750729,1794186014.071474,0.3207,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186014.071474,1794186014.08349,0.012,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186014.08349,1794186015.132571,1.0491,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186015.132571,1794186015.454273,0.3217,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186015.454273,1794186015.776614,0.3223,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186015.776614,1794186016.100726,0.3241,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186016.100726,1794186016.420657,0.3199,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186016.420657,1794186016.743393,0.3227,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186016.743393,1794186016.75883,0.0154,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186016.75883,1794186017.086271,0.3274,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186017.086271,1794186017.403616,0.3173,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186017.403616,1794186017.728752,0.3251,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186017.728752,1794186023.765107,6.0364,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186023.765107,1794186024.838025,1.0729,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186024.838025,1794186024.85986,0.0218,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186024.85986,1794186025.915617,1.0558,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186025.915617,1794186026.240674,0.3251,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186026.240674,1794186026.564771,0.3241,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186026.564771,1794186026.88884,0.3241,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186026.88884,1794186027.212699,0.3239,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_095948,1794186027.212699,1794186027.53679,0.3241,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186087.737117,1794186088.797099,1.06,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186088.797099,1794186089.191249,0.3941,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186089.191249,1794186089.593611,0.4024,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186089.593611,1794186090.002162,0.4086,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186090.002162,1794186090.401358,0.3992,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186090.401358,1794186090.790776,0.3894,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186090.790776,1794186091.170864,0.3801,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186091.170864,1794186091.565211,0.3943,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186091.565211,1794186091.960957,0.3957,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186091.960957,1794186092.201222,0.2403,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186092.201222,1794186092.221093,0.0199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186092.221093,1794186092.545035,0.3239,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186092.545035,1794186092.869233,0.3242,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186092.869233,1794186093.193314,0.3241,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186093.193314,1794186099.234323,6.041,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186099.234323,1794186100.285255,1.0509,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186100.285255,1794186100.60527,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186100.60527,1794186100.925175,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186100.925175,1794186101.257489,0.3323,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186101.257489,1794186101.573084,0.3156,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186101.573084,1794186101.897262,0.3242,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186101.897262,1794186102.213847,0.3166,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186102.213847,1794186102.533116,0.3193,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186102.533116,1794186102.857219,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186102.857219,1794186103.181227,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186103.181227,1794186103.503181,0.322,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186103.503181,1794186103.825136,0.322,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186103.825136,1794186104.149315,0.3242,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186104.149315,1794186104.169255,0.0199,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186104.169255,1794186105.221236,1.052,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186105.221236,1794186105.231797,0.0106,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186105.231797,1794186105.55526,0.3235,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186105.55526,1794186105.87724,0.322,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186105.87724,1794186106.197307,0.3201,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186106.197307,1794186108.227793,2.0305,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186108.227793,1794186109.271329,1.0435,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186109.271329,1794186109.289139,0.0178,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186109.289139,1794186110.337269,1.0481,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186110.337269,1794186110.657355,0.3201,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186110.657355,1794186110.970032,0.3127,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186110.970032,1794186111.289378,0.3193,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186111.289378,1794186111.60908,0.3197,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186111.60908,1794186111.933312,0.3242,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186111.933312,1794186112.258385,0.3251,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186112.258385,1794186112.278459,0.0201,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186112.278459,1794186113.35167,1.0732,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186113.35167,1794186113.675404,0.3237,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186113.675404,1794186113.993232,0.3178,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186113.993232,1794186114.311375,0.3181,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186114.311375,1794186114.631418,0.32,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186114.631418,1794186114.953295,0.3219,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186114.953295,1794186114.973315,0.02,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186114.973315,1794186115.297311,0.324,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186115.297311,1794186115.617321,0.32,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186115.617321,1794186115.93731,0.32,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186115.93731,1794186121.973639,6.0363,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186121.973639,1794186123.028303,1.0547,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186123.028303,1794186123.040021,0.0117,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186123.040021,1794186124.085406,1.0454,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186124.085406,1794186124.406016,0.3206,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186124.406016,1794186124.725749,0.3197,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186124.725749,1794186125.05767,0.3319,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100126,1794186125.05767,1794186125.382419,0.3247,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186188.771545,1794186189.833597,1.0621,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186189.833597,1794186190.230881,0.3973,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186190.230881,1794186190.609279,0.3784,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186190.609279,1794186191.001737,0.3925,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186191.001737,1794186191.389364,0.3876,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186191.389364,1794186191.785858,0.3965,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186191.785858,1794186192.181756,0.3959,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186192.181756,1794186192.581708,0.4,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186192.581708,1794186192.977731,0.396,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186192.977731,1794186193.210328,0.2326,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186193.210328,1794186193.233245,0.0229,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186193.233245,1794186193.550429,0.3172,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186193.550429,1794186193.873776,0.3233,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186193.873776,1794186194.197812,0.324,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186194.197812,1794186200.231676,6.0339,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186200.231676,1794186201.307126,1.0754,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186201.307126,1794186201.632612,0.3255,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186201.632612,1794186201.958008,0.3254,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186201.958008,1794186202.282351,0.3243,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186202.282351,1794186202.605854,0.3235,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186202.605854,1794186202.926274,0.3204,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186202.926274,1794186203.245832,0.3196,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186203.245832,1794186203.569772,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186203.569772,1794186203.893883,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186203.893883,1794186204.217863,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186204.217863,1794186204.541901,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186204.541901,1794186204.865724,0.3238,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186204.865724,1794186205.18256,0.3168,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186205.18256,1794186205.19388,0.0113,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186205.19388,1794186206.245899,1.052,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186206.245899,1794186206.265803,0.0199,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186206.265803,1794186206.595399,0.3296,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186206.595399,1794186206.925104,0.3297,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186206.925104,1794186207.255446,0.3303,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186207.255446,1794186209.275926,2.0205,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186209.275926,1794186210.322431,1.0465,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186210.322431,1794186210.341798,0.0194,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186210.341798,1794186211.394004,1.0522,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186211.394004,1794186211.718431,0.3244,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186211.718431,1794186212.037998,0.3196,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186212.037998,1794186212.36204,0.324,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186212.36204,1794186212.685916,0.3239,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186212.685916,1794186213.019525,0.3336,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186213.019525,1794186213.349221,0.3297,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186213.349221,1794186213.370736,0.0215,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186213.370736,1794186214.423978,1.0532,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186214.423978,1794186214.745892,0.3219,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186214.745892,1794186214.765985,0.0201,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186214.765985,1794186215.085934,0.3199,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186215.085934,1794186215.410933,0.325,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186215.410933,1794186215.730022,0.3191,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186215.730022,1794186221.762132,6.0321,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186221.762132,1794186222.808107,1.046,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186222.808107,1794186222.818373,0.0103,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186222.818373,1794186223.870005,1.0516,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186223.870005,1794186224.184589,0.3146,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186224.184589,1794186224.505941,0.3214,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186224.505941,1794186224.838177,0.3322,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100307,1794186224.838177,1794186225.164766,0.3266,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186285.993128,1794186287.050658,1.0575,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186287.050658,1794186287.442294,0.3916,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186287.442294,1794186287.835979,0.3937,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186287.835979,1794186288.230208,0.3942,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186288.230208,1794186288.626434,0.3962,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186288.626434,1794186289.02647,0.4,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186289.02647,1794186289.422327,0.3959,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186289.422327,1794186289.823701,0.4014,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186289.823701,1794186290.214878,0.3912,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186290.214878,1794186290.450398,0.2355,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186290.450398,1794186290.470461,0.0201,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186290.470461,1794186290.785684,0.3152,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186290.785684,1794186291.104978,0.3193,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186291.104978,1794186291.426491,0.3215,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186291.426491,1794186297.46741,6.0409,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186297.46741,1794186298.51446,1.047,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186298.51446,1794186298.837187,0.3227,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186298.837187,1794186299.157361,0.3202,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186299.157361,1794186299.477988,0.3206,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186299.477988,1794186299.79725,0.3193,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186299.79725,1794186300.118416,0.3212,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186300.118416,1794186300.442361,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186300.442361,1794186300.766449,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186300.766449,1794186301.090434,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186301.090434,1794186301.414402,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186301.414402,1794186301.749054,0.3347,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186301.749054,1794186302.078697,0.3296,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186302.078697,1794186302.10066,0.022,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186302.10066,1794186303.146327,1.0457,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186303.146327,1794186303.166577,0.0203,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186303.166577,1794186303.490618,0.324,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186303.490618,1794186303.810558,0.3199,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186303.810558,1794186304.134416,0.3239,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186304.134416,1794186306.1715,2.0371,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186306.1715,1794186307.215349,1.0438,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186307.215349,1794186307.234458,0.0191,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186307.234458,1794186308.282045,1.0476,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186308.282045,1794186308.60445,0.3224,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186308.60445,1794186308.926385,0.3219,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186308.926385,1794186309.243616,0.3172,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186309.243616,1794186309.566462,0.3228,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186309.566462,1794186309.890619,0.3242,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186309.890619,1794186310.214933,0.3243,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186310.214933,1794186310.234567,0.0196,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186310.234567,1794186311.280119,1.0456,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186311.280119,1794186311.595516,0.3154,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186311.595516,1794186311.915665,0.3201,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186311.915665,1794186312.234529,0.3189,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186312.234529,1794186312.555572,0.321,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186312.555572,1794186312.87852,0.3229,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186312.87852,1794186312.898816,0.0203,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186312.898816,1794186313.221133,0.3223,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186313.221133,1794186313.544299,0.3232,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186313.544299,1794186313.877111,0.3328,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186313.877111,1794186314.19594,0.3188,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186314.19594,1794186320.238739,6.0428,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186320.238739,1794186321.28173,1.043,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186321.28173,1794186321.298488,0.0168,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186321.298488,1794186322.358865,1.0604,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186322.358865,1794186322.67993,0.3211,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186322.67993,1794186323.000461,0.3205,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186323.000461,1794186323.321447,0.321,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100444,1794186323.321447,1794186323.642646,0.3212,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186437.966887,1794186439.014719,1.0478,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186439.014719,1794186439.414552,0.3998,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186439.414552,1794186439.815362,0.4008,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186439.815362,1794186440.214975,0.3996,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186440.214975,1794186440.615636,0.4007,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186440.615636,1794186441.006265,0.3906,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186441.006265,1794186441.405053,0.3988,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186441.405053,1794186441.807304,0.4023,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186441.807304,1794186442.20727,0.4,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186442.20727,1794186442.439281,0.232,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186442.439281,1794186442.459215,0.0199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186442.459215,1794186442.78181,0.3226,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186442.78181,1794186443.113756,0.3319,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186443.113756,1794186443.441762,0.328,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186443.441762,1794186449.507893,6.0661,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186449.507893,1794186450.563338,1.0554,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186450.563338,1794186450.887695,0.3244,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186450.887695,1794186451.211407,0.3237,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186451.211407,1794186451.539328,0.3279,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186451.539328,1794186451.863403,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186451.863403,1794186452.18335,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186452.18335,1794186452.507663,0.3243,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186452.507663,1794186452.82765,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186452.82765,1794186453.147334,0.3197,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186453.147334,1794186453.471274,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186453.471274,1794186453.795317,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186453.795317,1794186454.119258,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186454.119258,1794186454.143408,0.0242,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186454.143408,1794186455.224616,1.0812,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186455.224616,1794186455.256868,0.0323,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186455.256868,1794186455.579559,0.3227,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186455.579559,1794186455.899469,0.3199,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186455.899469,1794186456.219882,0.3204,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186456.219882,1794186458.26143,2.0415,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186458.26143,1794186459.307524,1.0461,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186459.307524,1794186459.327803,0.0203,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186459.327803,1794186460.400143,1.0723,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186460.400143,1794186460.723747,0.3236,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186460.723747,1794186461.04339,0.3196,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186461.04339,1794186461.364202,0.3208,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186461.364202,1794186461.683578,0.3194,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186461.683578,1794186462.007589,0.324,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186462.007589,1794186462.327449,0.3199,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186462.327449,1794186462.347658,0.0202,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186462.347658,1794186463.395346,1.0477,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186463.395346,1794186463.715664,0.3203,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186463.715664,1794186463.735371,0.0197,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186463.735371,1794186464.05571,0.3203,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186464.05571,1794186464.376248,0.3205,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186464.376248,1794186464.695561,0.3193,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186464.695561,1794186470.727759,6.0322,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186470.727759,1794186471.779473,1.0517,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186471.779473,1794186471.799379,0.0199,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186471.799379,1794186472.879556,1.0802,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186472.879556,1794186473.200637,0.3211,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186473.200637,1794186473.519772,0.3191,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186473.519772,1794186473.839776,0.32,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186473.839776,1794186474.159795,0.32,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_100716,1794186474.159795,1794186474.487494,0.3277,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186719.070147,1794186720.120957,1.0508,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186720.120957,1794186720.520297,0.3993,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186720.520297,1794186720.910287,0.39,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186720.910287,1794186721.305,0.3947,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186721.305,1794186721.710151,0.4052,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186721.710151,1794186722.110289,0.4001,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186722.110289,1794186722.500449,0.3902,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186722.500449,1794186722.900344,0.3999,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186722.900344,1794186723.291021,0.3907,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186723.291021,1794186723.52039,0.2294,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186723.52039,1794186723.537066,0.0167,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186723.537066,1794186723.850419,0.3134,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186723.850419,1794186724.17031,0.3199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186724.17031,1794186724.492936,0.3226,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186724.492936,1794186730.532445,6.0395,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186730.532445,1794186731.617855,1.0854,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186731.617855,1794186731.933097,0.3152,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186731.933097,1794186732.252606,0.3195,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186732.252606,1794186732.57699,0.3244,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186732.57699,1794186732.893239,0.3162,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186732.893239,1794186733.217181,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186733.217181,1794186733.541094,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186733.541094,1794186733.865024,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186733.865024,1794186734.189055,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186734.189055,1794186734.513349,0.3243,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186734.513349,1794186734.83338,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186734.83338,1794186735.153429,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186735.153429,1794186735.477113,0.3237,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186735.477113,1794186735.497611,0.0205,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186735.497611,1794186736.557018,1.0594,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186736.557018,1794186736.576958,0.0199,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186736.576958,1794186736.906332,0.3294,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186736.906332,1794186737.236257,0.3299,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186737.236257,1794186737.566381,0.3301,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186737.566381,1794186739.586767,2.0204,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186739.586767,1794186740.64146,1.0547,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186740.64146,1794186740.653356,0.0119,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186740.653356,1794186741.7052,1.0518,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186741.7052,1794186742.029007,0.3238,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186742.029007,1794186742.35314,0.3241,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186742.35314,1794186742.677072,0.3239,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186742.677072,1794186743.01018,0.3331,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186743.01018,1794186743.340614,0.3304,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186743.340614,1794186743.659039,0.3184,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186743.659039,1794186743.671895,0.0129,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186743.671895,1794186744.717206,1.0453,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186744.717206,1794186745.041581,0.3244,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186745.041581,1794186745.360937,0.3194,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186745.360937,1794186745.6851,0.3242,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186745.6851,1794186746.00085,0.3157,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186746.00085,1794186746.325103,0.3243,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186746.325103,1794186746.345309,0.0202,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186746.345309,1794186746.660895,0.3156,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186746.660895,1794186746.980987,0.3201,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186746.980987,1794186747.300963,0.32,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186747.300963,1794186753.323155,6.0222,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186753.323155,1794186754.377477,1.0543,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186754.377477,1794186754.39777,0.0203,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186754.39777,1794186755.463894,1.0661,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186755.463894,1794186755.785772,0.3219,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186755.785772,1794186756.105147,0.3194,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186756.105147,1794186756.429213,0.3241,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186756.429213,1794186756.753337,0.3241,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_101157,1794186756.753337,1794186757.077316,0.324,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187270.961106,1794187272.0129,1.0518,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187272.0129,1794187272.412636,0.3997,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187272.412636,1794187272.80273,0.3901,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187272.80273,1794187273.192716,0.39,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187273.192716,1794187273.604376,0.4117,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187273.604376,1794187273.993386,0.389,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187273.993386,1794187274.383209,0.3898,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187274.383209,1794187274.776331,0.3931,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187274.776331,1794187275.168391,0.3921,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187275.168391,1794187275.400414,0.232,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187275.400414,1794187275.420288,0.0199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187275.420288,1794187275.744471,0.3242,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187275.744471,1794187276.063811,0.3193,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187276.063811,1794187276.388643,0.3248,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187276.388643,1794187282.41507,6.0264,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187282.41507,1794187283.464601,1.0495,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187283.464601,1794187283.788488,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187283.788488,1794187284.105232,0.3167,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187284.105232,1794187284.428517,0.3233,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187284.428517,1794187284.752465,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187284.752465,1794187285.083853,0.3314,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187285.083853,1794187285.416701,0.3328,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187285.416701,1794187285.754689,0.338,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187285.754689,1794187286.078571,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187286.078571,1794187286.395266,0.3167,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187286.395266,1794187286.720513,0.3252,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187286.720513,1794187287.045118,0.3246,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187287.045118,1794187287.068869,0.0238,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187287.068869,1794187288.132294,1.0634,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187288.132294,1794187288.154057,0.0218,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187288.154057,1794187288.477147,0.3231,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187288.477147,1794187288.797679,0.3205,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187288.797679,1794187289.117905,0.3202,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187289.117905,1794187291.161119,2.0432,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187291.161119,1794187292.208755,1.0476,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187292.208755,1794187292.536465,0.3277,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187292.536465,1794187292.860806,0.3243,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187292.860806,1794187293.189351,0.3285,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187293.189351,1794187293.509399,0.32,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187293.509399,1794187293.532742,0.0233,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187293.532742,1794187294.580415,1.0477,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187294.580415,1794187294.902273,0.3219,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187294.902273,1794187295.224625,0.3224,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187295.224625,1794187295.548559,0.3239,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187295.548559,1794187295.872697,0.3241,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187295.872697,1794187296.196585,0.3239,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187296.196585,1794187296.521359,0.3248,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187296.521359,1794187296.540483,0.0191,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187296.540483,1794187297.629862,1.0894,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187297.629862,1794187297.651553,0.0217,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187297.651553,1794187297.96512,0.3136,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187297.96512,1794187298.283576,0.3185,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187298.283576,1794187298.608448,0.3249,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187298.608448,1794187304.645783,6.0373,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187304.645783,1794187305.708569,1.0628,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187305.708569,1794187305.732907,0.0243,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187305.732907,1794187306.790707,1.0578,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187306.790707,1794187307.107712,0.317,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102109,1794187307.107712,1794187307.432759,0.325,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187369.449624,1794187370.497212,1.0476,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187370.497212,1794187370.891342,0.3941,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187370.891342,1794187371.291605,0.4003,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187371.291605,1794187371.682166,0.3906,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187371.682166,1794187372.071569,0.3894,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187372.071569,1794187372.461524,0.39,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187372.461524,1794187372.841363,0.3798,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187372.841363,1794187373.231442,0.3901,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187373.231442,1794187373.63287,0.4014,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187373.63287,1794187373.872761,0.2399,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187373.872761,1794187373.894952,0.0222,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187373.894952,1794187374.21163,0.3167,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187374.21163,1794187374.532389,0.3208,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187374.532389,1794187374.851446,0.3191,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187374.851446,1794187380.893825,6.0424,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187380.893825,1794187381.952986,1.0592,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187381.952986,1794187382.274687,0.3217,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187382.274687,1794187382.593747,0.3191,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187382.593747,1794187382.917165,0.3234,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187382.917165,1794187383.234465,0.3173,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187383.234465,1794187383.553719,0.3193,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187383.553719,1794187383.877134,0.3234,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187383.877134,1794187384.201054,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187384.201054,1794187384.525382,0.3243,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187384.525382,1794187384.849069,0.3237,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187384.849069,1794187385.179522,0.3305,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187385.179522,1794187385.515212,0.3357,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187385.515212,1794187385.84527,0.3301,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187385.84527,1794187385.867224,0.022,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187385.867224,1794187386.913046,1.0458,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187386.913046,1794187386.933247,0.0202,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187386.933247,1794187387.253053,0.3198,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187387.253053,1794187387.577306,0.3243,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187387.577306,1794187387.90129,0.324,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187387.90129,1794187389.938137,2.0368,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187389.938137,1794187390.984983,1.0468,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187390.984983,1794187391.319415,0.3344,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187391.319415,1794187391.649556,0.3301,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187391.649556,1794187391.968391,0.3188,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187391.968391,1794187392.288828,0.3204,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187392.288828,1794187392.608034,0.3192,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187392.608034,1794187392.625053,0.017,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187392.625053,1794187393.684154,1.0591,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187393.684154,1794187394.009179,0.325,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187394.009179,1794187394.333328,0.3241,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187394.333328,1794187394.650074,0.3167,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187394.650074,1794187394.970798,0.3207,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187394.970798,1794187395.290098,0.3193,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187395.290098,1794187395.610189,0.3201,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187395.610189,1794187395.629255,0.0191,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187395.629255,1794187396.677397,1.0481,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187396.677397,1794187396.697132,0.0197,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187396.697132,1794187397.027502,0.3304,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187397.027502,1794187397.363602,0.3361,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187397.363602,1794187397.693574,0.33,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187397.693574,1794187403.73686,6.0433,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187403.73686,1794187404.778379,1.0415,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187404.778379,1794187404.797164,0.0188,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187404.797164,1794187405.854322,1.0572,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187405.854322,1794187406.176483,0.3222,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102248,1794187406.176483,1794187406.501205,0.3247,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187472.806418,1794187473.891522,1.0851,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187473.891522,1794187474.280894,0.3894,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187474.280894,1794187474.670283,0.3894,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187474.670283,1794187475.065747,0.3955,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187475.065747,1794187475.460232,0.3945,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187475.460232,1794187475.857528,0.3973,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187475.857528,1794187476.245663,0.3881,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187476.245663,1794187476.640119,0.3945,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187476.640119,1794187477.041769,0.4016,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187477.041769,1794187477.270771,0.229,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187477.270771,1794187477.282256,0.0115,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187477.282256,1794187477.600288,0.318,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187477.600288,1794187477.921703,0.3214,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187477.921703,1794187478.241769,0.3201,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187478.241769,1794187484.282621,6.0409,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187484.282621,1794187485.367875,1.0853,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187485.367875,1794187485.682672,0.3148,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187485.682672,1794187486.002952,0.3203,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187486.002952,1794187486.323012,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187486.323012,1794187486.642437,0.3194,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187486.642437,1794187486.965889,0.3235,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187486.965889,1794187487.289788,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187487.289788,1794187487.613853,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187487.613853,1794187487.937723,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187487.937723,1794187488.257856,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187488.257856,1794187488.577717,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187488.577717,1794187488.893416,0.3157,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187488.893416,1794187489.213161,0.3197,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187489.213161,1794187489.224847,0.0117,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187489.224847,1794187490.278603,1.0538,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187490.278603,1794187490.297743,0.0191,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187490.297743,1794187490.62335,0.3256,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187490.62335,1794187490.945889,0.3225,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187490.945889,1794187491.265925,0.32,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187491.265925,1794187493.296766,2.0308,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187493.296766,1794187494.342096,1.0453,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187494.342096,1794187494.665903,0.3238,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187494.665903,1794187494.98737,0.3215,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187494.98737,1794187495.306787,0.3194,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187495.306787,1794187495.626648,0.3199,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187495.626648,1794187495.957827,0.3312,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187495.957827,1794187496.280631,0.3228,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187496.280631,1794187496.302516,0.0219,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187496.302516,1794187497.349773,1.0473,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187497.349773,1794187497.67454,0.3248,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187497.67454,1794187497.999387,0.3248,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187497.999387,1794187498.318863,0.3195,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187498.318863,1794187498.641722,0.3229,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187498.641722,1794187498.958959,0.3172,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187498.958959,1794187499.28182,0.3229,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187499.28182,1794187499.302065,0.0202,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187499.302065,1794187500.361823,1.0598,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187500.361823,1794187500.381925,0.0201,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187500.381925,1794187500.701642,0.3197,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187500.701642,1794187501.021562,0.3199,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187501.021562,1794187501.340905,0.3193,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187501.340905,1794187507.372667,6.0318,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187507.372667,1794187508.445796,1.0731,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187508.445796,1794187508.470781,0.025,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187508.470781,1794187509.523726,1.0529,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187509.523726,1794187509.845552,0.3218,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_102431,1794187509.845552,1794187510.166214,0.3207,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187850.225862,1794187851.268798,1.0429,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187851.268798,1794187851.658332,0.3895,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187851.658332,1794187852.060156,0.4018,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187852.060156,1794187852.456054,0.3959,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187852.456054,1794187852.848293,0.3922,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187852.848293,1794187853.238402,0.3901,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187853.238402,1794187853.6384,0.4,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187853.6384,1794187854.032061,0.3937,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187854.032061,1794187854.419071,0.387,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187854.419071,1794187854.648414,0.2293,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187854.648414,1794187854.667977,0.0196,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187854.667977,1794187854.988544,0.3206,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187854.988544,1794187855.308461,0.3199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187855.308461,1794187855.628392,0.3199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187855.628392,1794187861.661252,6.0329,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187861.661252,1794187862.745889,1.0846,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187862.745889,1794187863.07182,0.3259,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187863.07182,1794187863.390678,0.3189,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187863.390678,1794187863.710736,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187863.710736,1794187864.032236,0.3215,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187864.032236,1794187864.356065,0.3238,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187864.356065,1794187864.680619,0.3246,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187864.680619,1794187865.004052,0.3234,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187865.004052,1794187865.324113,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187865.324113,1794187865.648047,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187865.648047,1794187865.971367,0.3233,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187865.971367,1794187866.290986,0.3196,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187866.290986,1794187866.302614,0.0116,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187866.302614,1794187867.360112,1.0575,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187867.360112,1794187867.380238,0.0201,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187867.380238,1794187867.704246,0.324,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187867.704246,1794187868.03412,0.3299,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187868.03412,1794187868.364068,0.3299,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187868.364068,1794187870.384832,2.0208,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187870.384832,1794187871.4323,1.0475,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187871.4323,1794187871.4523,0.02,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187871.4523,1794187872.500276,1.048,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187872.500276,1794187872.824201,0.3239,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187872.824201,1794187873.146761,0.3226,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187873.146761,1794187873.468193,0.3214,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187873.468193,1794187873.7884,0.3202,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187873.7884,1794187874.118337,0.3299,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187874.118337,1794187874.448159,0.3298,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187874.448159,1794187874.470076,0.0219,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187874.470076,1794187875.516201,1.0461,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187875.516201,1794187875.840394,0.3242,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187875.840394,1794187876.164261,0.3239,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187876.164261,1794187876.488221,0.324,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187876.488221,1794187876.812141,0.3239,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187876.812141,1794187877.128875,0.3167,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187877.128875,1794187877.148515,0.0196,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187877.148515,1794187877.472246,0.3237,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187877.472246,1794187877.789478,0.3172,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187877.789478,1794187878.109448,0.32,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187878.109448,1794187884.141715,6.0323,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187884.141715,1794187885.213949,1.0722,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187885.213949,1794187885.235482,0.0215,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187885.235482,1794187886.301218,1.0657,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187886.301218,1794187886.623813,0.3226,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187886.623813,1794187886.943279,0.3195,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187886.943279,1794187887.268327,0.325,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187887.268327,1794187887.592254,0.3239,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103049,1794187887.592254,1794187887.916314,0.3241,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188285.283223,1794188286.332546,1.0493,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188286.332546,1794188286.736347,0.4038,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188286.736347,1794188287.124557,0.3882,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188287.124557,1794188287.508608,0.3841,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188287.508608,1794188287.90451,0.3959,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188287.90451,1794188288.300774,0.3963,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188288.300774,1794188288.692479,0.3917,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188288.692479,1794188289.075557,0.3831,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188289.075557,1794188289.467192,0.3916,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188289.467192,1794188289.695834,0.2286,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188289.695834,1794188289.708066,0.0122,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188289.708066,1794188290.025703,0.3176,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188290.025703,1794188290.348606,0.3229,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188290.348606,1794188290.672467,0.3239,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188290.672467,1794188296.707606,6.0351,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188296.707606,1794188297.788235,1.0806,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188297.788235,1794188298.119083,0.3308,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188298.119083,1794188298.43845,0.3194,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188298.43845,1794188298.7576,0.3191,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188298.7576,1794188299.08042,0.3228,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188299.08042,1794188299.400504,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188299.400504,1794188299.724336,0.3238,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188299.724336,1794188300.048767,0.3244,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188300.048767,1794188300.367828,0.3191,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188300.367828,1794188300.68763,0.3198,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188300.68763,1794188300.708344,0.0207,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188300.708344,1794188301.756335,1.048,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188301.756335,1794188301.776632,0.0203,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188301.776632,1794188302.100595,0.324,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188302.100595,1794188302.41965,0.3191,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188302.41965,1794188302.744275,0.3246,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188302.744275,1794188304.781755,2.0375,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188304.781755,1794188305.840317,1.0586,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188305.840317,1794188306.164186,0.3239,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188306.164186,1794188306.481859,0.3177,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188306.481859,1794188306.80434,0.3225,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188306.80434,1794188307.121994,0.3177,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188307.121994,1794188307.135003,0.013,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188307.135003,1794188308.184269,1.0493,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188308.184269,1794188308.504239,0.32,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188308.504239,1794188308.828234,0.324,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188308.828234,1794188309.153791,0.3256,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188309.153791,1794188309.481541,0.3277,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188309.481541,1794188309.815291,0.3338,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188309.815291,1794188310.134533,0.3192,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188310.134533,1794188310.156328,0.0218,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188310.156328,1794188311.208176,1.0518,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188311.208176,1794188311.22823,0.0201,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188311.22823,1794188311.552142,0.3239,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188311.552142,1794188311.876389,0.3242,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188311.876389,1794188312.200184,0.3238,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188312.200184,1794188318.237856,6.0377,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188318.237856,1794188319.284039,1.0462,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188319.284039,1794188319.304282,0.0202,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188319.304282,1794188320.364103,1.0598,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188320.364103,1794188320.684131,0.32,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103804,1794188320.684131,1794188321.018561,0.3344,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188384.453816,1794188385.53321,1.0794,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188385.53321,1794188385.931852,0.3986,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188385.931852,1794188386.322312,0.3905,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188386.322312,1794188386.712538,0.3902,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188386.712538,1794188387.101867,0.3893,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188387.101867,1794188387.498776,0.3969,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188387.498776,1794188387.894831,0.3961,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188387.894831,1794188388.294865,0.4,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188388.294865,1794188388.691929,0.3971,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188388.691929,1794188388.930748,0.2388,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188388.930748,1794188388.950857,0.0201,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188388.950857,1794188389.271812,0.321,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188389.271812,1794188389.592611,0.3208,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188389.592611,1794188389.91248,0.3199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188389.91248,1794188395.934048,6.0216,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188395.934048,1794188396.982776,1.0487,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188396.982776,1794188397.302728,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188397.302728,1794188397.635628,0.3329,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188397.635628,1794188397.965344,0.3297,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188397.965344,1794188398.295571,0.3302,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188398.295571,1794188398.615069,0.3195,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188398.615069,1794188398.934008,0.3189,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188398.934008,1794188399.254865,0.3209,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188399.254865,1794188399.578512,0.3236,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188399.578512,1794188399.90268,0.3242,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188399.90268,1794188400.222604,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188400.222604,1794188400.542549,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188400.542549,1794188400.562574,0.02,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188400.562574,1794188401.610527,1.048,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188401.610527,1794188401.622493,0.012,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188401.622493,1794188401.94257,0.3201,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188401.94257,1794188402.266918,0.3243,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188402.266918,1794188402.590455,0.3235,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188402.590455,1794188404.618601,2.0281,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188404.618601,1794188405.661763,1.0432,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188405.661763,1794188405.986644,0.3249,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188405.986644,1794188406.310611,0.324,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188406.310611,1794188406.634462,0.3239,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188406.634462,1794188406.958035,0.3236,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188406.958035,1794188407.278477,0.3204,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188407.278477,1794188407.290298,0.0118,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188407.290298,1794188408.344027,1.0537,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188408.344027,1794188408.662409,0.3184,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188408.662409,1794188408.979831,0.3174,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188408.979831,1794188409.302464,0.3226,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188409.302464,1794188409.627802,0.3253,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188409.627802,1794188409.961539,0.3337,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188409.961539,1794188410.280532,0.319,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188410.280532,1794188410.292481,0.0119,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188410.292481,1794188411.338362,1.0459,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188411.338362,1794188411.358331,0.02,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188411.358331,1794188411.682732,0.3244,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188411.682732,1794188412.006415,0.3237,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188412.006415,1794188412.330372,0.324,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188412.330372,1794188418.374181,6.0438,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188418.374181,1794188419.428604,1.0544,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188419.428604,1794188419.440092,0.0115,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188419.440092,1794188420.498295,1.0582,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188420.498295,1794188420.822253,0.324,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_103943,1794188420.822253,1794188421.135746,0.3135,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188471.709987,1794188472.757764,1.0478,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188472.757764,1794188473.151097,0.3933,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188473.151097,1794188473.545364,0.3943,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188473.545364,1794188473.941742,0.3964,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188473.941742,1794188474.342728,0.401,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188474.342728,1794188474.742585,0.3999,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188474.742585,1794188475.141246,0.3987,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188475.141246,1794188475.534132,0.3929,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188475.534132,1794188475.930586,0.3965,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188475.930586,1794188476.165201,0.2346,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188476.165201,1794188476.185114,0.0199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188476.185114,1794188476.505255,0.3201,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188476.505255,1794188476.829147,0.3239,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188476.829147,1794188477.153207,0.3241,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188477.153207,1794188483.183359,6.0302,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188483.183359,1794188484.22829,1.0449,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188484.22829,1794188484.543143,0.3149,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188484.543143,1794188484.863206,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188484.863206,1794188485.185256,0.3221,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188485.185256,1794188485.505202,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188485.505202,1794188485.829066,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188485.829066,1794188486.154619,0.3256,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188486.154619,1794188486.484686,0.3301,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188486.484686,1794188486.818655,0.334,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188486.818655,1794188487.133998,0.3153,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188487.133998,1794188487.457091,0.3231,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188487.457091,1794188487.781009,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188487.781009,1794188487.801054,0.02,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188487.801054,1794188488.849581,1.0485,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188488.849581,1794188488.868998,0.0194,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188488.868998,1794188489.193001,0.324,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188489.193001,1794188489.516951,0.324,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188489.516951,1794188489.835934,0.319,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188489.835934,1794188491.867217,2.0313,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188491.867217,1794188492.911652,1.0444,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188492.911652,1794188493.227385,0.3157,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188493.227385,1794188493.548871,0.3215,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188493.548871,1794188493.873054,0.3242,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188493.873054,1794188494.197288,0.3242,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188494.197288,1794188494.520895,0.3236,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188494.520895,1794188494.844923,0.324,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188494.844923,1794188495.167279,0.3224,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188495.167279,1794188495.488969,0.3217,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188495.488969,1794188495.508994,0.02,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188495.508994,1794188496.560855,1.0519,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188496.560855,1794188496.880877,0.32,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188496.880877,1794188497.207196,0.3263,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188497.207196,1794188497.540733,0.3335,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188497.540733,1794188497.870683,0.3299,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188497.870683,1794188498.202852,0.3322,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188498.202852,1794188498.524919,0.3221,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188498.524919,1794188498.545464,0.0205,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188498.545464,1794188499.592823,1.0474,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188499.592823,1794188499.612819,0.02,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188499.612819,1794188499.941245,0.3284,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188499.941245,1794188500.265524,0.3243,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188500.265524,1794188500.588785,0.3233,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188500.588785,1794188506.623203,6.0344,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188506.623203,1794188507.667908,1.0447,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188507.667908,1794188507.68096,0.0131,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188507.68096,1794188508.732661,1.0517,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188508.732661,1794188509.052821,0.3202,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104110,1794188509.052821,1794188509.376875,0.3241,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188718.094549,1794188719.138821,1.0443,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188719.138821,1794188719.538,0.3992,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188719.538,1794188719.941292,0.4033,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188719.941292,1794188720.341041,0.3997,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188720.341041,1794188720.732967,0.3919,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188720.732967,1794188721.129205,0.3962,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188721.129205,1794188721.52688,0.3977,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188721.52688,1794188721.924698,0.3978,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188721.924698,1794188722.31856,0.3939,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188722.31856,1794188722.548028,0.2295,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188722.548028,1794188722.565008,0.017,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188722.565008,1794188722.87881,0.3138,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188722.87881,1794188723.19797,0.3192,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188723.19797,1794188723.521063,0.3231,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188723.521063,1794188729.549815,6.0288,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188729.549815,1794188730.597017,1.0472,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188730.597017,1794188730.921111,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188730.921111,1794188731.240575,0.3195,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188731.240575,1794188731.560185,0.3196,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188731.560185,1794188731.885025,0.3248,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188731.885025,1794188732.204889,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188732.204889,1794188732.528811,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188732.528811,1794188732.852844,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188732.852844,1794188733.181424,0.3286,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188733.181424,1794188733.511326,0.3299,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188733.511326,1794188733.83214,0.3208,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188733.83214,1794188733.842517,0.0104,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188733.842517,1794188734.888843,1.0463,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188734.888843,1794188734.909076,0.0202,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188734.909076,1794188735.233138,0.3241,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188735.233138,1794188735.552983,0.3198,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188735.552983,1794188735.873118,0.3201,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188735.873118,1794188737.903779,2.0307,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188737.903779,1794188738.979429,1.0756,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188738.979429,1794188739.304725,0.3253,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188739.304725,1794188739.628792,0.3241,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188739.628792,1794188739.944847,0.3161,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188739.944847,1794188740.264054,0.3192,APPROACH_PICK_LIFT,carry_lift,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188740.264054,1794188740.280696,0.0166,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188740.280696,1794188741.341005,1.0603,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188741.341005,1794188741.664689,0.3237,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188741.664689,1794188741.985966,0.3213,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188741.985966,1794188742.306042,0.3201,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188742.306042,1794188742.628235,0.3222,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188742.628235,1794188742.946582,0.3183,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188742.946582,1794188743.266025,0.3194,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188743.266025,1794188743.284637,0.0186,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188743.284637,1794188744.358744,1.0741,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188744.358744,1794188744.380802,0.0221,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188744.380802,1794188744.700595,0.3198,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188744.700595,1794188745.024695,0.3241,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188745.024695,1794188745.348952,0.3243,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188745.348952,1794188751.381812,6.0329,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188751.381812,1794188752.433215,1.0514,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188752.433215,1794188752.452612,0.0194,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188752.452612,1794188753.512714,1.0601,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188753.512714,1794188753.832276,0.3196,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_104517,1794188753.832276,1794188754.152045,0.3198,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195477.884593,1794195478.936468,1.0519,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195478.936468,1794195479.31777,0.3813,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195479.31777,1794195479.707942,0.3902,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195479.707942,1794195480.098907,0.391,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195480.098907,1794195480.478703,0.3798,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195480.478703,1794195480.860454,0.3818,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195480.860454,1794195481.252354,0.3919,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195481.252354,1794195481.647989,0.3956,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195481.647989,1794195482.04935,0.4014,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195482.04935,1794195482.288317,0.239,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195482.288317,1794195482.3119,0.0236,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195482.3119,1794195482.63825,0.3264,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195482.63825,1794195482.958464,0.3202,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195482.958464,1794195483.278028,0.3196,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195483.278028,1794195489.312445,6.0344,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195489.312445,1794195490.364497,1.0521,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195490.364497,1794195490.688537,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195490.688537,1794195491.012656,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195491.012656,1794195491.336522,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195491.336522,1794195491.65047,0.3139,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195491.65047,1794195491.970561,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195491.970561,1794195492.296838,0.3263,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195492.296838,1794195492.620752,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195492.620752,1794195492.940412,0.3197,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195492.940412,1794195493.26439,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195493.26439,1794195493.588301,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195493.588301,1794195493.608788,0.0205,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195493.608788,1794195494.656748,1.048,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195494.656748,1794195494.668724,0.012,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195494.668724,1794195494.982199,0.3135,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195494.982199,1794195495.304572,0.3224,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195495.304572,1794195495.628428,0.3239,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195495.628428,1794195497.665121,2.0367,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195497.665121,1794195498.716352,1.0512,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195498.716352,1794195498.736431,0.0201,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195498.736431,1794195499.815702,1.0793,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195499.815702,1794195500.136856,0.3212,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195500.136856,1794195500.458296,0.3214,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195500.458296,1794195500.776481,0.3182,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195500.776481,1794195501.100347,0.3239,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195501.100347,1794195501.12057,0.0202,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195501.12057,1794195502.16833,1.0478,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195502.16833,1794195502.188412,0.0201,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195502.188412,1794195502.508748,0.3203,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195502.508748,1794195502.838315,0.3296,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195502.838315,1794195503.157227,0.3189,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195503.157227,1794195509.181164,6.0239,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195509.181164,1794195510.22441,1.0432,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195510.22441,1794195510.237153,0.0127,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195510.237153,1794195511.319077,1.0819,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195511.319077,1794195511.634489,0.3154,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195511.634489,1794195511.956411,0.3219,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123756,1794195511.956411,1794195512.273934,0.3175,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195529.322293,1794195530.372317,1.05,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195530.372317,1794195530.755054,0.3827,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195530.755054,1794195531.148381,0.3933,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195531.148381,1794195531.536727,0.3883,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195531.536727,1794195531.916688,0.38,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195531.916688,1794195532.32183,0.4051,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195532.32183,1794195532.675751,0.3539,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195532.675751,1794195533.065027,0.3893,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195533.065027,1794195533.452287,0.3873,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195533.452287,1794195533.732427,0.2801,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195533.732427,1794195533.752286,0.0199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195533.752286,1794195534.072759,0.3205,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195534.072759,1794195534.396412,0.3237,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195534.396412,1794195534.721599,0.3252,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195534.721599,1794195540.765799,6.0442,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195540.765799,1794195541.811608,1.0458,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195541.811608,1794195542.132455,0.3208,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195542.132455,1794195542.4563,0.3238,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195542.4563,1794195542.780352,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195542.780352,1794195543.097513,0.3172,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195543.097513,1794195543.423116,0.3256,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195543.423116,1794195543.744372,0.3213,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195543.744372,1794195544.068525,0.3242,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195544.068525,1794195544.387572,0.319,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195544.387572,1794195544.708076,0.3205,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195544.708076,1794195545.027775,0.3197,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195545.027775,1794195545.347284,0.3195,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195545.347284,1794195545.36482,0.0175,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195545.36482,1794195546.424489,1.0597,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195546.424489,1794195546.444443,0.02,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195546.444443,1794195546.767934,0.3235,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195546.767934,1794195547.102142,0.3342,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195547.102142,1794195547.419756,0.3176,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195547.419756,1794195549.45122,2.0315,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195549.45122,1794195550.495534,1.0443,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195550.495534,1794195550.507803,0.0123,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195550.507803,1794195551.56061,1.0528,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195551.56061,1794195551.88445,0.3238,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195551.88445,1794195552.212222,0.3278,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195552.212222,1794195552.544667,0.3324,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195552.544667,1794195552.874736,0.3301,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195552.874736,1794195552.89754,0.0228,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195552.89754,1794195553.939869,1.0423,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195553.939869,1794195553.952929,0.0131,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195553.952929,1794195554.276534,0.3236,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195554.276534,1794195554.600612,0.3241,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195554.600612,1794195554.924311,0.3237,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195554.924311,1794195560.957483,6.0332,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195560.957483,1794195562.0085,1.051,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195562.0085,1794195562.025664,0.0172,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195562.025664,1794195563.072318,1.0467,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195563.072318,1794195563.392315,0.32,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195563.392315,1794195563.716409,0.3241,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195563.716409,1794195564.04078,0.3244,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_123848,1794195564.04078,1794195564.368407,0.3276,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195633.524885,1794195634.598023,1.0731,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195634.598023,1794195634.988264,0.3902,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195634.988264,1794195635.372751,0.3845,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195635.372751,1794195635.769735,0.397,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195635.769735,1794195636.149064,0.3793,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195636.149064,1794195636.540378,0.3913,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195636.540378,1794195636.924305,0.3839,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195636.924305,1794195637.309469,0.3852,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195637.309469,1794195637.696245,0.3868,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195637.696245,1794195637.928253,0.232,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195637.928253,1794195637.948207,0.02,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195637.948207,1794195638.268919,0.3207,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195638.268919,1794195638.589256,0.3203,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195638.589256,1794195638.909883,0.3206,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195638.909883,1794195644.931257,6.0214,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195644.931257,1794195645.976478,1.0452,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195645.976478,1794195646.308553,0.3321,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195646.308553,1794195646.642469,0.3339,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195646.642469,1794195646.972528,0.3301,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195646.972528,1794195647.303579,0.3311,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195647.303579,1794195647.621253,0.3177,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195647.621253,1794195647.941409,0.3202,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195647.941409,1794195648.264197,0.3228,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195648.264197,1794195648.584156,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195648.584156,1794195648.904397,0.3202,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195648.904397,1794195649.22418,0.3198,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195649.22418,1794195649.244448,0.0203,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195649.244448,1794195650.292199,1.0478,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195650.292199,1794195650.3147,0.0225,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195650.3147,1794195650.634222,0.3195,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195650.634222,1794195650.953172,0.3189,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195650.953172,1794195651.273291,0.3201,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195651.273291,1794195653.316891,2.0436,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195653.316891,1794195654.364226,1.0473,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195654.364226,1794195654.384211,0.02,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195654.384211,1794195655.44459,1.0604,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195655.44459,1794195655.758256,0.3137,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195655.758256,1794195656.077258,0.319,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195656.077258,1794195656.397327,0.3201,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195656.397327,1794195656.717492,0.3202,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195656.717492,1794195656.74056,0.0231,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195656.74056,1794195657.793641,1.0531,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195657.793641,1794195657.813091,0.0194,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195657.813091,1794195658.129272,0.3162,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195658.129272,1794195658.458597,0.3293,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195658.458597,1794195658.78086,0.3223,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195658.78086,1794195664.822748,6.0419,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195664.822748,1794195665.864362,1.0416,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195665.864362,1794195665.884398,0.02,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195665.884398,1794195666.944421,1.06,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195666.944421,1794195667.268595,0.3242,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195667.268595,1794195667.58399,0.3154,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124032,1794195667.58399,1794195667.903855,0.3199,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195678.561838,1794195679.608366,1.0465,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195679.608366,1794195679.996438,0.3881,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195679.996438,1794195680.385979,0.3895,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195680.385979,1794195680.775919,0.3899,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195680.775919,1794195681.155968,0.38,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195681.155968,1794195681.548196,0.3922,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195681.548196,1794195681.932222,0.384,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195681.932222,1794195682.322722,0.3905,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195682.322722,1794195682.708462,0.3857,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195682.708462,1794195682.948283,0.2398,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195682.948283,1794195682.960287,0.012,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195682.960287,1794195683.27641,0.3161,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195683.27641,1794195683.596895,0.3205,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195683.596895,1794195683.920374,0.3235,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195683.920374,1794195689.957864,6.0375,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195689.957864,1794195691.004257,1.0464,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195691.004257,1794195691.318508,0.3143,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195691.318508,1794195691.638889,0.3204,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195691.638889,1794195691.958884,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195691.958884,1794195692.284358,0.3255,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195692.284358,1794195692.608159,0.3238,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195692.608159,1794195692.928804,0.3206,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195692.928804,1794195693.248893,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195693.248893,1794195693.579687,0.3308,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195693.579687,1794195693.908957,0.3293,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195693.908957,1794195694.239836,0.3309,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195694.239836,1794195694.261705,0.0219,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195694.261705,1794195695.31262,1.0509,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195695.31262,1794195695.333128,0.0205,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195695.333128,1794195695.653527,0.3204,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195695.653527,1794195695.976324,0.3228,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195695.976324,1794195696.296329,0.32,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195696.296329,1794195698.332252,2.0359,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195698.332252,1794195699.376361,1.0441,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195699.376361,1794195699.396407,0.02,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195699.396407,1794195700.484935,1.0885,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195700.484935,1794195700.804612,0.3197,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195700.804612,1794195701.124416,0.3198,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195701.124416,1794195701.444729,0.3203,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195701.444729,1794195701.764475,0.3197,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195701.764475,1794195701.784283,0.0198,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195701.784283,1794195702.83658,1.0523,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195702.83658,1794195702.856498,0.0199,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195702.856498,1794195703.176832,0.3203,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195703.176832,1794195703.496757,0.3199,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195703.496757,1794195703.81708,0.3203,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195703.81708,1794195709.848826,6.0317,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195709.848826,1794195710.896058,1.0472,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195710.896058,1794195710.914806,0.0187,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195710.914806,1794195711.985382,1.0706,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195711.985382,1794195712.342268,0.3569,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124117,1794195712.342268,1794195712.673201,0.3309,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195728.248719,1794195729.335385,1.0867,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195729.335385,1794195729.712966,0.3776,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195729.712966,1794195730.103576,0.3906,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195730.103576,1794195730.472978,0.3694,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195730.472978,1794195730.862915,0.3899,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195730.862915,1794195731.244939,0.382,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195731.244939,1794195731.632197,0.3873,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195731.632197,1794195732.023002,0.3908,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195732.023002,1794195732.412909,0.3899,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195732.412909,1794195732.640581,0.2277,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195732.640581,1794195732.660611,0.02,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195732.660611,1794195732.973631,0.313,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195732.973631,1794195733.293098,0.3195,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195733.293098,1794195733.616296,0.3232,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195733.616296,1794195739.645207,6.0289,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195739.645207,1794195740.704768,1.0596,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195740.704768,1794195741.036553,0.3318,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195741.036553,1794195741.366647,0.3301,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195741.366647,1794195741.689159,0.3225,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195741.689159,1794195742.005684,0.3165,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195742.005684,1794195742.325267,0.3196,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195742.325267,1794195742.645171,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195742.645171,1794195742.965661,0.3205,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195742.965661,1794195743.288455,0.3228,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195743.288455,1794195743.608244,0.3198,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195743.608244,1794195743.928294,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195743.928294,1794195743.94848,0.0202,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195743.94848,1794195744.992278,1.0438,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195744.992278,1794195745.006649,0.0144,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195745.006649,1794195745.328628,0.322,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195745.328628,1794195745.653007,0.3244,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195745.653007,1794195745.976307,0.3233,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195745.976307,1794195748.009726,2.0334,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195748.009726,1794195749.056287,1.0466,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195749.056287,1794195749.076511,0.0202,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195749.076511,1794195750.124172,1.0477,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195750.124172,1794195750.448506,0.3243,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195750.448506,1794195750.761551,0.313,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195750.761551,1794195751.08143,0.3199,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195751.08143,1794195751.404395,0.323,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195751.404395,1794195751.424728,0.0203,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195751.424728,1794195752.472403,1.0477,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195752.472403,1794195752.492273,0.0199,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195752.492273,1794195752.82418,0.3319,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195752.82418,1794195753.1522,0.328,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195753.1522,1794195753.472162,0.32,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195753.472162,1794195759.511526,6.0394,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195759.511526,1794195760.559854,1.0483,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195760.559854,1794195760.580606,0.0208,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195760.580606,1794195761.640769,1.0602,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195761.640769,1794195761.957672,0.3169,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195761.957672,1794195762.280233,0.3226,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124207,1794195762.280233,1794195762.598196,0.318,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195777.389589,1794195778.433203,1.0436,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195778.433203,1794195778.830868,0.3977,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195778.830868,1794195779.223325,0.3925,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195779.223325,1794195779.612503,0.3892,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195779.612503,1794195779.992679,0.3802,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195779.992679,1794195780.373077,0.3804,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195780.373077,1794195780.762685,0.3896,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195780.762685,1794195781.151,0.3883,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195781.151,1794195781.542941,0.3919,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195781.542941,1794195781.779183,0.2362,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195781.779183,1794195781.799105,0.0199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195781.799105,1794195782.122719,0.3236,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195782.122719,1794195782.451367,0.3286,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195782.451367,1794195782.784244,0.3329,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195782.784244,1794195788.830677,6.0464,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195788.830677,1794195789.881415,1.0507,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195789.881415,1794195790.20545,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195790.20545,1794195790.525478,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195790.525478,1794195790.845438,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195790.845438,1794195791.165581,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195791.165581,1794195791.487647,0.3221,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195791.487647,1794195791.806126,0.3185,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195791.806126,1794195792.126233,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195792.126233,1794195792.447661,0.3214,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195792.447661,1794195792.772353,0.3247,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195792.772353,1794195793.085597,0.3132,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195793.085597,1794195793.405495,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195793.405495,1794195793.42366,0.0182,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195793.42366,1794195794.503022,1.0794,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195794.503022,1794195794.525199,0.0222,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195794.525199,1794195794.85054,0.3253,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195794.85054,1794195795.16842,0.3179,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195795.16842,1794195795.491736,0.3233,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195795.491736,1794195797.520001,2.0283,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195797.520001,1794195798.574038,1.054,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195798.574038,1794195798.591812,0.0178,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195798.591812,1794195799.658666,1.0669,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195799.658666,1794195799.99073,0.3321,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195799.99073,1794195800.323552,0.3328,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195800.323552,1794195800.649726,0.3262,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195800.649726,1794195800.972571,0.3228,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195800.972571,1794195800.990186,0.0176,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195800.990186,1794195802.032027,1.0418,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195802.032027,1794195802.053178,0.0212,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195802.053178,1794195802.375971,0.3228,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195802.375971,1794195802.699962,0.324,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195802.699962,1794195803.024268,0.3243,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195803.024268,1794195809.066432,6.0422,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195809.066432,1794195810.110485,1.0441,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195810.110485,1794195810.12804,0.0176,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195810.12804,1794195811.178301,1.0503,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195811.178301,1794195811.48818,0.3099,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195811.48818,1794195811.815819,0.3276,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124256,1794195811.815819,1794195812.14734,0.3315,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195879.884645,1794195880.940324,1.0557,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195880.940324,1794195881.342004,0.4017,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195881.342004,1794195881.736223,0.3942,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195881.736223,1794195882.132689,0.3965,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195882.132689,1794195882.524298,0.3916,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195882.524298,1794195882.922113,0.3978,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195882.922113,1794195883.312561,0.3904,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195883.312561,1794195883.702147,0.3896,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195883.702147,1794195884.102032,0.3999,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195884.102032,1794195884.340231,0.2382,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195884.340231,1794195884.360179,0.0199,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195884.360179,1794195884.684205,0.324,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195884.684205,1794195885.00208,0.3179,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195885.00208,1794195885.328224,0.3261,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195885.328224,1794195891.372093,6.0439,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195891.372093,1794195892.419769,1.0477,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195892.419769,1794195892.744204,0.3244,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195892.744204,1794195893.064542,0.3203,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195893.064542,1794195893.388305,0.3238,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195893.388305,1794195893.712289,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195893.712289,1794195894.034167,0.3219,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195894.034167,1794195894.356403,0.3222,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195894.356403,1794195894.684759,0.3284,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195894.684759,1794195895.006122,0.3214,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195895.006122,1794195895.325225,0.3191,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195895.325225,1794195895.64486,0.3196,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195895.64486,1794195895.664249,0.0194,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195895.664249,1794195896.724234,1.06,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195896.724234,1794195896.744162,0.0199,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195896.744162,1794195897.068309,0.3241,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195897.068309,1794195897.392106,0.3238,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195897.392106,1794195897.716802,0.3247,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195897.716802,1794195899.748538,2.0317,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195899.748538,1794195900.800161,1.0516,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195900.800161,1794195900.820842,0.0207,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195900.820842,1794195901.868306,1.0475,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195901.868306,1794195902.188337,0.32,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195902.188337,1794195902.519213,0.3309,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195902.519213,1794195902.852077,0.3329,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195902.852077,1794195903.181896,0.3298,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195903.181896,1794195903.213573,0.0317,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195903.213573,1794195905.457456,2.2439,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195905.457456,1794195905.479216,0.0218,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195905.479216,1794195905.804213,0.325,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195905.804213,1794195906.12815,0.3239,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195906.12815,1794195906.448239,0.3201,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195906.448239,1794195912.484797,6.0366,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195912.484797,1794195913.532382,1.0476,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195913.532382,1794195913.556356,0.024,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195913.556356,1794195914.615529,1.0592,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195914.615529,1794195914.947025,0.3315,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195914.947025,1794195915.27444,0.3274,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124438,1794195915.27444,1794195915.587268,0.3128,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196098.774443,1794196099.836495,1.0621,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196099.836495,1794196100.232401,0.3959,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196100.232401,1794196100.628743,0.3963,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196100.628743,1794196101.028675,0.3999,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196101.028675,1794196101.420063,0.3914,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196101.420063,1794196101.812354,0.3923,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196101.812354,1794196102.208717,0.3964,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196102.208717,1794196102.604359,0.3956,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196102.604359,1794196102.998753,0.3944,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196102.998753,1794196103.233184,0.2344,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196103.233184,1794196103.257288,0.0241,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196103.257288,1794196103.59031,0.333,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196103.59031,1794196103.919381,0.3291,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196103.919381,1794196104.239492,0.3201,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196104.239492,1794196110.271563,6.0321,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196110.271563,1794196111.320324,1.0488,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196111.320324,1794196111.640315,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196111.640315,1794196111.964339,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196111.964339,1794196112.281039,0.3167,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196112.281039,1794196112.60432,0.3233,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196112.60432,1794196112.931549,0.3272,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196112.931549,1794196113.251462,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196113.251462,1794196113.576544,0.3251,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196113.576544,1794196113.904329,0.3278,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196113.904329,1794196114.221632,0.3173,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196114.221632,1794196114.544356,0.3227,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196114.544356,1794196114.868402,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196114.868402,1794196114.888295,0.0199,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196114.888295,1794196115.93731,1.049,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196115.93731,1794196116.264829,0.3275,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196116.264829,1794196116.584548,0.3197,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196116.584548,1794196116.604273,0.0197,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196116.604273,1794196116.928372,0.3241,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196116.928372,1794196117.252308,0.3239,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196117.252308,1794196117.576248,0.3239,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196117.576248,1794196119.605197,2.0289,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196119.605197,1794196120.6524,1.0472,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196120.6524,1794196120.674474,0.0221,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196120.674474,1794196121.759459,1.085,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196121.759459,1794196122.078201,0.3187,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196122.078201,1794196122.397903,0.3197,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196122.397903,1794196122.720471,0.3226,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196122.720471,1794196123.037179,0.3167,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196123.037179,1794196123.056348,0.0192,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196123.056348,1794196124.116344,1.06,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196124.116344,1794196124.136563,0.0202,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196124.136563,1794196124.449591,0.313,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196124.449591,1794196124.771519,0.3219,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196124.771519,1794196125.089604,0.3181,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196125.089604,1794196131.121525,6.0319,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196131.121525,1794196132.180534,1.059,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196132.180534,1794196132.200343,0.0198,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196132.200343,1794196133.28031,1.08,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196133.28031,1794196133.611187,0.3309,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124817,1794196133.611187,1794196133.935148,0.324,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196161.583406,1794196162.664644,1.0812,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196162.664644,1794196163.065941,0.4013,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196163.065941,1794196163.46652,0.4006,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196163.46652,1794196163.864495,0.398,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196163.864495,1794196164.256076,0.3916,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196164.256076,1794196164.652393,0.3963,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196164.652393,1794196165.05343,0.401,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196165.05343,1794196165.452535,0.3991,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196165.452535,1794196165.848439,0.3959,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196165.848439,1794196166.086644,0.2382,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196166.086644,1794196166.098433,0.0118,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196166.098433,1794196166.41846,0.32,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196166.41846,1794196166.74718,0.3287,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196166.74718,1794196167.072454,0.3253,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196167.072454,1794196173.10796,6.0355,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196173.10796,1794196174.181205,1.0732,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196174.181205,1794196174.507127,0.3259,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196174.507127,1794196174.839887,0.3328,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196174.839887,1794196175.158858,0.319,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196175.158858,1794196175.478515,0.3197,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196175.478515,1794196175.798496,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196175.798496,1794196176.120528,0.322,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196176.120528,1794196176.444484,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196176.444484,1794196176.768817,0.3243,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196176.768817,1794196177.092332,0.3235,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196177.092332,1794196177.408542,0.3162,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196177.408542,1794196177.428462,0.0199,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196177.428462,1794196178.47652,1.0481,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196178.47652,1794196178.496871,0.0204,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196178.496871,1794196178.820351,0.3235,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196178.820351,1794196179.140909,0.3206,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196179.140909,1794196179.464392,0.3235,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196179.464392,1794196181.492693,2.0283,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196181.492693,1794196182.544549,1.0519,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196182.544549,1794196182.564383,0.0198,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196182.564383,1794196183.612801,1.0484,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196183.612801,1794196183.935343,0.3225,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196183.935343,1794196184.25463,0.3193,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196184.25463,1794196184.580479,0.3258,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196184.580479,1794196184.904621,0.3241,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196184.904621,1794196184.936502,0.0319,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196184.936502,1794196185.99246,1.056,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196185.99246,1794196186.020277,0.0278,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196186.020277,1794196186.340449,0.3202,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196186.340449,1794196186.6686,0.3282,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196186.6686,1794196186.987144,0.3185,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196186.987144,1794196193.038941,6.0518,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196193.038941,1794196194.100512,1.0616,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196194.100512,1794196194.125235,0.0247,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196194.125235,1794196195.178879,1.0536,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196195.178879,1794196195.501421,0.3225,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196195.501421,1794196195.821273,0.3199,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_124920,1794196195.821273,1794196196.140938,0.3197,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197143.184568,1794197144.232456,1.0479,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197144.232456,1794197144.62821,0.3958,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197144.62821,1794197145.024302,0.3961,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197145.024302,1794197145.420205,0.3959,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197145.420205,1794197145.811819,0.3916,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197145.811819,1794197146.202058,0.3902,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197146.202058,1794197146.592411,0.3904,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197146.592411,1794197146.991803,0.3994,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197146.991803,1794197147.388269,0.3965,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197147.388269,1794197147.633932,0.2457,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197147.633932,1794197147.653635,0.0197,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197147.653635,1794197147.972387,0.3188,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197147.972387,1794197148.296414,0.324,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197148.296414,1794197148.626127,0.3297,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197148.626127,1794197154.685581,6.0595,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197154.685581,1794197155.724404,1.0388,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197155.724404,1794197156.048314,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197156.048314,1794197156.372731,0.3244,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197156.372731,1794197156.700288,0.3276,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197156.700288,1794197157.024667,0.3244,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197157.024667,1794197157.344673,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197157.344673,1794197157.673937,0.3293,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197157.673937,1794197158.004403,0.3305,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197158.004403,1794197158.324476,0.3201,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197158.324476,1794197158.644656,0.3202,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197158.644656,1794197158.968313,0.3237,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197158.968313,1794197159.288204,0.3199,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197159.288204,1794197159.308257,0.0201,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197159.308257,1794197160.375103,1.0668,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197160.375103,1794197160.397136,0.022,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197160.397136,1794197160.721603,0.3245,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197160.721603,1794197161.046572,0.325,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197161.046572,1794197161.365943,0.3194,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197161.365943,1794197163.408035,2.0421,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197163.408035,1794197164.460366,1.0523,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197164.460366,1794197164.488228,0.0279,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197164.488228,1794197165.556638,1.0684,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197165.556638,1794197165.880688,0.324,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197165.880688,1794197166.204349,0.3237,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197166.204349,1794197166.530031,0.3257,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197166.530031,1794197166.850389,0.3204,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197166.850389,1794197167.170665,0.3203,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197167.170665,1794197167.496433,0.3258,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197167.496433,1794197167.820367,0.3239,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197167.820367,1794197168.140634,0.3203,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197168.140634,1794197168.160288,0.0197,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197168.160288,1794197169.206325,1.046,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197169.206325,1794197169.218284,0.012,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197169.218284,1794197169.540248,0.322,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197169.540248,1794197169.862674,0.3224,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197169.862674,1794197170.18223,0.3196,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197170.18223,1794197176.204382,6.0222,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197176.204382,1794197177.256278,1.0519,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197177.256278,1794197177.279659,0.0234,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197177.279659,1794197178.349462,1.0698,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197178.349462,1794197178.667149,0.3177,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197178.667149,1794197178.986652,0.3195,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130542,1794197178.986652,1794197179.312413,0.3258,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197244.457496,1794197245.509699,1.0522,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197245.509699,1794197245.902267,0.3926,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197245.902267,1794197246.299635,0.3974,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197246.299635,1794197246.700511,0.4009,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197246.700511,1794197247.092319,0.3918,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197247.092319,1794197247.480712,0.3884,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197247.480712,1794197247.876236,0.3955,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197247.876236,1794197248.259921,0.3837,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197248.259921,1794197248.658644,0.3987,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197248.658644,1794197248.901282,0.2426,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197248.901282,1794197248.933554,0.0323,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197248.933554,1794197249.261445,0.3279,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197249.261445,1794197249.580197,0.3188,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197249.580197,1794197249.899955,0.3198,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197249.899955,1794197255.941923,6.042,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197255.941923,1794197256.986089,1.0442,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197256.986089,1794197257.312329,0.3262,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197257.312329,1794197257.636772,0.3244,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197257.636772,1794197257.962054,0.3253,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197257.962054,1794197258.282622,0.3206,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197258.282622,1794197258.602054,0.3194,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197258.602054,1794197258.924363,0.3223,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197258.924363,1794197259.248255,0.3239,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197259.248255,1794197259.568304,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197259.568304,1794197259.892952,0.3246,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197259.892952,1794197259.912672,0.0197,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197259.912672,1794197260.960375,1.0477,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197260.960375,1794197260.980742,0.0204,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197260.980742,1794197261.304747,0.324,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197261.304747,1794197261.624133,0.3194,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197261.624133,1794197261.948305,0.3242,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197261.948305,1794197263.9762,2.0279,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197263.9762,1794197265.02017,1.044,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197265.02017,1794197265.040381,0.0202,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197265.040381,1794197266.117558,1.0772,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197266.117558,1794197266.438298,0.3207,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197266.438298,1794197266.760362,0.3221,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197266.760362,1794197267.0785,0.3181,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197267.0785,1794197267.398294,0.3198,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197267.398294,1794197267.724318,0.326,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197267.724318,1794197268.048868,0.3245,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197268.048868,1794197268.376364,0.3275,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197268.376364,1794197268.69837,0.322,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197268.69837,1794197268.724355,0.026,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197268.724355,1794197269.776235,1.0519,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197269.776235,1794197269.797432,0.0212,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197269.797432,1794197270.121212,0.3238,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197270.121212,1794197270.440879,0.3197,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197270.440879,1794197270.760807,0.3199,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197270.760807,1794197276.803142,6.0423,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197276.803142,1794197277.874932,1.0718,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197277.874932,1794197277.901854,0.0269,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197277.901854,1794197278.953118,1.0513,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197278.953118,1794197279.274535,0.3214,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197279.274535,1794197279.600352,0.3258,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130723,1794197279.600352,1794197279.924282,0.3239,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197305.491544,1794197306.543224,1.0517,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197306.543224,1794197306.940288,0.3971,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197306.940288,1794197307.304688,0.3644,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197307.304688,1794197307.697223,0.3925,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197307.697223,1794197308.088808,0.3916,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197308.088808,1794197308.477186,0.3884,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197308.477186,1794197308.867143,0.39,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197308.867143,1794197309.260204,0.3931,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197309.260204,1794197309.647107,0.3869,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197309.647107,1794197309.93249,0.2854,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197309.93249,1794197309.95218,0.0197,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197309.95218,1794197310.276298,0.3241,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197310.276298,1794197310.60267,0.3264,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197310.60267,1794197310.924346,0.3217,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197310.924346,1794197316.94941,6.0251,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197316.94941,1794197317.996442,1.047,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197317.996442,1794197318.320529,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197318.320529,1794197318.640512,0.32,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197318.640512,1794197318.970336,0.3298,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197318.970336,1794197319.300724,0.3304,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197319.300724,1794197319.630753,0.33,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197319.630753,1794197319.949854,0.3191,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197319.949854,1794197320.270618,0.3208,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197320.270618,1794197320.592337,0.3217,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197320.592337,1794197320.916402,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197320.916402,1794197320.936316,0.0199,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197320.936316,1794197322.575469,1.6392,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197322.575469,1794197322.592432,0.017,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197322.592432,1794197322.912242,0.3198,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197322.912242,1794197323.232093,0.3199,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197323.232093,1794197323.552498,0.3204,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197323.552498,1794197325.594918,2.0424,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197325.594918,1794197326.647949,1.053,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197326.647949,1794197326.659626,0.0117,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197326.659626,1794197327.723542,1.0639,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197327.723542,1794197328.04434,0.3208,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197328.04434,1794197328.365607,0.3213,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197328.365607,1794197328.685942,0.3203,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197328.685942,1794197329.00595,0.32,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197329.00595,1794197329.325624,0.3197,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197329.325624,1794197329.648254,0.3226,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197329.648254,1794197329.968451,0.3202,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197329.968451,1794197330.292501,0.324,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197330.292501,1794197330.312351,0.0199,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197330.312351,1794197331.393056,1.0807,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197331.393056,1794197331.404603,0.0115,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197331.404603,1794197331.717969,0.3134,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197331.717969,1794197332.038207,0.3202,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197332.038207,1794197332.360341,0.3221,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197332.360341,1794197338.399881,6.0395,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197338.399881,1794197339.452383,1.0525,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197339.452383,1794197339.472389,0.02,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197339.472389,1794197340.521271,1.0489,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197340.521271,1794197340.842572,0.3213,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197340.842572,1794197341.16171,0.3191,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130824,1794197341.16171,1794197341.481749,0.32,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197370.632036,1794197371.68542,1.0534,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197371.68542,1794197372.076436,0.391,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197372.076436,1794197372.476054,0.3996,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197372.476054,1794197372.875709,0.3997,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197372.875709,1794197373.255117,0.3794,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197373.255117,1794197373.64462,0.3895,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197373.64462,1794197374.044792,0.4002,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197374.044792,1794197374.436346,0.3916,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197374.436346,1794197374.836444,0.4001,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197374.836444,1794197375.064709,0.2283,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197375.064709,1794197375.084361,0.0197,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197375.084361,1794197375.408249,0.3239,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197375.408249,1794197375.734378,0.3261,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197375.734378,1794197376.054941,0.3206,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197376.054941,1794197382.097361,6.0424,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197382.097361,1794197383.158772,1.0614,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197383.158772,1794197383.480394,0.3216,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197383.480394,1794197383.804471,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197383.804471,1794197384.137283,0.3328,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197384.137283,1794197384.469381,0.3321,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197384.469381,1794197384.797878,0.3285,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197384.797878,1794197385.117099,0.3192,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197385.117099,1794197385.436935,0.3198,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197385.436935,1794197385.760296,0.3234,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197385.760296,1794197386.076711,0.3164,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197386.076711,1794197386.09637,0.0197,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197386.09637,1794197387.156474,1.0601,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197387.156474,1794197387.176533,0.0201,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197387.176533,1794197387.496344,0.3198,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197387.496344,1794197387.819368,0.323,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197387.819368,1794197388.139214,0.3198,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197388.139214,1794197390.161971,2.0228,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197390.161971,1794197391.208318,1.0463,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197391.208318,1794197391.22841,0.0201,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197391.22841,1794197392.288486,1.0601,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197392.288486,1794197392.612464,0.324,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197392.612464,1794197392.936566,0.3241,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197392.936566,1794197393.253077,0.3165,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197393.253077,1794197393.576332,0.3233,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197393.576332,1794197393.893658,0.3173,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197393.893658,1794197394.213326,0.3197,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197394.213326,1794197394.536325,0.323,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197394.536325,1794197394.857661,0.3213,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197394.857661,1794197394.8765,0.0188,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197394.8765,1794197395.960314,1.0838,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197395.960314,1794197395.982616,0.0223,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197395.982616,1794197396.305028,0.3224,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197396.305028,1794197396.625767,0.3207,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197396.625767,1794197396.945613,0.3198,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197396.945613,1794197402.987251,6.0416,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197402.987251,1794197404.04437,1.0571,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197404.04437,1794197404.06442,0.0201,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197404.06442,1794197405.112261,1.0478,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197405.112261,1794197405.42967,0.3174,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197405.42967,1794197405.749365,0.3197,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_130929,1794197405.749365,1794197406.072397,0.323,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197464.252748,1794197465.30437,1.0516,HOME_START,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197465.30437,1794197465.692786,0.3884,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197465.692786,1794197466.082638,0.3899,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197466.082638,1794197466.492606,0.41,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197466.492606,1794197466.894491,0.4019,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197466.894491,1794197467.284573,0.3901,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197467.284573,1794197467.673154,0.3886,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197467.673154,1794197468.062503,0.3893,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197468.062503,1794197468.460431,0.3979,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197468.460431,1794197468.696343,0.2359,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197468.696343,1794197468.716423,0.0201,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197468.716423,1794197469.040451,0.324,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197469.040451,1794197469.368302,0.3279,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197469.368302,1794197469.692313,0.324,HOME_START,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197469.692313,1794197475.734714,6.0424,HOME_START,home,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197475.734714,1794197476.784405,1.0497,APPROACH_PICK,approach,send,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197476.784405,1794197477.104785,0.3204,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197477.104785,1794197477.428334,0.3235,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197477.428334,1794197477.752289,0.324,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197477.752289,1794197478.07477,0.3225,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197478.07477,1794197478.406074,0.3313,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197478.406074,1794197478.73635,0.3303,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197478.73635,1794197479.06716,0.3308,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197479.06716,1794197479.385395,0.3182,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197479.385395,1794197479.704802,0.3194,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197479.704802,1794197480.028948,0.3241,APPROACH_PICK,approach,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197480.028948,1794197480.047711,0.0188,APPROACH_PICK,approach,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197480.047711,1794197481.09631,1.0486,PICK,grasp,send,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197481.09631,1794197481.116527,0.0202,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197481.116527,1794197481.440365,0.3238,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197481.440365,1794197481.764397,0.324,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197481.764397,1794197482.087527,0.3231,PICK,grasp,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197482.087527,1794197484.118922,2.0314,PICK,grasp,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197484.118922,1794197485.173912,1.055,APPROACH_PICK_LIFT,carry_lift,send,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197485.173912,1794197485.195193,0.0213,APPROACH_PICK_LIFT,carry_lift,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197485.195193,1794197486.238887,1.0437,APPROACH_PLACE,carry,send,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197486.238887,1794197486.562078,0.3232,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197486.562078,1794197486.884383,0.3223,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197486.884383,1794197487.212378,0.328,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197487.212378,1794197487.530862,0.3185,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197487.530862,1794197487.856417,0.3256,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197487.856417,1794197488.180894,0.3245,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197488.180894,1794197488.500657,0.3198,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197488.500657,1794197488.824422,0.3238,APPROACH_PLACE,carry,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197488.824422,1794197488.848432,0.024,APPROACH_PLACE,carry,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197488.848432,1794197489.90841,1.06,PLACE,release,send,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197489.90841,1794197489.928344,0.0199,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197489.928344,1794197490.264245,0.3359,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197490.264245,1794197490.58834,0.3241,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197490.58834,1794197490.918492,0.3302,PLACE,release,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197490.918492,1794197496.957132,6.0386,PLACE,release,gripper,gripper_cmd;stage
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197496.957132,1794197498.004483,1.0474,APPROACH_PLACE_RETREAT,retreat,send,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197498.004483,1794197498.027108,0.0226,APPROACH_PLACE_RETREAT,retreat,stage_change,stage
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197498.027108,1794197499.076529,1.0494,HOME,home,send,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197499.076529,1794197499.400314,0.3238,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197499.400314,1794197499.717692,0.3174,HOME,home,poll,
teach_pos1to4_deep_v1,run_0001_20261109_131103,1794197499.717692,1794197500.037847,0.3202,HOME,home,poll,
scripted_v1,run_0001_20261015_173315,1792053195.6548,1792053226.907188,31.2524,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_173315,1792053226.907188,1792053226.919199,0.012,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_173315,1792053226.919199,1792053229.515176,2.596,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_173315,1792053229.515176,1792053229.837249,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_173315,1792053229.837249,1792053230.159401,0.3222,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_173315,1792053230.159401,1792053230.481239,0.3218,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_173315,1792053230.481239,1792053230.5044,0.0232,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_173315,1792053230.5044,1792053230.535117,0.0307,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_173315,1792053230.535117,1792053230.547116,0.012,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_173315,1792053230.547116,1792053233.181188,2.6341,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_173315,1792053233.181188,1792053233.203039,0.0219,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_173315,1792053233.203039,1792053237.415477,4.2124,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_173315,1792053237.415477,1792053237.427744,0.0123,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_173315,1792053237.427744,1792053240.080575,2.6528,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_173315,1792053240.080575,1792053240.40403,0.3235,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_173315,1792053240.40403,1792053240.726033,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_173315,1792053240.726033,1792053241.049234,0.3232,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_173315,1792053241.049234,1792053241.369229,0.32,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_173315,1792053241.369229,1792053241.691267,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_173315,1792053241.691267,1792053241.716362,0.0251,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_173315,1792053241.716362,1792053249.555345,7.839,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261015_173315,1792053249.555345,1792053249.577308,0.022,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_173315,1792053249.577308,1792053252.183752,2.6064,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_173315,1792053252.183752,1792053252.206163,0.0224,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_173315,1792053252.206163,1792053252.387887,0.1817,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_173315,1792053252.387887,1792053252.410234,0.0223,stage8_place,release,poll,
scripted_v1,run_0001_20261015_173315,1792053252.410234,1792053254.994229,2.584,stage8_place,release,poll,
scripted_v1,run_0001_20261015_173315,1792053254.994229,1792053255.00618,0.012,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_173315,1792053255.00618,1792053259.530291,4.5241,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261015_173315,1792053259.530291,1792053259.62419,0.0939,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_173315,1792053259.62419,1792053259.734218,0.11,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_173315,1792053259.734218,1792053259.746244,0.012,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_173315,1792053259.746244,1792053262.34016,2.5939,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_173315,1792053262.34016,1792053262.352108,0.0119,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_173315,1792053262.352108,1792053266.466275,4.1142,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_173315,1792053266.466275,1792053266.548353,0.0821,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_173315,1792053266.548353,1792053284.400549,17.8522,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_173315,1792053284.400549,1792053284.412246,0.0117,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_173315,1792053284.412246,1792053286.958338,2.5461,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_173315,1792053286.958338,1792053286.970322,0.012,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_173315,1792053286.970322,1792053298.092363,11.122,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_173315,1792053298.092363,1792053298.114414,0.0221,stage10,retreat,poll,
scripted_v1,run_0001_20261015_173315,1792053298.114414,1792053300.678408,2.564,stage10,retreat,poll,
scripted_v1,run_0001_20261015_173315,1792053300.678408,1792053300.690221,0.0118,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_173315,1792053300.690221,1792053300.712272,0.0221,stage10,retreat,poll,
scripted_v1,run_0001_20261015_173315,1792053300.712272,1792053300.724331,0.0121,stage10,retreat,poll,
scripted_v1,run_0001_20261015_173315,1792053300.724331,1792053303.341431,2.6171,stage10,retreat,poll,
scripted_v1,run_0001_20261015_173315,1792053303.341431,1792053303.353331,0.0119,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_175333,1792054413.18571,1792054444.537881,31.3522,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_175333,1792054444.537881,1792054444.54971,0.0118,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_175333,1792054444.54971,1792054447.167971,2.6183,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_175333,1792054447.167971,1792054447.488004,0.32,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_175333,1792054447.488004,1792054447.80975,0.3217,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_175333,1792054447.80975,1792054448.131619,0.3219,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_175333,1792054448.131619,1792054448.143559,0.0119,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_175333,1792054448.143559,1792054448.178097,0.0345,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_175333,1792054448.178097,1792054448.197598,0.0195,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_175333,1792054448.197598,1792054450.821652,2.6241,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_175333,1792054450.821652,1792054450.843838,0.0222,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_175333,1792054450.843838,1792054455.015744,4.1719,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_175333,1792054455.015744,1792054455.027599,0.0119,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_175333,1792054455.027599,1792054457.681036,2.6534,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_175333,1792054457.681036,1792054458.015993,0.335,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_175333,1792054458.015993,1792054458.34798,0.332,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_175333,1792054458.34798,1792054458.668306,0.3203,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_175333,1792054458.668306,1792054458.691343,0.023,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_175333,1792054458.691343,1792054471.972561,13.2812,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261015_175333,1792054471.972561,1792054471.983559,0.011,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_175333,1792054471.983559,1792054474.559661,2.5761,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_175333,1792054474.559661,1792054474.581849,0.0222,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_175333,1792054474.581849,1792054474.723596,0.1417,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_175333,1792054474.723596,1792054474.745788,0.0222,stage8_place,release,poll,
scripted_v1,run_0001_20261015_175333,1792054474.745788,1792054477.339836,2.594,stage8_place,release,poll,
scripted_v1,run_0001_20261015_175333,1792054477.339836,1792054477.351767,0.0119,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_175333,1792054477.351767,1792054477.823787,0.472,stage8_place,release,stage_change,stage
scripted_v1,run_0001_20261015_175333,1792054477.823787,1792054477.905711,0.0819,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_175333,1792054477.905711,1792054477.917631,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_175333,1792054477.917631,1792054480.501784,2.5842,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_175333,1792054480.501784,1792054480.513729,0.0119,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_175333,1792054480.513729,1792054484.627714,4.114,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_175333,1792054484.627714,1792054488.711821,4.0841,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_175333,1792054488.711821,1792054488.793705,0.0819,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_175333,1792054488.793705,1792054506.655483,17.8618,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_175333,1792054506.655483,1792054506.667375,0.0119,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_175333,1792054506.667375,1792054509.293835,2.6265,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_175333,1792054509.293835,1792054509.315764,0.0219,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_175333,1792054509.315764,1792054523.110299,13.7945,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_175333,1792054523.110299,1792054523.1421,0.0318,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054523.1421,1792054525.713972,2.5719,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054525.713972,1792054526.035994,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054526.035994,1792054526.359401,0.3234,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054526.359401,1792054526.680114,0.3207,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054526.680114,1792054527.001967,0.3219,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054527.001967,1792054527.323953,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054527.323953,1792054527.645933,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054527.645933,1792054527.967926,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054527.967926,1792054528.290105,0.3222,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054528.290105,1792054528.624248,0.3341,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054528.624248,1792054528.95635,0.3321,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054528.95635,1792054529.277053,0.3207,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054529.277053,1792054529.598801,0.3217,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054529.598801,1792054529.920113,0.3213,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054529.920113,1792054530.242828,0.3227,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054530.242828,1792054530.564113,0.3213,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054530.564113,1792054530.885903,0.3218,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054530.885903,1792054531.207927,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054531.207927,1792054531.52992,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054531.52992,1792054531.852118,0.3222,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054531.852118,1792054532.174112,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054532.174112,1792054532.496439,0.3223,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054532.496439,1792054532.818004,0.3216,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054532.818004,1792054533.139978,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054533.139978,1792054533.461899,0.3219,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054533.461899,1792054533.784097,0.3222,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054533.784097,1792054534.105879,0.3218,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054534.105879,1792054534.432242,0.3264,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054534.432242,1792054534.762177,0.3299,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054534.762177,1792054535.094299,0.3321,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_175333,1792054535.094299,1792054535.126311,0.032,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054535.126311,1792054535.159487,0.0332,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054535.159487,1792054537.763011,2.6035,stage10,retreat,poll,
scripted_v1,run_0001_20261015_175333,1792054537.763011,1792054537.785051,0.022,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_181752,1792055872.905263,1792055907.158758,34.2535,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_181752,1792055907.158758,1792055907.17966,0.0209,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_181752,1792055907.17966,1792055909.785532,2.6059,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_181752,1792055909.785532,1792055910.107874,0.3223,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_181752,1792055910.107874,1792055910.431381,0.3235,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_181752,1792055910.431381,1792055910.473906,0.0425,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_181752,1792055910.473906,1792055910.524272,0.0504,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_181752,1792055910.524272,1792055910.547498,0.0232,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_181752,1792055910.547498,1792055913.120946,2.5734,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_181752,1792055913.120946,1792055913.132799,0.0119,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_181752,1792055913.132799,1792055917.327736,4.1949,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_181752,1792055917.327736,1792055917.359458,0.0317,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055917.359458,1792055919.921984,2.5625,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055919.921984,1792055920.244765,0.3228,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055920.244765,1792055920.566732,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055920.566732,1792055920.888589,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055920.888589,1792055921.209997,0.3214,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055921.209997,1792055921.532061,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055921.532061,1792055921.853971,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055921.853971,1792055922.176287,0.3223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055922.176287,1792055922.497643,0.3214,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055922.497643,1792055922.831514,0.3339,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055922.831514,1792055923.220534,0.389,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_181752,1792055923.220534,1792055923.301397,0.0809,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_181752,1792055923.301397,1792055954.616642,31.3152,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261015_181752,1792055954.616642,1792055954.628413,0.0118,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_181752,1792055954.628413,1792055957.256665,2.6283,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_181752,1792055957.256665,1792055957.28758,0.0309,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_181752,1792055957.28758,1792055957.589079,0.3015,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_181752,1792055957.589079,1792055957.601429,0.0124,stage8_place,release,poll,
scripted_v1,run_0001_20261015_181752,1792055957.601429,1792055960.196311,2.5949,stage8_place,release,poll,
scripted_v1,run_0001_20261015_181752,1792055960.196311,1792055960.217516,0.0212,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_181752,1792055960.217516,1792055964.802056,4.5845,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261015_181752,1792055964.802056,1792055968.93566,4.1336,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_181752,1792055968.93566,1792055973.029814,4.0942,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_181752,1792055973.029814,1792055977.133908,4.1041,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_181752,1792055977.133908,1792055994.876308,17.7424,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_181752,1792055994.876308,1792055994.888005,0.0117,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_181752,1792055994.888005,1792055997.442996,2.555,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_181752,1792055997.442996,1792055997.45505,0.0121,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_181752,1792055997.45505,1792056043.14797,45.6929,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_181752,1792056043.14797,1792056043.159584,0.0116,stage10,retreat,poll,
scripted_v1,run_0001_20261015_181752,1792056043.159584,1792056045.763592,2.604,stage10,retreat,poll,
scripted_v1,run_0001_20261015_181752,1792056045.763592,1792056045.775629,0.012,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_181752,1792056045.775629,1792056045.797719,0.0221,stage10,retreat,poll,
scripted_v1,run_0001_20261015_181752,1792056045.797719,1792056045.809528,0.0118,stage10,retreat,poll,
scripted_v1,run_0001_20261015_181752,1792056045.809528,1792056048.416701,2.6072,stage10,retreat,poll,
scripted_v1,run_0001_20261015_181752,1792056048.416701,1792056048.428533,0.0118,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_182056,1792056056.870856,1792056090.274538,33.4037,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_182056,1792056090.274538,1792056090.295418,0.0209,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182056,1792056090.295418,1792056092.901286,2.6059,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182056,1792056092.901286,1792056093.232964,0.3317,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182056,1792056093.232964,1792056093.579328,0.3464,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182056,1792056093.579328,1792056093.909604,0.3303,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182056,1792056093.909604,1792056094.230099,0.3205,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182056,1792056094.230099,1792056094.2519,0.0218,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_182056,1792056094.2519,1792056094.284712,0.0328,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_182056,1792056094.284712,1792056094.305393,0.0207,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_182056,1792056094.305393,1792056096.849206,2.5438,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_182056,1792056096.849206,1792056096.861206,0.012,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_182056,1792056096.861206,1792056101.033401,4.1722,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_182056,1792056101.033401,1792056101.045312,0.0119,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182056,1792056101.045312,1792056103.900863,2.8556,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182056,1792056103.900863,1792056104.231428,0.3306,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182056,1792056104.231428,1792056104.554025,0.3226,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182056,1792056104.554025,1792056104.875724,0.3217,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182056,1792056104.875724,1792056104.89744,0.0217,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_182056,1792056104.89744,1792056112.259758,7.3623,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261015_182056,1792056112.259758,1792056112.271426,0.0117,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_182056,1792056112.271426,1792056114.868539,2.5971,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_182056,1792056114.868539,1792056114.890287,0.0217,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_182056,1792056114.890287,1792056115.091918,0.2016,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_182056,1792056115.091918,1792056115.104229,0.0123,stage8_place,release,poll,
scripted_v1,run_0001_20261015_182056,1792056115.104229,1792056117.728248,2.624,stage8_place,release,poll,
scripted_v1,run_0001_20261015_182056,1792056117.728248,1792056117.74042,0.0122,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_182056,1792056117.74042,1792056122.315114,4.5747,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261015_182056,1792056122.315114,1792056122.375631,0.0605,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182056,1792056122.375631,1792056122.507638,0.132,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182056,1792056122.507638,1792056122.519607,0.012,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182056,1792056122.519607,1792056125.119094,2.5995,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182056,1792056125.119094,1792056125.135557,0.0165,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_182056,1792056125.135557,1792056125.217462,0.0819,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182056,1792056125.217462,1792056125.359564,0.1421,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182056,1792056125.359564,1792056125.371576,0.012,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182056,1792056125.371576,1792056127.905783,2.5342,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182056,1792056127.905783,1792056127.917626,0.0118,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_182056,1792056127.917626,1792056127.979789,0.0622,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182056,1792056127.979789,1792056145.922388,17.9426,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_182056,1792056145.922388,1792056145.934148,0.0118,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_182056,1792056145.934148,1792056148.528927,2.5948,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_182056,1792056148.528927,1792056148.540966,0.012,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_182056,1792056148.540966,1792056159.872794,11.3318,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_182056,1792056159.872794,1792056159.885213,0.0124,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056159.885213,1792056162.489072,2.6039,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056162.489072,1792056162.81118,0.3221,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056162.81118,1792056163.133208,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056163.133208,1792056163.45514,0.3219,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056163.45514,1792056163.7771,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056163.7771,1792056164.089205,0.3121,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056164.089205,1792056164.411383,0.3222,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056164.411383,1792056164.733949,0.3226,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056164.733949,1792056165.055781,0.3218,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056165.055781,1792056165.377716,0.3219,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056165.377716,1792056165.699046,0.3213,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056165.699046,1792056166.021595,0.3225,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056166.021595,1792056166.333307,0.3117,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056166.333307,1792056166.655286,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056166.655286,1792056166.977336,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056166.977336,1792056167.29934,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056167.29934,1792056167.621336,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056167.621336,1792056167.933825,0.3125,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056167.933825,1792056168.255432,0.3216,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056168.255432,1792056168.5773,0.3219,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056168.5773,1792056168.899296,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056168.899296,1792056169.23341,0.3341,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056169.23341,1792056169.565048,0.3316,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056169.565048,1792056169.906471,0.3414,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056169.906471,1792056170.251393,0.3449,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056170.251393,1792056170.569812,0.3184,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056170.569812,1792056170.891699,0.3219,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_182056,1792056170.891699,1792056170.913785,0.0221,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056170.913785,1792056170.935832,0.022,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056170.935832,1792056173.554242,2.6184,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182056,1792056173.554242,1792056173.574898,0.0207,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_182552,1792056352.87876,1792056387.031458,34.1527,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_182552,1792056387.031458,1792056387.043106,0.0116,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056387.043106,1792056389.650943,2.6078,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056389.650943,1792056389.972458,0.3215,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056389.972458,1792056390.293373,0.3209,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056390.293373,1792056390.615266,0.3219,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056390.615266,1792056390.627345,0.0121,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_182552,1792056390.627345,1792056390.669399,0.0421,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_182552,1792056390.669399,1792056390.691387,0.022,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_182552,1792056390.691387,1792056393.339341,2.648,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_182552,1792056393.339341,1792056393.671166,0.3318,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_182552,1792056393.671166,1792056393.704959,0.0338,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_182552,1792056393.704959,1792056397.891506,4.1865,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_182552,1792056397.891506,1792056397.908408,0.0169,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056397.908408,1792056400.527478,2.6191,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056400.527478,1792056400.84938,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056400.84938,1792056401.16143,0.312,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056401.16143,1792056401.483422,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056401.483422,1792056401.806398,0.323,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056401.806398,1792056402.127528,0.3211,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056402.127528,1792056402.140072,0.0125,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_182552,1792056402.140072,1792056418.561698,16.4216,stage6,carry_lift,gripper,gripper_cmd;gripper
scripted_v1,run_0001_20261015_182552,1792056418.561698,1792056418.58375,0.0221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056418.58375,1792056421.245451,2.6617,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056421.245451,1792056421.593403,0.348,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_182552,1792056421.593403,1792056421.613089,0.0197,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_182552,1792056421.613089,1792056446.015158,24.4021,stage6,carry_lift,stage_change,stage;stage
scripted_v1,run_0001_20261015_182552,1792056446.015158,1792056446.027004,0.0118,stage3_approach_pick_a2,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056446.027004,1792056448.686012,2.659,stage3_approach_pick_a2,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056448.686012,1792056449.034483,0.3485,stage3_approach_pick_a2,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056449.034483,1792056449.050026,0.0155,stage3_approach_pick_a2,approach,send,commanded
scripted_v1,run_0001_20261015_182552,1792056449.050026,1792056449.078968,0.0289,stage3_approach_pick_a2,approach,stage_change,stage
scripted_v1,run_0001_20261015_182552,1792056449.078968,1792056449.090868,0.0119,stage4_pick_a2,grasp,poll,
scripted_v1,run_0001_20261015_182552,1792056449.090868,1792056451.715644,2.6248,stage4_pick_a2,grasp,poll,
scripted_v1,run_0001_20261015_182552,1792056451.715644,1792056451.726872,0.0112,stage4_pick_a2,grasp,send,commanded
scripted_v1,run_0001_20261015_182552,1792056451.726872,1792056455.909825,4.183,stage4_pick_a2,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_182552,1792056455.909825,1792056455.934278,0.0245,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056455.934278,1792056458.502388,2.5681,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056458.502388,1792056458.827838,0.3254,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056458.827838,1792056459.139664,0.3118,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056459.139664,1792056459.461229,0.3216,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056459.461229,1792056459.783357,0.3221,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056459.783357,1792056460.105218,0.3219,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056460.105218,1792056460.117189,0.012,stage6_a2,other:STAGE6_A2,send,commanded
scripted_v1,run_0001_20261015_182552,1792056460.117189,1792056508.569884,48.4527,stage6_a2,other:STAGE6_A2,gripper,gripper_cmd;gripper
scripted_v1,run_0001_20261015_182552,1792056508.569884,1792056508.581815,0.0119,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056508.581815,1792056511.303029,2.7212,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056511.303029,1792056511.657822,0.3548,stage6_a2,other:STAGE6_A2,poll,
scripted_v1,run_0001_20261015_182552,1792056511.657822,1792056511.682283,0.0245,stage6_a2,other:STAGE6_A2,send,commanded
scripted_v1,run_0001_20261015_182552,1792056511.682283,1792056535.24643,23.5641,stage6_a2,other:STAGE6_A2,stage_change,stage;stage
scripted_v1,run_0001_20261015_182552,1792056535.24643,1792056535.278404,0.032,stage3_approach_pick_a3,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056535.278404,1792056537.927242,2.6488,stage3_approach_pick_a3,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056537.927242,1792056538.803516,0.8763,stage3_approach_pick_a3,approach,poll,
scripted_v1,run_0001_20261015_182552,1792056538.803516,1792056538.815296,0.0118,stage3_approach_pick_a3,approach,send,commanded
scripted_v1,run_0001_20261015_182552,1792056538.815296,1792056538.858284,0.043,stage3_approach_pick_a3,approach,stage_change,stage
scripted_v1,run_0001_20261015_182552,1792056538.858284,1792056538.869085,0.0108,stage4_pick_a3,grasp,poll,
scripted_v1,run_0001_20261015_182552,1792056538.869085,1792056541.49382,2.6247,stage4_pick_a3,grasp,poll,
scripted_v1,run_0001_20261015_182552,1792056541.49382,1792056541.515749,0.0219,stage4_pick_a3,grasp,send,commanded
scripted_v1,run_0001_20261015_182552,1792056541.515749,1792056545.707444,4.1917,stage4_pick_a3,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_182552,1792056545.707444,1792056545.719057,0.0116,stage6_a3,other:STAGE6_A3,poll,
scripted_v1,run_0001_20261015_182552,1792056545.719057,1792056548.35601,2.637,stage6_a3,other:STAGE6_A3,poll,
scripted_v1,run_0001_20261015_182552,1792056548.35601,1792056548.68007,0.3241,stage6_a3,other:STAGE6_A3,poll,
scripted_v1,run_0001_20261015_182552,1792056548.68007,1792056548.999359,0.3193,stage6_a3,other:STAGE6_A3,poll,
scripted_v1,run_0001_20261015_182552,1792056548.999359,1792056549.336146,0.3368,stage6_a3,other:STAGE6_A3,poll,
scripted_v1,run_0001_20261015_182552,1792056549.336146,1792056549.652241,0.3161,stage6_a3,other:STAGE6_A3,poll,
scripted_v1,run_0001_20261015_182552,1792056549.652241,1792056549.673446,0.0212,stage6_a3,other:STAGE6_A3,send,commanded
scripted_v1,run_0001_20261015_182552,1792056549.673446,1792056556.417344,6.7439,stage6_a3,other:STAGE6_A3,stage_change,stage
scripted_v1,run_0001_20261015_182552,1792056556.417344,1792056556.437514,0.0202,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_182552,1792056556.437514,1792056559.027229,2.5897,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_182552,1792056559.027229,1792056559.046054,0.0188,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_182552,1792056559.046054,1792056559.227798,0.1817,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_182552,1792056559.227798,1792056559.240366,0.0126,stage8_place,release,poll,
scripted_v1,run_0001_20261015_182552,1792056559.240366,1792056561.814222,2.5739,stage8_place,release,poll,
scripted_v1,run_0001_20261015_182552,1792056561.814222,1792056561.836215,0.022,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_182552,1792056561.836215,1792056566.389757,4.5535,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261015_182552,1792056566.389757,1792056566.451825,0.0621,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056566.451825,1792056566.603806,0.152,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056566.603806,1792056566.615692,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056566.615692,1792056569.199697,2.584,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056569.199697,1792056569.211773,0.0121,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_182552,1792056569.211773,1792056569.283711,0.0719,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056569.283711,1792056569.366,0.0823,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056569.366,1792056569.377675,0.0117,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056569.377675,1792056571.91147,2.5338,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056571.91147,1792056571.926481,0.015,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_182552,1792056571.926481,1792056576.017411,4.0909,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_182552,1792056576.017411,1792056576.098454,0.081,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056576.098454,1792056576.208998,0.1105,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056576.208998,1792056576.230839,0.0218,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056576.230839,1792056578.777935,2.5471,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056578.777935,1792056578.799783,0.0218,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_182552,1792056578.799783,1792056582.914093,4.1143,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_182552,1792056582.914093,1792056582.995827,0.0817,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_182552,1792056582.995827,1792056600.828307,17.8325,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_182552,1792056600.828307,1792056600.84118,0.0129,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_182552,1792056600.84118,1792056603.376677,2.5355,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_182552,1792056603.376677,1792056603.392965,0.0163,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_182552,1792056603.392965,1792056614.26013,10.8672,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_182552,1792056614.26013,1792056614.272601,0.0125,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056614.272601,1792056616.876394,2.6038,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056616.876394,1792056616.906463,0.0301,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_182552,1792056616.906463,1792056616.939682,0.0332,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056616.939682,1792056616.96164,0.022,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056616.96164,1792056619.57942,2.6178,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056619.57942,1792056619.901461,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056619.901461,1792056620.225553,0.3241,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056620.225553,1792056620.545646,0.3201,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056620.545646,1792056620.867938,0.3223,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056620.867938,1792056621.194488,0.3266,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056621.194488,1792056621.511578,0.3171,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056621.511578,1792056621.833421,0.3218,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056621.833421,1792056622.167709,0.3343,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056622.167709,1792056622.49923,0.3315,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056622.49923,1792056622.83168,0.3325,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056622.83168,1792056623.163796,0.3321,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056623.163796,1792056623.495454,0.3317,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056623.495454,1792056623.816307,0.3209,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056623.816307,1792056624.137684,0.3214,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056624.137684,1792056624.459711,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056624.459711,1792056624.781821,0.3221,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056624.781821,1792056625.103587,0.3218,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056625.103587,1792056625.425918,0.3223,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056625.425918,1792056625.747495,0.3216,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056625.747495,1792056626.069518,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056626.069518,1792056626.393941,0.3244,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056626.393941,1792056626.714413,0.3205,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056626.714413,1792056627.03575,0.3213,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056627.03575,1792056627.357937,0.3222,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056627.357937,1792056627.679501,0.3216,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056627.679501,1792056628.001518,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056628.001518,1792056628.323624,0.3221,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056628.323624,1792056628.645718,0.3221,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056628.645718,1792056628.980139,0.3344,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056628.980139,1792056629.312047,0.3319,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056629.312047,1792056629.632439,0.3204,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056629.632439,1792056629.953649,0.3212,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056629.953649,1792056630.275661,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056630.275661,1792056630.597721,0.3221,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056630.597721,1792056630.919709,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056630.919709,1792056631.23153,0.3118,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056631.23153,1792056631.553562,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056631.553562,1792056631.875603,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056631.875603,1792056632.197652,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056632.197652,1792056632.520267,0.3226,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056632.520267,1792056632.84243,0.3222,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056632.84243,1792056633.163682,0.3213,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056633.163682,1792056633.486413,0.3227,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056633.486413,1792056633.807813,0.3214,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056633.807813,1792056634.12984,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056634.12984,1792056634.451476,0.3216,stage10,retreat,poll,
scripted_v1,run_0001_20261015_182552,1792056634.451476,1792056634.786078,0.3346,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_183310,1792056790.633836,1792056790.645616,0.0118,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056790.645616,1792056790.657609,0.012,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056790.657609,1792056793.211054,2.5534,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056793.211054,1792056793.54596,0.3349,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056793.54596,1792056793.878171,0.3322,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056793.878171,1792056794.211963,0.3338,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056794.211963,1792056794.530646,0.3187,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056794.530646,1792056794.852073,0.3214,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056794.852073,1792056795.163828,0.3118,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056795.163828,1792056795.485771,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056795.485771,1792056795.797792,0.312,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056795.797792,1792056796.119795,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056796.119795,1792056796.442021,0.3222,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056796.442021,1792056796.764044,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056796.764044,1792056797.08579,0.3217,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056797.08579,1792056797.408284,0.3225,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056797.408284,1792056797.729997,0.3217,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056797.729997,1792056798.052449,0.3225,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056798.052449,1792056798.373907,0.3215,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056798.373907,1792056798.696051,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056798.696051,1792056799.017923,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056799.017923,1792056799.349131,0.3312,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056799.349131,1792056799.68544,0.3363,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056799.68544,1792056800.017275,0.3318,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056800.017275,1792056800.338558,0.3213,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056800.338558,1792056800.658024,0.3195,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056800.658024,1792056800.979907,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056800.979907,1792056801.301775,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056801.301775,1792056801.623956,0.3222,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056801.623956,1792056801.946508,0.3226,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056801.946508,1792056802.267848,0.3213,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056802.267848,1792056802.589952,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056802.589952,1792056802.911901,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056802.911901,1792056808.234367,5.3225,stage1,home,send,commanded
scripted_v1,run_0001_20261015_183310,1792056808.234367,1792056810.767925,2.5336,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056810.767925,1792056811.090131,0.3222,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056811.090131,1792056811.424245,0.3341,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056811.424245,1792056811.756707,0.3325,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056811.756707,1792056812.076655,0.3199,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056812.076655,1792056812.398418,0.3218,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056812.398418,1792056812.720213,0.3218,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056812.720213,1792056813.042297,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056813.042297,1792056813.364096,0.3218,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056813.364096,1792056813.676232,0.3121,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056813.676232,1792056813.998073,0.3218,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056813.998073,1792056814.320619,0.3225,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056814.320619,1792056814.643035,0.3224,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056814.643035,1792056814.974731,0.3317,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056814.974731,1792056815.296142,0.3214,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056815.296142,1792056815.618118,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056815.618118,1792056815.942419,0.3243,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056815.942419,1792056816.262006,0.3196,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056816.262006,1792056816.583959,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056816.583959,1792056816.906285,0.3223,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056816.906285,1792056817.240449,0.3342,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056817.240449,1792056817.57279,0.3323,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056817.57279,1792056817.89286,0.3201,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056817.89286,1792056818.214983,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056818.214983,1792056818.536299,0.3213,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056818.536299,1792056818.858206,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056818.858206,1792056819.180143,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056819.180143,1792056819.502154,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056819.502154,1792056819.824081,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056819.824081,1792056820.146138,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056820.146138,1792056820.468164,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_183310,1792056820.468164,1792056820.790502,0.3223,stage1,home,send,commanded
scripted_v1,run_0001_20261015_183310,1792056820.790502,1792056853.292924,32.5024,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_183310,1792056853.292924,1792056853.317626,0.0247,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_183310,1792056853.317626,1792056855.920577,2.603,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_183310,1792056855.920577,1792056856.243456,0.3229,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_183310,1792056856.243456,1792056856.564828,0.3214,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_183310,1792056856.564828,1792056856.886682,0.3219,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_183310,1792056856.886682,1792056857.2086,0.3219,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_183310,1792056857.2086,1792056857.520642,0.312,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_183310,1792056857.520642,1792056857.842695,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_183310,1792056857.842695,1792056857.854605,0.0119,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_183310,1792056857.854605,1792056857.936528,0.0819,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_183310,1792056857.936528,1792056857.948509,0.012,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_183310,1792056857.948509,1792056860.48268,2.5342,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_183310,1792056860.48268,1792056860.504623,0.0219,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_183310,1792056860.504623,1792056864.709101,4.2045,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_183310,1792056864.709101,1792056864.735772,0.0267,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056864.735772,1792056867.362697,2.6269,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056867.362697,1792056867.684711,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056867.684711,1792056868.007337,0.3226,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056868.007337,1792056868.329042,0.3217,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056868.329042,1792056868.651472,0.3224,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056868.651472,1792056868.972822,0.3213,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056868.972822,1792056869.294989,0.3222,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056869.294989,1792056869.617466,0.3225,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056869.617466,1792056869.958442,0.341,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_183310,1792056869.958442,1792056869.979965,0.0215,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_183310,1792056869.979965,1792056999.897908,129.9179,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261015_183310,1792056999.897908,1792056999.929006,0.0311,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_183310,1792056999.929006,1792057002.532832,2.6038,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_183310,1792057002.532832,1792057002.854414,0.3216,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_183310,1792057002.854414,1792057003.176965,0.3226,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_183310,1792057003.176965,1792057003.499079,0.3221,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_183310,1792057003.499079,1792057003.520407,0.0213,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_183310,1792057003.520407,1792057003.702559,0.1822,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_183310,1792057003.702559,1792057003.724589,0.022,stage8_place,release,poll,
scripted_v1,run_0001_20261015_183310,1792057003.724589,1792057006.309106,2.5845,stage8_place,release,poll,
scripted_v1,run_0001_20261015_183310,1792057006.309106,1792057006.321195,0.0121,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_183310,1792057006.321195,1792057010.954716,4.6335,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261015_183310,1792057010.954716,1792057011.026436,0.0717,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057011.026436,1792057011.178783,0.1523,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057011.178783,1792057011.190657,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057011.190657,1792057013.784714,2.5941,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057013.784714,1792057013.796575,0.0119,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_183310,1792057013.796575,1792057013.858545,0.062,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057013.858545,1792057013.940624,0.0821,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057013.940624,1792057013.952591,0.012,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057013.952591,1792057016.518779,2.5662,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057016.518779,1792057016.550765,0.032,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_183310,1792057016.550765,1792057016.636122,0.0854,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057016.636122,1792057016.76217,0.126,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057016.76217,1792057016.794356,0.0322,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057016.794356,1792057019.329891,2.5355,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057019.329891,1792057019.351046,0.0212,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_183310,1792057019.351046,1792057023.452968,4.1019,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_183310,1792057023.452968,1792057023.571646,0.1187,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_183310,1792057023.571646,1792057041.510622,17.939,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_183310,1792057041.510622,1792057041.531906,0.0213,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_183310,1792057041.531906,1792057044.168771,2.6369,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_183310,1792057044.168771,1792057044.189087,0.0203,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_183310,1792057044.189087,1792057078.491844,34.3028,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_183310,1792057078.491844,1792057078.504286,0.0124,stage10,retreat,poll,
scripted_v1,run_0001_20261015_183310,1792057078.504286,1792057081.047578,2.5433,stage10,retreat,poll,
scripted_v1,run_0001_20261015_183310,1792057081.047578,1792057081.069637,0.0221,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_183310,1792057081.069637,1792057081.094638,0.025,stage10,retreat,poll,
scripted_v1,run_0001_20261015_183310,1792057081.094638,1792057081.113556,0.0189,stage10,retreat,poll,
scripted_v1,run_0001_20261015_183310,1792057081.113556,1792057083.7406,2.627,stage10,retreat,poll,
scripted_v1,run_0001_20261015_183310,1792057083.7406,1792057083.752491,0.0119,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_185536,1792058136.761079,1792058136.782992,0.0219,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058136.782992,1792058136.805096,0.0221,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058136.805096,1792058139.339221,2.5341,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058139.339221,1792058139.661182,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058139.661182,1792058139.983057,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058139.983057,1792058140.317496,0.3344,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058140.317496,1792058140.65129,0.3338,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058140.65129,1792058140.969626,0.3183,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058140.969626,1792058141.291927,0.3223,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058141.291927,1792058141.613224,0.3213,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058141.613224,1792058141.935251,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058141.935251,1792058142.257248,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058142.257248,1792058142.579026,0.3218,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058142.579026,1792058142.901158,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058142.901158,1792058143.223147,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058143.223147,1792058143.54521,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058143.54521,1792058143.867252,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058143.867252,1792058144.189607,0.3224,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058144.189607,1792058144.511282,0.3217,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058144.511282,1792058144.823139,0.3119,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058144.823139,1792058145.145174,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058145.145174,1792058145.457406,0.3122,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058145.457406,1792058145.779307,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058145.779307,1792058146.113285,0.334,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058146.113285,1792058146.445604,0.3323,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058146.445604,1792058146.777445,0.3318,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058146.777445,1792058147.098426,0.321,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058147.098426,1792058147.41937,0.3209,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058147.41937,1792058147.741295,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058147.741295,1792058148.053182,0.3119,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058148.053182,1792058148.375302,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058148.375302,1792058148.697428,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058148.697428,1792058149.019114,0.3217,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058149.019114,1792058149.341298,0.3222,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058149.341298,1792058154.66332,5.322,stage1,home,send,commanded
scripted_v1,run_0001_20261015_185536,1792058154.66332,1792058157.207407,2.5441,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058157.207407,1792058157.530471,0.3231,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058157.530471,1792058157.861054,0.3306,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058157.861054,1792058158.195615,0.3346,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058158.195615,1792058158.527713,0.3321,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058158.527713,1792058158.84772,0.32,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058158.84772,1792058159.171008,0.3233,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058159.171008,1792058159.491443,0.3204,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058159.491443,1792058159.81346,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058159.81346,1792058160.125248,0.3118,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058160.125248,1792058160.447251,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058160.447251,1792058160.769392,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058160.769392,1792058161.091416,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058161.091416,1792058161.413462,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058161.413462,1792058161.735771,0.3223,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058161.735771,1792058162.057479,0.3217,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058162.057479,1792058162.379323,0.3218,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058162.379323,1792058162.701493,0.3222,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058162.701493,1792058163.023482,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058163.023482,1792058163.34535,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058163.34535,1792058163.668487,0.3231,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058163.668487,1792058164.00204,0.3336,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058164.00204,1792058164.33417,0.3321,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058164.33417,1792058164.654295,0.3201,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058164.654295,1792058164.97551,0.3212,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058164.97551,1792058165.29743,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058165.29743,1792058165.619585,0.3222,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058165.619585,1792058165.94152,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058165.94152,1792058166.263557,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058166.263557,1792058166.585475,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058166.585475,1792058166.907475,0.322,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058166.907475,1792058167.229543,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261015_185536,1792058167.229543,1792058167.552045,0.3225,stage1,home,send,commanded
scripted_v1,run_0001_20261015_185536,1792058167.552045,1792058199.033555,31.4815,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_185536,1792058199.033555,1792058199.065301,0.0317,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_185536,1792058199.065301,1792058201.671811,2.6065,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_185536,1792058201.671811,1792058201.99398,0.3222,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_185536,1792058201.99398,1792058202.316123,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_185536,1792058202.316123,1792058202.638213,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_185536,1792058202.638213,1792058202.960592,0.3224,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_185536,1792058202.960592,1792058202.982555,0.022,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_185536,1792058202.982555,1792058203.01446,0.0319,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_185536,1792058203.01446,1792058203.026639,0.0122,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_185536,1792058203.026639,1792058205.682146,2.6555,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_185536,1792058205.682146,1792058205.71445,0.0323,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_185536,1792058205.71445,1792058209.894149,4.1797,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_185536,1792058209.894149,1792058209.905785,0.0116,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_185536,1792058209.905785,1792058212.539927,2.6341,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_185536,1792058212.539927,1792058212.862286,0.3224,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_185536,1792058212.862286,1792058213.184058,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_185536,1792058213.184058,1792058213.506318,0.3223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_185536,1792058213.506318,1792058213.828087,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_185536,1792058213.828087,1792058214.139615,0.3115,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_185536,1792058214.139615,1792058214.462154,0.3225,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_185536,1792058214.462154,1792058214.473875,0.0117,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_185536,1792058214.473875,1792058224.606524,10.1326,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261015_185536,1792058224.606524,1792058224.628317,0.0218,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_185536,1792058224.628317,1792058227.224527,2.5962,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_185536,1792058227.224527,1792058227.236229,0.0117,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_185536,1792058227.236229,1792058227.408197,0.172,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_185536,1792058227.408197,1792058227.420232,0.012,stage8_place,release,poll,
scripted_v1,run_0001_20261015_185536,1792058227.420232,1792058229.994243,2.574,stage8_place,release,poll,
scripted_v1,run_0001_20261015_185536,1792058229.994243,1792058230.016199,0.022,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_185536,1792058230.016199,1792058234.5959,4.5797,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261015_185536,1792058234.5959,1792058234.689594,0.0937,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058234.689594,1792058234.853527,0.1639,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058234.853527,1792058234.87564,0.0221,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058234.87564,1792058237.420326,2.5447,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058237.420326,1792058237.43226,0.0119,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_185536,1792058237.43226,1792058241.536382,4.1041,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_185536,1792058241.536382,1792058241.609169,0.0728,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058241.609169,1792058241.720414,0.1112,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058241.720414,1792058241.732424,0.012,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058241.732424,1792058244.296818,2.5644,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058244.296818,1792058244.310291,0.0135,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_185536,1792058244.310291,1792058248.372588,4.0623,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_185536,1792058248.372588,1792058252.458872,4.0863,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_185536,1792058252.458872,1792058252.548147,0.0893,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058252.548147,1792058252.669866,0.1217,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058252.669866,1792058252.691978,0.0221,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058252.691978,1792058255.236602,2.5446,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058255.236602,1792058255.25869,0.0221,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_185536,1792058255.25869,1792058255.341098,0.0824,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_185536,1792058255.341098,1792058273.273038,17.9319,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_185536,1792058273.273038,1792058273.288789,0.0158,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_185536,1792058273.288789,1792058275.903299,2.6145,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_185536,1792058275.903299,1792058275.935068,0.0318,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_185536,1792058275.935068,1792058289.325372,13.3903,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_185536,1792058289.325372,1792058289.337223,0.0119,stage10,retreat,poll,
scripted_v1,run_0001_20261015_185536,1792058289.337223,1792058291.951002,2.6138,stage10,retreat,poll,
scripted_v1,run_0001_20261015_185536,1792058291.951002,1792058291.963844,0.0128,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_185536,1792058291.963844,1792058291.984961,0.0211,stage10,retreat,poll,
scripted_v1,run_0001_20261015_185536,1792058291.984961,1792058291.996992,0.012,stage10,retreat,poll,
scripted_v1,run_0001_20261015_185536,1792058291.996992,1792058294.604345,2.6074,stage10,retreat,poll,
scripted_v1,run_0001_20261015_185536,1792058294.604345,1792058294.617889,0.0135,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_193907,1792060747.228239,1792060779.631579,32.4033,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_193907,1792060779.631579,1792060779.652979,0.0214,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_193907,1792060779.652979,1792060782.248921,2.5959,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_193907,1792060782.248921,1792060782.583322,0.3344,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_193907,1792060782.583322,1792060782.915466,0.3321,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_193907,1792060782.915466,1792060783.236033,0.3206,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_193907,1792060783.236033,1792060783.560147,0.3241,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_193907,1792060783.560147,1792060783.878826,0.3187,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_193907,1792060783.878826,1792060783.891141,0.0123,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_193907,1792060783.891141,1792060783.925027,0.0339,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_193907,1792060783.925027,1792060783.94494,0.0199,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_193907,1792060783.94494,1792060786.480741,2.5358,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_193907,1792060786.480741,1792060786.502977,0.0222,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_193907,1792060786.502977,1792060790.694256,4.1913,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_193907,1792060790.694256,1792060790.705969,0.0117,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060790.705969,1792060793.340973,2.635,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060793.340973,1792060793.663153,0.3222,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060793.663153,1792060793.985172,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060793.985172,1792060794.319514,0.3343,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060794.319514,1792060794.647333,0.3278,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060794.647333,1792060794.976367,0.329,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060794.976367,1792060795.293964,0.3176,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060795.293964,1792060795.615234,0.3213,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060795.615234,1792060795.937144,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060795.937144,1792060796.259121,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060796.259121,1792060796.581128,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060796.581128,1792060796.893514,0.3124,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060796.893514,1792060797.215266,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060797.215266,1792060797.537189,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060797.537189,1792060797.859299,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060797.859299,1792060798.182272,0.323,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060798.182272,1792060798.503377,0.3211,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060798.503377,1792060798.825483,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060798.825483,1792060799.147131,0.3216,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060799.147131,1792060799.469227,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060799.469227,1792060799.791092,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060799.791092,1792060800.122506,0.3314,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060800.122506,1792060800.457902,0.3354,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060800.457902,1792060800.791045,0.3331,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060800.791045,1792060801.109832,0.3188,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_193907,1792060801.109832,1792060801.431386,0.3216,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_193907,1792060801.431386,1792060807.822998,6.3916,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261015_193907,1792060807.822998,1792060807.835136,0.0121,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_193907,1792060807.835136,1792060810.41114,2.576,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_193907,1792060810.41114,1792060810.423097,0.012,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_193907,1792060810.423097,1792060810.61551,0.1924,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_193907,1792060810.61551,1792060810.627077,0.0116,stage8_place,release,poll,
scripted_v1,run_0001_20261015_193907,1792060810.627077,1792060813.221171,2.5941,stage8_place,release,poll,
scripted_v1,run_0001_20261015_193907,1792060813.221171,1792060813.243311,0.0221,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_193907,1792060813.243311,1792060817.836699,4.5934,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261015_193907,1792060817.836699,1792060817.916234,0.0795,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060817.916234,1792060818.028557,0.1123,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060818.028557,1792060818.050662,0.0221,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060818.050662,1792060820.647244,2.5966,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060820.647244,1792060820.659009,0.0118,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_193907,1792060820.659009,1792060824.763865,4.1049,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_193907,1792060824.763865,1792060824.847011,0.0831,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060824.847011,1792060824.95735,0.1103,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060824.95735,1792060824.969266,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060824.969266,1792060827.534533,2.5653,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060827.534533,1792060827.555723,0.0212,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_193907,1792060827.555723,1792060831.66893,4.1132,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_193907,1792060831.66893,1792060831.751122,0.0822,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060831.751122,1792060831.843218,0.0921,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060831.843218,1792060831.855318,0.0121,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060831.855318,1792060834.529405,2.6741,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060834.529405,1792060834.55133,0.0219,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_193907,1792060834.55133,1792060838.655309,4.104,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_193907,1792060838.655309,1792060838.717499,0.0622,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_193907,1792060838.717499,1792060856.579479,17.862,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_193907,1792060856.579479,1792060856.593253,0.0138,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_193907,1792060856.593253,1792060859.137577,2.5443,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_193907,1792060859.137577,1792060859.150788,0.0132,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_193907,1792060859.150788,1792060885.591653,26.4409,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_193907,1792060885.591653,1792060885.603633,0.012,stage10,retreat,poll,
scripted_v1,run_0001_20261015_193907,1792060885.603633,1792060888.217594,2.614,stage10,retreat,poll,
scripted_v1,run_0001_20261015_193907,1792060888.217594,1792060888.239634,0.022,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_193907,1792060888.239634,1792060888.266447,0.0268,stage10,retreat,poll,
scripted_v1,run_0001_20261015_193907,1792060888.266447,1792060888.283383,0.0169,stage10,retreat,poll,
scripted_v1,run_0001_20261015_193907,1792060888.283383,1792060890.890438,2.6071,stage10,retreat,poll,
scripted_v1,run_0001_20261015_193907,1792060890.890438,1792060890.902511,0.0121,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_194135,1792060895.336008,1792060927.166794,31.8308,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_194135,1792060927.166794,1792060927.178791,0.012,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_194135,1792060927.178791,1792060955.843523,28.6647,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_194135,1792060955.843523,1792060955.925127,0.0816,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_194135,1792060955.925127,1792060955.948422,0.0233,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_194135,1792060955.948422,1792060958.480976,2.5326,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_194135,1792060958.480976,1792060958.492929,0.012,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_194135,1792060958.492929,1792060962.705108,4.2122,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_194135,1792060962.705108,1792060962.716846,0.0117,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194135,1792060962.716846,1792060965.360324,2.6435,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194135,1792060965.360324,1792060965.685299,0.325,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194135,1792060965.685299,1792060966.017406,0.3321,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194135,1792060966.017406,1792060966.049408,0.032,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_194135,1792060966.049408,1792060974.889125,8.8397,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261015_194135,1792060974.889125,1792060974.900834,0.0117,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_194135,1792060974.900834,1792060977.514632,2.6138,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_194135,1792060977.514632,1792060977.53666,0.022,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_194135,1792060977.53666,1792060977.713155,0.1765,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_194135,1792060977.713155,1792060977.735696,0.0225,stage8_place,release,poll,
scripted_v1,run_0001_20261015_194135,1792060977.735696,1792060980.323675,2.588,stage8_place,release,poll,
scripted_v1,run_0001_20261015_194135,1792060980.323675,1792060980.345545,0.0219,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_194135,1792060980.345545,1792060984.867847,4.5223,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261015_194135,1792060984.867847,1792060984.959832,0.092,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060984.959832,1792060985.0718,0.112,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060985.0718,1792060985.093731,0.0219,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060985.093731,1792060987.636701,2.543,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060987.636701,1792060987.65877,0.0221,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194135,1792060987.65877,1792060991.732007,4.0732,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194135,1792060991.732007,1792060991.823992,0.092,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060991.823992,1792060991.995932,0.1719,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060991.995932,1792060992.007733,0.0118,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060992.007733,1792060994.561195,2.5535,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060994.561195,1792060994.582976,0.0218,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194135,1792060994.582976,1792060998.666587,4.0836,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194135,1792060998.666587,1792060998.748627,0.082,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060998.748627,1792060998.850394,0.1018,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060998.850394,1792060998.872556,0.0222,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792060998.872556,1792061001.455582,2.583,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792061001.455582,1792061001.475385,0.0198,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194135,1792061001.475385,1792061005.591795,4.1164,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194135,1792061005.591795,1792061009.675317,4.0835,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194135,1792061009.675317,1792061009.747268,0.072,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194135,1792061009.747268,1792061027.608715,17.8614,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_194135,1792061027.608715,1792061027.620801,0.0121,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_194135,1792061027.620801,1792061030.236633,2.6158,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_194135,1792061030.236633,1792061030.248469,0.0118,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_194135,1792061030.248469,1792061043.560392,13.3119,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_194135,1792061043.560392,1792061043.582385,0.022,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194135,1792061043.582385,1792061046.217027,2.6346,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194135,1792061046.217027,1792061046.24342,0.0264,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_194135,1792061046.24342,1792061046.261364,0.0179,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194135,1792061046.261364,1792061046.273883,0.0125,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194135,1792061046.273883,1792061048.939222,2.6653,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194135,1792061048.939222,1792061049.262177,0.323,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194135,1792061049.262177,1792061049.284094,0.0219,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_194420,1792061060.387727,1792061091.937849,31.5501,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261015_194420,1792061091.937849,1792061091.949318,0.0115,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_194420,1792061091.949318,1792061094.546314,2.597,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_194420,1792061094.546314,1792061094.868456,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_194420,1792061094.868456,1792061095.191572,0.3231,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_194420,1792061095.191572,1792061095.524863,0.3333,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_194420,1792061095.524863,1792061095.856683,0.3318,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_194420,1792061095.856683,1792061096.18295,0.3263,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261015_194420,1792061096.18295,1792061096.219554,0.0366,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261015_194420,1792061096.219554,1792061096.250739,0.0312,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261015_194420,1792061096.250739,1792061096.262691,0.012,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_194420,1792061096.262691,1792061098.837401,2.5747,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_194420,1792061098.837401,1792061099.159997,0.3226,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261015_194420,1792061099.159997,1792061099.181737,0.0217,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261015_194420,1792061099.181737,1792061103.384096,4.2024,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261015_194420,1792061103.384096,1792061103.395823,0.0117,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061103.395823,1792061105.950345,2.5545,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061105.950345,1792061106.272297,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061106.272297,1792061106.606925,0.3346,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061106.606925,1792061106.938759,0.3318,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061106.938759,1792061107.27072,0.332,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061107.27072,1792061107.590651,0.3199,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061107.590651,1792061107.914262,0.3236,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061107.914262,1792061108.235014,0.3208,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061108.235014,1792061108.556575,0.3216,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061108.556575,1792061108.878514,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061108.878514,1792061109.200571,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061109.200571,1792061109.522431,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061109.522431,1792061109.84531,0.3229,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061109.84531,1792061110.166494,0.3212,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061110.166494,1792061110.488498,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061110.488498,1792061110.810786,0.3223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061110.810786,1792061111.133064,0.3223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061111.133064,1792061111.454518,0.3215,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061111.454518,1792061111.776587,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061111.776587,1792061112.098531,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061112.098531,1792061112.420317,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061112.420317,1792061112.754977,0.3347,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061112.754977,1792061113.086724,0.3317,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061113.086724,1792061113.418664,0.3319,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061113.418664,1792061113.738871,0.3202,stage6,carry_lift,poll,
scripted_v1,run_0001_20261015_194420,1792061113.738871,1792061114.060875,0.322,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261015_194420,1792061114.060875,1792061120.832781,6.7719,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261015_194420,1792061120.832781,1792061120.854485,0.0217,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_194420,1792061120.854485,1792061123.410424,2.5559,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261015_194420,1792061123.410424,1792061123.422414,0.012,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261015_194420,1792061123.422414,1792061123.58434,0.1619,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261015_194420,1792061123.58434,1792061123.596297,0.012,stage8_place,release,poll,
scripted_v1,run_0001_20261015_194420,1792061123.596297,1792061126.180375,2.5841,stage8_place,release,poll,
scripted_v1,run_0001_20261015_194420,1792061126.180375,1792061126.192445,0.0121,stage8_place,release,send,commanded
scripted_v1,run_0001_20261015_194420,1792061126.192445,1792061126.694344,0.5019,stage8_place,release,stage_change,stage
scripted_v1,run_0001_20261015_194420,1792061126.694344,1792061126.806435,0.1121,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061126.806435,1792061126.818347,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061126.818347,1792061129.412423,2.5941,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061129.412423,1792061129.424316,0.0119,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194420,1792061129.424316,1792061133.508444,4.0841,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194420,1792061133.508444,1792061133.592434,0.084,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061133.592434,1792061133.69245,0.1,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061133.69245,1792061133.714603,0.0222,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061133.714603,1792061136.299124,2.5845,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061136.299124,1792061136.320394,0.0213,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194420,1792061136.320394,1792061140.47505,4.1547,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194420,1792061140.47505,1792061140.557168,0.0821,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061140.557168,1792061140.668521,0.1114,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061140.668521,1792061140.680518,0.012,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061140.680518,1792061143.275037,2.5945,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261015_194420,1792061143.275037,1792061143.288008,0.013,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261015_194420,1792061143.288008,1792061161.110737,17.8227,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261015_194420,1792061161.110737,1792061161.131122,0.0204,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_194420,1792061161.131122,1792061163.736061,2.6049,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261015_194420,1792061163.736061,1792061163.757985,0.0219,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261015_194420,1792061163.757985,1792061175.409772,11.6518,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261015_194420,1792061175.409772,1792061175.421591,0.0118,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194420,1792061175.421591,1792061177.987758,2.5662,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194420,1792061177.987758,1792061178.019472,0.0317,stage10,retreat,send,commanded
scripted_v1,run_0001_20261015_194420,1792061178.019472,1792061178.044534,0.0251,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194420,1792061178.044534,1792061178.065576,0.021,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194420,1792061178.065576,1792061180.678615,2.613,stage10,retreat,poll,
scripted_v1,run_0001_20261015_194420,1792061180.678615,1792061180.690535,0.0119,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_175444,1792140884.966473,1792140917.877748,32.9113,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_175444,1792140917.877748,1792140917.899187,0.0214,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175444,1792140917.899187,1792140920.496051,2.5969,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175444,1792140920.496051,1792140920.830683,0.3346,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175444,1792140920.830683,1792140921.162687,0.332,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175444,1792140921.162687,1792140921.498607,0.3359,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175444,1792140921.498607,1792140921.529956,0.0313,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_175444,1792140921.529956,1792140921.577719,0.0478,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_175444,1792140921.577719,1792140921.600908,0.0232,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_175444,1792140921.600908,1792140924.173318,2.5724,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_175444,1792140924.173318,1792140924.495919,0.3226,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_175444,1792140924.495919,1792140924.818073,0.3222,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_175444,1792140924.818073,1792140924.839888,0.0218,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_175444,1792140924.839888,1792140929.011749,4.1719,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_175444,1792140929.011749,1792140929.023269,0.0115,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140929.023269,1792140931.558586,2.5353,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140931.558586,1792140931.870475,0.3119,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140931.870475,1792140932.192321,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140932.192321,1792140932.523916,0.3316,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140932.523916,1792140932.85895,0.335,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140932.85895,1792140933.192308,0.3334,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140933.192308,1792140933.510818,0.3185,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140933.510818,1792140933.832539,0.3217,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140933.832539,1792140934.154493,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140934.154493,1792140934.46642,0.3119,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140934.46642,1792140934.788341,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140934.788341,1792140935.110385,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140935.110385,1792140935.432467,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140935.432467,1792140935.7545,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140935.7545,1792140936.076455,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140936.076455,1792140936.39893,0.3225,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140936.39893,1792140936.720642,0.3217,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140936.720642,1792140937.042386,0.3217,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140937.042386,1792140937.364638,0.3223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140937.364638,1792140937.686472,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140937.686472,1792140938.007983,0.3215,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140938.007983,1792140938.328475,0.3205,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140938.328475,1792140938.70504,0.3766,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140938.70504,1792140939.047071,0.342,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140939.047071,1792140939.367433,0.3204,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175444,1792140939.367433,1792140939.688531,0.3211,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_175444,1792140939.688531,1792140952.061471,12.3729,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_175444,1792140952.061471,1792140952.08257,0.0211,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_175444,1792140952.08257,1792140954.638982,2.5564,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_175444,1792140954.638982,1792140954.650531,0.0115,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_175444,1792140954.650531,1792140954.85267,0.2021,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_175444,1792140954.85267,1792140954.864595,0.0119,stage8_place,release,poll,
scripted_v1,run_0001_20261016_175444,1792140954.864595,1792140957.458692,2.5941,stage8_place,release,poll,
scripted_v1,run_0001_20261016_175444,1792140957.458692,1792140957.470514,0.0118,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_175444,1792140957.470514,1792140962.027334,4.5568,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261016_175444,1792140962.027334,1792140962.103615,0.0763,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140962.103615,1792140962.216896,0.1133,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140962.216896,1792140962.240311,0.0234,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140962.240311,1792140964.864803,2.6245,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140964.864803,1792140964.886686,0.0219,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175444,1792140964.886686,1792140964.968892,0.0822,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140964.968892,1792140965.060738,0.0918,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140965.060738,1792140965.072625,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140965.072625,1792140967.646794,2.5742,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140967.646794,1792140967.658828,0.012,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175444,1792140967.658828,1792140971.793631,4.1348,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175444,1792140971.793631,1792140971.86556,0.0719,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140971.86556,1792140971.967024,0.1015,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140971.967024,1792140971.988776,0.0218,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140971.988776,1792140974.583401,2.5946,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140974.583401,1792140974.606044,0.0226,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175444,1792140974.606044,1792140978.708968,4.1029,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175444,1792140978.708968,1792140978.770843,0.0619,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140978.770843,1792140978.90244,0.1316,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140978.90244,1792140978.924727,0.0223,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140978.924727,1792140981.509002,2.5843,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140981.509002,1792140981.520798,0.0118,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175444,1792140981.520798,1792140985.667682,4.1469,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175444,1792140985.667682,1792140985.747759,0.0801,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175444,1792140985.747759,1792141003.691664,17.9439,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_175444,1792141003.691664,1792141003.723313,0.0316,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_175444,1792141003.723313,1792141006.256003,2.5327,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_175444,1792141006.256003,1792141006.268121,0.0121,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_175444,1792141006.268121,1792141018.520414,12.2523,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_175444,1792141018.520414,1792141018.532258,0.0118,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141018.532258,1792141021.195349,2.6631,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141021.195349,1792141021.21654,0.0212,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_175444,1792141021.21654,1792141021.247974,0.0314,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141021.247974,1792141021.269808,0.0218,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141021.269808,1792141023.889322,2.6195,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141023.889322,1792141024.211403,0.3221,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141024.211403,1792141024.534081,0.3227,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141024.534081,1792141024.855994,0.3219,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141024.855994,1792141025.177521,0.3215,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141025.177521,1792141025.499407,0.3219,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175444,1792141025.499407,1792141025.511438,0.012,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_175708,1792141028.713747,1792141062.530019,33.8163,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_175708,1792141062.530019,1792141062.561647,0.0316,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175708,1792141062.561647,1792141065.175066,2.6134,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175708,1792141065.175066,1792141065.497171,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175708,1792141065.497171,1792141065.819478,0.3223,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175708,1792141065.819478,1792141066.142189,0.3227,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_175708,1792141066.142189,1792141066.163906,0.0217,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_175708,1792141066.163906,1792141066.19558,0.0317,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_175708,1792141066.19558,1792141066.207619,0.012,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_175708,1792141066.207619,1792141068.831926,2.6243,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_175708,1792141068.831926,1792141068.85384,0.0219,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_175708,1792141068.85384,1792141073.045012,4.1912,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_175708,1792141073.045012,1792141073.057535,0.0125,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175708,1792141073.057535,1792141075.681778,2.6242,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175708,1792141075.681778,1792141076.003897,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175708,1792141076.003897,1792141076.325653,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175708,1792141076.325653,1792141076.647711,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175708,1792141076.647711,1792141076.970061,0.3224,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175708,1792141076.970061,1792141077.292515,0.3225,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175708,1792141077.292515,1792141077.636992,0.3445,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175708,1792141077.636992,1792141077.955907,0.3189,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_175708,1792141077.955907,1792141077.977675,0.0218,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_175708,1792141077.977675,1792141134.759255,56.7816,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_175708,1792141134.759255,1792141134.770909,0.0117,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_175708,1792141134.770909,1792141137.337027,2.5661,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_175708,1792141137.337027,1792141137.359056,0.022,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_175708,1792141137.359056,1792141137.541068,0.182,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_175708,1792141137.541068,1792141137.552983,0.0119,stage8_place,release,poll,
scripted_v1,run_0001_20261016_175708,1792141137.552983,1792141140.137882,2.5849,stage8_place,release,poll,
scripted_v1,run_0001_20261016_175708,1792141140.137882,1792141140.159024,0.0211,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_175708,1792141140.159024,1792141144.73535,4.5763,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261016_175708,1792141144.73535,1792141144.815383,0.08,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141144.815383,1792141144.945332,0.1299,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141144.945332,1792141144.968722,0.0234,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141144.968722,1792141147.53289,2.5642,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141147.53289,1792141147.544924,0.012,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175708,1792141147.544924,1792141151.648857,4.1039,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175708,1792141151.648857,1792141151.74225,0.0934,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141151.74225,1792141151.933077,0.1908,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141151.933077,1792141151.944918,0.0118,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141151.944918,1792141154.509106,2.5642,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141154.509106,1792141154.521025,0.0119,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175708,1792141154.521025,1792141158.725152,4.2041,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175708,1792141158.725152,1792141162.819445,4.0943,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175708,1792141162.819445,1792141162.911481,0.092,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141162.911481,1792141163.083944,0.1725,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141163.083944,1792141163.095613,0.0117,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141163.095613,1792141165.640111,2.5445,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141165.640111,1792141165.661833,0.0217,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175708,1792141165.661833,1792141169.765195,4.1034,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_175708,1792141169.765195,1792141169.837287,0.0721,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_175708,1792141169.837287,1792141187.72946,17.8922,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_175708,1792141187.72946,1792141187.741725,0.0123,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_175708,1792141187.741725,1792141190.358107,2.6164,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_175708,1792141190.358107,1792141190.369193,0.0111,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_175708,1792141190.369193,1792141202.531636,12.1624,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_175708,1792141202.531636,1792141202.543574,0.0119,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175708,1792141202.543574,1792141205.178408,2.6348,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175708,1792141205.178408,1792141205.200504,0.0221,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_175708,1792141205.200504,1792141205.222303,0.0218,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175708,1792141205.222303,1792141205.234405,0.0121,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175708,1792141205.234405,1792141207.841417,2.607,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175708,1792141207.841417,1792141208.16351,0.3221,stage10,retreat,poll,
scripted_v1,run_0001_20261016_175708,1792141208.16351,1792141208.174976,0.0115,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_180013,1792141213.837556,1792141246.620116,32.7826,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_180013,1792141246.620116,1792141246.641666,0.0215,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_180013,1792141246.641666,1792141249.238655,2.597,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_180013,1792141249.238655,1792141249.560649,0.322,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_180013,1792141249.560649,1792141249.902513,0.3419,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_180013,1792141249.902513,1792141250.262624,0.3601,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_180013,1792141250.262624,1792141250.586832,0.3242,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_180013,1792141250.586832,1792141250.602524,0.0157,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_180013,1792141250.602524,1792141250.640711,0.0382,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_180013,1792141250.640711,1792141250.65268,0.012,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_180013,1792141250.65268,1792141253.257641,2.605,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_180013,1792141253.257641,1792141253.270023,0.0124,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_180013,1792141253.270023,1792141257.472385,4.2024,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_180013,1792141257.472385,1792141257.483968,0.0116,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141257.483968,1792141260.109479,2.6255,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141260.109479,1792141260.430989,0.3215,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141260.430989,1792141260.752824,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141260.752824,1792141261.074867,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141261.074867,1792141261.396947,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141261.396947,1792141261.718792,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141261.718792,1792141262.05311,0.3343,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141262.05311,1792141262.384906,0.3318,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141262.384906,1792141262.713443,0.3285,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141262.713443,1792141263.027304,0.3139,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141263.027304,1792141263.348631,0.3213,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141263.348631,1792141263.67089,0.3223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141263.67089,1792141263.982791,0.3119,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141263.982791,1792141264.304686,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141264.304686,1792141264.626825,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141264.626825,1792141264.948931,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141264.948931,1792141265.270982,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141265.270982,1792141265.592901,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141265.592901,1792141265.915791,0.3229,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141265.915791,1792141266.237029,0.3212,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141266.237029,1792141266.558909,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141266.558909,1792141266.880822,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141266.880822,1792141267.202903,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141267.202903,1792141267.514945,0.312,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141267.514945,1792141267.859365,0.3444,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_180013,1792141267.859365,1792141268.191318,0.332,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_180013,1792141268.191318,1792141277.551627,9.3603,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_180013,1792141277.551627,1792141277.573116,0.0215,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_180013,1792141277.573116,1792141280.190443,2.6173,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_180013,1792141280.190443,1792141280.210981,0.0205,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_180013,1792141280.210981,1792141280.373583,0.1626,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_180013,1792141280.373583,1792141280.385341,0.0118,stage8_place,release,poll,
scripted_v1,run_0001_20261016_180013,1792141280.385341,1792141282.979011,2.5937,stage8_place,release,poll,
scripted_v1,run_0001_20261016_180013,1792141282.979011,1792141282.990925,0.0119,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_180013,1792141282.990925,1792141287.545003,4.5541,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261016_180013,1792141287.545003,1792141287.617049,0.072,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141287.617049,1792141287.779108,0.1621,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141287.779108,1792141287.790915,0.0118,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141287.790915,1792141290.424976,2.6341,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141290.424976,1792141290.436968,0.012,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_180013,1792141290.436968,1792141290.51896,0.082,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141290.51896,1792141290.622704,0.1037,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141290.622704,1792141290.643019,0.0203,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141290.643019,1792141293.216983,2.574,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141293.216983,1792141293.23885,0.0219,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_180013,1792141293.23885,1792141297.373478,4.1346,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_180013,1792141297.373478,1792141297.456714,0.0832,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141297.456714,1792141297.577227,0.1205,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141297.577227,1792141297.589112,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141297.589112,1792141300.173053,2.5839,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141300.173053,1792141300.185091,0.012,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_180013,1792141300.185091,1792141304.329172,4.1441,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_180013,1792141304.329172,1792141304.421161,0.092,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141304.421161,1792141304.544316,0.1232,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141304.544316,1792141304.565067,0.0208,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141304.565067,1792141307.17973,2.6147,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141307.17973,1792141307.201744,0.022,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_180013,1792141307.201744,1792141311.345379,4.1436,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_180013,1792141311.345379,1792141311.427107,0.0817,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_180013,1792141311.427107,1792141329.279303,17.8522,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_180013,1792141329.279303,1792141329.291298,0.012,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_180013,1792141329.291298,1792141331.856289,2.565,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_180013,1792141331.856289,1792141331.87822,0.0219,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_180013,1792141331.87822,1792141342.930849,11.0526,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_180013,1792141342.930849,1792141342.942386,0.0115,stage10,retreat,poll,
scripted_v1,run_0001_20261016_180013,1792141342.942386,1792141345.476932,2.5345,stage10,retreat,poll,
scripted_v1,run_0001_20261016_180013,1792141345.476932,1792141345.499508,0.0226,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_180013,1792141345.499508,1792141345.52473,0.0252,stage10,retreat,poll,
scripted_v1,run_0001_20261016_180013,1792141345.52473,1792141345.543265,0.0185,stage10,retreat,poll,
scripted_v1,run_0001_20261016_180013,1792141345.543265,1792141348.159404,2.6161,stage10,retreat,poll,
scripted_v1,run_0001_20261016_180013,1792141348.159404,1792141348.482193,0.3228,stage10,retreat,poll,
scripted_v1,run_0001_20261016_180013,1792141348.482193,1792141348.504119,0.0219,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_184725,1792144045.393348,1792144077.84529,32.4519,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_184725,1792144077.84529,1792144077.857339,0.012,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_184725,1792144077.857339,1792144080.463386,2.606,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_184725,1792144080.463386,1792144080.785113,0.3217,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_184725,1792144080.785113,1792144081.107305,0.3222,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_184725,1792144081.107305,1792144081.429394,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_184725,1792144081.429394,1792144081.441286,0.0119,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_184725,1792144081.441286,1792144081.473126,0.0318,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_184725,1792144081.473126,1792144081.48548,0.0124,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_184725,1792144081.48548,1792144084.099265,2.6138,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_184725,1792144084.099265,1792144084.111214,0.0119,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_184725,1792144084.111214,1792144088.27397,4.1628,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_184725,1792144088.27397,1792144088.285263,0.0113,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_184725,1792144088.285263,1792144090.918756,2.6335,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_184725,1792144090.918756,1792144091.243821,0.3251,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_184725,1792144091.243821,1792144091.563635,0.3198,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_184725,1792144091.563635,1792144091.886224,0.3226,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_184725,1792144091.886224,1792144092.207411,0.3212,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_184725,1792144092.207411,1792144092.229356,0.0219,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_184725,1792144092.229356,1792144122.171813,29.9425,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_184725,1792144122.171813,1792144122.193743,0.0219,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_184725,1792144122.193743,1792144124.789529,2.5958,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_184725,1792144124.789529,1792144124.801529,0.012,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_184725,1792144124.801529,1792144124.973715,0.1722,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_184725,1792144124.973715,1792144124.995614,0.0219,stage8_place,release,poll,
scripted_v1,run_0001_20261016_184725,1792144124.995614,1792144127.579574,2.584,stage8_place,release,poll,
scripted_v1,run_0001_20261016_184725,1792144127.579574,1792144127.59154,0.012,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_184725,1792144127.59154,1792144132.125095,4.5336,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261016_184725,1792144132.125095,1792144132.21571,0.0906,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144132.21571,1792144132.344383,0.1287,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144132.344383,1792144132.373165,0.0288,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144132.373165,1792144135.005755,2.6326,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144135.005755,1792144135.02777,0.022,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_184725,1792144135.02777,1792144139.171792,4.144,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_184725,1792144139.171792,1792144143.255681,4.0839,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_184725,1792144143.255681,1792144143.337742,0.0821,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144143.337742,1792144143.499839,0.1621,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144143.499839,1792144143.511787,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144143.511787,1792144146.065806,2.554,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144146.065806,1792144146.077638,0.0118,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_184725,1792144146.077638,1792144146.139802,0.0622,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144146.139802,1792144146.241749,0.1019,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144146.241749,1792144146.263824,0.0221,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144146.263824,1792144148.797386,2.5336,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144148.797386,1792144148.810602,0.0132,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_184725,1792144148.810602,1792144148.871878,0.0613,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_184725,1792144148.871878,1792144166.744285,17.8724,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_184725,1792144166.744285,1792144166.766043,0.0218,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_184725,1792144166.766043,1792144169.342001,2.576,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_184725,1792144169.342001,1792144169.354107,0.0121,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_184725,1792144169.354107,1792144250.417721,81.0636,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_184725,1792144250.417721,1792144250.431741,0.014,stage10,retreat,poll,
scripted_v1,run_0001_20261016_184725,1792144250.431741,1792144252.962571,2.5308,stage10,retreat,poll,
scripted_v1,run_0001_20261016_184725,1792144252.962571,1792144252.974508,0.0119,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_184725,1792144252.974508,1792144252.99674,0.0222,stage10,retreat,poll,
scripted_v1,run_0001_20261016_184725,1792144252.99674,1792144253.018651,0.0219,stage10,retreat,poll,
scripted_v1,run_0001_20261016_184725,1792144253.018651,1792144255.695637,2.677,stage10,retreat,poll,
scripted_v1,run_0001_20261016_184725,1792144255.695637,1792144255.707463,0.0118,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_185201,1792144321.330185,1792144353.672552,32.3424,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_185201,1792144353.672552,1792144353.684392,0.0118,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_185201,1792144353.684392,1792144356.292689,2.6083,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_185201,1792144356.292689,1792144356.613406,0.3207,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_185201,1792144356.613406,1792144356.935463,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_185201,1792144356.935463,1792144357.257163,0.3217,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_185201,1792144357.257163,1792144357.27937,0.0222,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_185201,1792144357.27937,1792144357.311408,0.032,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_185201,1792144357.311408,1792144357.32333,0.0119,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_185201,1792144357.32333,1792144359.948349,2.625,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_185201,1792144359.948349,1792144359.970359,0.022,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_185201,1792144359.970359,1792144364.162553,4.1922,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_185201,1792144364.162553,1792144364.184207,0.0217,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144364.184207,1792144366.83832,2.6541,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144366.83832,1792144367.172739,0.3344,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144367.172739,1792144367.506054,0.3333,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144367.506054,1792144367.826414,0.3204,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144367.826414,1792144368.147934,0.3215,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144368.147934,1792144368.469576,0.3216,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144368.469576,1792144368.791432,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144368.791432,1792144369.113554,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144369.113554,1792144369.425386,0.3118,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144369.425386,1792144369.747472,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144369.747472,1792144370.069577,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144370.069577,1792144370.391588,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144370.391588,1792144370.714271,0.3227,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144370.714271,1792144371.03616,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144371.03616,1792144371.357555,0.3214,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144371.357555,1792144371.679592,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144371.679592,1792144372.001597,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144372.001597,1792144372.323514,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144372.323514,1792144372.645614,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144372.645614,1792144372.980015,0.3344,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144372.980015,1792144373.311506,0.3315,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144373.311506,1792144373.648145,0.3366,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144373.648145,1792144373.964394,0.3162,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144373.964394,1792144374.285578,0.3212,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144374.285578,1792144374.607339,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_185201,1792144374.607339,1792144374.929682,0.3223,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_185201,1792144374.929682,1792144389.0619,14.1322,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_185201,1792144389.0619,1792144389.083615,0.0217,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_185201,1792144389.083615,1792144417.208214,28.1246,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_185201,1792144417.208214,1792144417.399677,0.1915,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_185201,1792144417.399677,1792144417.42185,0.0222,stage8_place,release,poll,
scripted_v1,run_0001_20261016_185201,1792144417.42185,1792144420.057979,2.6361,stage8_place,release,poll,
scripted_v1,run_0001_20261016_185201,1792144420.057979,1792144420.090478,0.0325,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_185201,1792144420.090478,1792144424.64191,4.5514,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261016_185201,1792144424.64191,1792144428.735728,4.0938,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_185201,1792144428.735728,1792144432.850043,4.1143,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_185201,1792144432.850043,1792144436.953999,4.104,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_185201,1792144436.953999,1792144454.726333,17.7723,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_185201,1792144454.726333,1792144454.738103,0.0118,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_185201,1792144454.738103,1792144457.313096,2.575,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_185201,1792144457.313096,1792144457.33504,0.0219,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_185201,1792144457.33504,1792144497.71778,40.3827,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_185201,1792144497.71778,1792144497.730836,0.0131,stage10,retreat,poll,
scripted_v1,run_0001_20261016_185201,1792144497.730836,1792144500.265919,2.5351,stage10,retreat,poll,
scripted_v1,run_0001_20261016_185201,1792144500.265919,1792144500.28559,0.0197,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_185201,1792144500.28559,1792144500.307857,0.0223,stage10,retreat,poll,
scripted_v1,run_0001_20261016_185201,1792144500.307857,1792144500.319448,0.0116,stage10,retreat,poll,
scripted_v1,run_0001_20261016_185201,1792144500.319448,1792144502.978523,2.6591,stage10,retreat,poll,
scripted_v1,run_0001_20261016_185201,1792144502.978523,1792144502.998948,0.0204,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_190925,1792145365.593797,1792145365.615397,0.0216,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145365.615397,1792145365.638472,0.0231,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145365.638472,1792145368.180511,2.542,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145368.180511,1792145368.503135,0.3226,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145368.503135,1792145368.8259,0.3228,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145368.8259,1792145369.146481,0.3206,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145369.146481,1792145369.468761,0.3223,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145369.468761,1792145369.790633,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145369.790633,1792145370.11247,0.3218,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145370.11247,1792145370.437741,0.3253,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145370.437741,1792145370.756973,0.3192,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145370.756973,1792145371.078617,0.3216,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145371.078617,1792145371.401192,0.3226,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145371.401192,1792145371.723256,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145371.723256,1792145372.044482,0.3212,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145372.044482,1792145372.366412,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145372.366412,1792145372.697954,0.3315,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145372.697954,1792145373.031842,0.3339,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145373.031842,1792145373.363738,0.3319,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145373.363738,1792145373.700086,0.3363,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145373.700086,1792145374.022602,0.3225,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145374.022602,1792145374.349251,0.3266,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145374.349251,1792145374.680603,0.3314,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145374.680603,1792145375.0022,0.3216,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145375.0022,1792145375.324599,0.3224,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145375.324599,1792145375.63681,0.3122,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145375.63681,1792145375.95863,0.3218,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145375.95863,1792145381.280653,5.322,stage1,home,send,commanded
scripted_v1,run_0001_20261016_190925,1792145381.280653,1792145383.814627,2.534,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145383.814627,1792145384.136696,0.3221,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145384.136696,1792145384.458525,0.3218,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145384.458525,1792145384.780543,0.322,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145384.780543,1792145385.092694,0.3122,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145385.092694,1792145385.42721,0.3345,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145385.42721,1792145385.758986,0.3318,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145385.758986,1792145386.079502,0.3205,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145386.079502,1792145386.400992,0.3215,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145386.400992,1792145386.722733,0.3217,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145386.722733,1792145387.044778,0.322,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145387.044778,1792145387.366651,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145387.366651,1792145387.681265,0.3146,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145387.681265,1792145388.000646,0.3194,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145388.000646,1792145388.322654,0.322,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145388.322654,1792145388.634692,0.312,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145388.634692,1792145388.957307,0.3226,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145388.957307,1792145389.279351,0.322,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145389.279351,1792145389.600806,0.3215,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145389.600806,1792145389.922667,0.3219,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145389.922667,1792145390.244655,0.322,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145390.244655,1792145390.5667,0.322,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145390.5667,1792145390.889162,0.3225,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145390.889162,1792145391.222127,0.333,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145391.222127,1792145391.554986,0.3329,stage1,home,poll,
scripted_v1,run_0001_20261016_190925,1792145391.554986,1792145391.889035,0.334,stage1,home,send,commanded
scripted_v1,run_0001_20261016_190925,1792145391.889035,1792145423.947207,32.0582,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_190925,1792145423.947207,1792145423.958905,0.0117,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_190925,1792145423.958905,1792145426.61593,2.657,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_190925,1792145426.61593,1792145426.938594,0.3227,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_190925,1792145426.938594,1792145427.260771,0.3222,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_190925,1792145427.260771,1792145427.582034,0.3213,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_190925,1792145427.582034,1792145427.593951,0.0119,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_190925,1792145427.593951,1792145427.62589,0.0319,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_190925,1792145427.62589,1792145427.637978,0.0121,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_190925,1792145427.637978,1792145430.208125,2.5701,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_190925,1792145430.208125,1792145430.228,0.0199,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_190925,1792145430.228,1792145434.417103,4.1891,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_190925,1792145434.417103,1792145434.428989,0.0119,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_190925,1792145434.428989,1792145464.232794,29.8038,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_190925,1792145464.232794,1792145470.574344,6.3415,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_190925,1792145470.574344,1792145470.596287,0.0219,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_190925,1792145470.596287,1792145473.152219,2.5559,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_190925,1792145473.152219,1792145473.174138,0.0219,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_190925,1792145473.174138,1792145473.512946,0.3388,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_190925,1792145473.512946,1792145473.540159,0.0272,stage8_place,release,poll,
scripted_v1,run_0001_20261016_190925,1792145473.540159,1792145476.142431,2.6023,stage8_place,release,poll,
scripted_v1,run_0001_20261016_190925,1792145476.142431,1792145476.164277,0.0218,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_190925,1792145476.164277,1792145480.730253,4.566,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261016_190925,1792145480.730253,1792145480.800358,0.0701,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_190925,1792145480.800358,1792145481.032447,0.2321,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_190925,1792145481.032447,1792145481.054309,0.0219,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_190925,1792145481.054309,1792145483.678223,2.6239,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_190925,1792145483.678223,1792145483.700402,0.0222,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_190925,1792145483.700402,1792145487.774611,4.0742,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_190925,1792145487.774611,1792145487.866374,0.0918,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_190925,1792145487.866374,1792145488.028402,0.162,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_190925,1792145488.028402,1792145488.050432,0.022,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_190925,1792145488.050432,1792145490.624347,2.5739,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_190925,1792145490.624347,1792145490.636405,0.0121,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_190925,1792145490.636405,1792145494.750656,4.1143,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_190925,1792145494.750656,1792145512.593349,17.8427,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_190925,1792145512.593349,1792145512.615243,0.0219,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_190925,1792145512.615243,1792145515.179719,2.5645,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_190925,1792145515.179719,1792145515.201799,0.0221,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_190925,1792145515.201799,1792145727.406277,212.2045,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_190925,1792145727.406277,1792145727.427835,0.0216,stage10,retreat,poll,
scripted_v1,run_0001_20261016_190925,1792145727.427835,1792145729.961174,2.5333,stage10,retreat,poll,
scripted_v1,run_0001_20261016_190925,1792145729.961174,1792145729.973306,0.0121,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_190925,1792145729.973306,1792145730.005263,0.032,stage10,retreat,poll,
scripted_v1,run_0001_20261016_190925,1792145730.005263,1792145730.01735,0.0121,stage10,retreat,poll,
scripted_v1,run_0001_20261016_190925,1792145730.01735,1792145732.684394,2.667,stage10,retreat,poll,
scripted_v1,run_0001_20261016_190925,1792145732.684394,1792145732.706495,0.0221,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_191539,1792145739.619163,1792145772.541896,32.9227,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_191539,1792145772.541896,1792145772.562639,0.0207,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191539,1792145772.562639,1792145775.149791,2.5872,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191539,1792145775.149791,1792145775.46182,0.312,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191539,1792145775.46182,1792145775.78359,0.3218,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191539,1792145775.78359,1792145776.105758,0.3222,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191539,1792145776.105758,1792145776.42767,0.3219,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191539,1792145776.42767,1792145776.439599,0.0119,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_191539,1792145776.439599,1792145776.471698,0.0321,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_191539,1792145776.471698,1792145776.483627,0.0119,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_191539,1792145776.483627,1792145779.028667,2.545,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_191539,1792145779.028667,1792145779.040663,0.012,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_191539,1792145779.040663,1792145783.223226,4.1826,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_191539,1792145783.223226,1792145783.245481,0.0223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145783.245481,1792145785.830512,2.585,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145785.830512,1792145786.152714,0.3222,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145786.152714,1792145786.47435,0.3216,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145786.47435,1792145786.795713,0.3214,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145786.795713,1792145787.118522,0.3228,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145787.118522,1792145787.439761,0.3212,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145787.439761,1792145787.761743,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145787.761743,1792145788.083764,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145788.083764,1792145788.40706,0.3233,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145788.40706,1792145788.727853,0.3208,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145788.727853,1792145789.05051,0.3227,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145789.05051,1792145789.371841,0.3213,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145789.371841,1792145789.693838,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145789.693838,1792145790.026103,0.3323,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145790.026103,1792145790.357762,0.3317,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145790.357762,1792145790.67984,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145790.67984,1792145791.011291,0.3315,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145791.011291,1792145791.333611,0.3223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145791.333611,1792145791.65576,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145791.65576,1792145791.978123,0.3224,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145791.978123,1792145792.299946,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145792.299946,1792145792.621799,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145792.621799,1792145792.943786,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145792.943786,1792145793.265821,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145793.265821,1792145793.588123,0.3223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191539,1792145793.588123,1792145793.909899,0.3218,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_191539,1792145793.909899,1792145826.904643,32.9947,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_191539,1792145826.904643,1792145826.942831,0.0382,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_191539,1792145826.942831,1792145829.499961,2.5571,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_191539,1792145829.499961,1792145829.512059,0.0121,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_191539,1792145829.512059,1792145829.704121,0.1921,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_191539,1792145829.704121,1792145829.716036,0.0119,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191539,1792145829.716036,1792145832.327532,2.6115,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191539,1792145832.327532,1792145832.349803,0.0223,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_191539,1792145832.349803,1792145836.876238,4.5264,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261016_191539,1792145836.876238,1792145836.960041,0.0838,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145836.960041,1792145837.090184,0.1301,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145837.090184,1792145837.102004,0.0118,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145837.102004,1792145839.726147,2.6241,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145839.726147,1792145839.748176,0.022,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_191539,1792145839.748176,1792145839.830218,0.082,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145839.830218,1792145840.002153,0.1719,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145840.002153,1792145840.024204,0.0221,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145840.024204,1792145842.58819,2.564,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145842.58819,1792145842.600115,0.0119,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_191539,1792145842.600115,1792145846.714255,4.1141,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_191539,1792145846.714255,1792145846.796339,0.0821,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145846.796339,1792145846.958218,0.1619,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145846.958218,1792145846.970142,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145846.970142,1792145849.54432,2.5742,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145849.54432,1792145849.556358,0.012,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_191539,1792145849.556358,1792145853.700915,4.1446,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_191539,1792145853.700915,1792145857.774179,4.0733,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_191539,1792145857.774179,1792145857.866056,0.0919,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191539,1792145857.866056,1792145875.788018,17.922,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_191539,1792145875.788018,1792145875.800458,0.0124,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_191539,1792145875.800458,1792145878.386436,2.586,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_191539,1792145878.386436,1792145878.398348,0.0119,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_191539,1792145878.398348,1792145970.111136,91.7128,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_191539,1792145970.111136,1792145970.123249,0.0121,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191539,1792145970.123249,1792145972.747152,2.6239,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191539,1792145972.747152,1792145972.769088,0.0219,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_191539,1792145972.769088,1792145972.791554,0.0225,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191539,1792145972.791554,1792145972.803003,0.0114,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191539,1792145972.803003,1792145975.420167,2.6172,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191539,1792145975.420167,1792145975.43299,0.0128,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_191942,1792145982.38467,1792146014.227351,31.8427,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_191942,1792146014.227351,1792146014.248322,0.021,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191942,1792146014.248322,1792146016.84534,2.597,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191942,1792146016.84534,1792146017.167465,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191942,1792146017.167465,1792146017.489566,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191942,1792146017.489566,1792146017.811346,0.3218,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_191942,1792146017.811346,1792146017.824032,0.0127,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_191942,1792146017.824032,1792146017.855666,0.0316,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_191942,1792146017.855666,1792146017.87748,0.0218,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_191942,1792146017.87748,1792146020.544784,2.6673,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_191942,1792146020.544784,1792146020.58171,0.0369,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_191942,1792146020.58171,1792146024.886633,4.3049,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_191942,1792146024.886633,1792146024.898653,0.012,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146024.898653,1792146027.523565,2.6249,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146027.523565,1792146027.845404,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146027.845404,1792146028.167469,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146028.167469,1792146028.489538,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146028.489538,1792146028.811534,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146028.811534,1792146029.133481,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146029.133481,1792146029.455636,0.3222,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146029.455636,1792146029.777655,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146029.777655,1792146030.100014,0.3224,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146030.100014,1792146030.422057,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146030.422057,1792146030.743751,0.3217,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146030.743751,1792146031.065505,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146031.065505,1792146031.387473,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146031.387473,1792146031.709558,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146031.709558,1792146032.031625,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146032.031625,1792146032.366154,0.3345,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146032.366154,1792146032.690081,0.3239,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146032.690081,1792146033.008091,0.318,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146033.008091,1792146033.330627,0.3225,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146033.330627,1792146033.651593,0.321,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146033.651593,1792146033.973611,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146033.973611,1792146034.295531,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146034.295531,1792146034.617481,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146034.617481,1792146034.939728,0.3222,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146034.939728,1792146035.261588,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_191942,1792146035.261588,1792146035.583565,0.322,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_191942,1792146035.583565,1792146065.025911,29.4423,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_191942,1792146065.025911,1792146065.037744,0.0118,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_191942,1792146065.037744,1792146067.655531,2.6178,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_191942,1792146067.655531,1792146067.675796,0.0203,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_191942,1792146067.675796,1792146067.837844,0.162,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_191942,1792146067.837844,1792146067.849837,0.012,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146067.849837,1792146070.433924,2.5841,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146070.433924,1792146070.755893,0.322,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146070.755893,1792146071.077877,0.322,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146071.077877,1792146071.400718,0.3228,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146071.400718,1792146071.721975,0.3213,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146071.721975,1792146072.033881,0.3119,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146072.033881,1792146072.355914,0.322,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146072.355914,1792146072.687519,0.3316,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146072.687519,1792146073.022531,0.335,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146073.022531,1792146073.354288,0.3318,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146073.354288,1792146073.681203,0.3269,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146073.681203,1792146074.02824,0.347,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146074.02824,1792146074.348788,0.3205,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146074.348788,1792146074.670071,0.3213,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146074.670071,1792146074.991936,0.3219,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146074.991936,1792146075.313944,0.322,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146075.313944,1792146075.636089,0.3221,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146075.636089,1792146075.948038,0.3119,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146075.948038,1792146076.271807,0.3238,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146076.271807,1792146076.59188,0.3201,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146076.59188,1792146076.914033,0.3222,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146076.914033,1792146077.23796,0.3239,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146077.23796,1792146077.557992,0.32,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146077.557992,1792146077.88008,0.3221,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146077.88008,1792146078.201941,0.3219,stage8_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146078.201941,1792146078.523969,0.322,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_191942,1792146078.523969,1792146079.01591,0.4919,stage8_place,release,stage_change,stage
scripted_v1,run_0001_20261016_191942,1792146079.01591,1792146079.187362,0.1715,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146079.187362,1792146079.219126,0.0318,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146079.219126,1792146081.793853,2.5747,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146081.793853,1792146082.116159,0.3223,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146082.116159,1792146082.438014,0.3219,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146082.438014,1792146082.759968,0.322,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146082.759968,1792146083.082605,0.3226,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146083.082605,1792146083.404015,0.3214,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146083.404015,1792146083.716087,0.3121,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146083.716087,1792146084.038083,0.322,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146084.038083,1792146084.360693,0.3226,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146084.360693,1792146084.682426,0.3217,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146084.682426,1792146085.016608,0.3342,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146085.016608,1792146085.348737,0.3321,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146085.348737,1792146085.680211,0.3315,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146085.680211,1792146086.010577,0.3304,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146086.010577,1792146086.331995,0.3214,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146086.331995,1792146086.653966,0.322,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146086.653966,1792146086.976025,0.3221,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146086.976025,1792146087.297935,0.3219,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146087.297935,1792146087.619936,0.322,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146087.619936,1792146087.942145,0.3222,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146087.942145,1792146088.263992,0.3218,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146088.263992,1792146088.585947,0.322,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146088.585947,1792146088.908886,0.3229,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146088.908886,1792146089.229912,0.321,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146089.229912,1792146089.552694,0.3228,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_191942,1792146089.552694,1792146089.873943,0.3212,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_191942,1792146089.873943,1792146107.655953,17.782,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_191942,1792146107.655953,1792146107.668232,0.0123,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146107.668232,1792146110.253354,2.5851,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_191942,1792146110.253354,1792146110.275209,0.0219,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_191942,1792146110.275209,1792146129.457562,19.1824,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_191942,1792146129.457562,1792146129.469291,0.0117,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191942,1792146129.469291,1792146129.481423,0.0121,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191942,1792146129.481423,1792146132.1577,2.6763,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191942,1792146132.1577,1792146132.480727,0.323,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191942,1792146132.480727,1792146132.802435,0.3217,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191942,1792146132.802435,1792146133.125089,0.3227,stage10,retreat,poll,
scripted_v1,run_0001_20261016_191942,1792146133.125089,1792146133.147013,0.0219,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_192229,1792146149.338572,1792146181.700871,32.3623,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_192229,1792146181.700871,1792146181.712622,0.0118,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_192229,1792146181.712622,1792146184.309608,2.597,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_192229,1792146184.309608,1792146184.631706,0.3221,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_192229,1792146184.631706,1792146184.963102,0.3314,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_192229,1792146184.963102,1792146185.298222,0.3351,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_192229,1792146185.298222,1792146185.329824,0.0316,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_192229,1792146185.329824,1792146185.372165,0.0423,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_192229,1792146185.372165,1792146185.39174,0.0196,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_192229,1792146185.39174,1792146187.936716,2.545,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_192229,1792146187.936716,1792146187.948731,0.012,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_192229,1792146187.948731,1792146192.142192,4.1935,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_192229,1792146192.142192,1792146192.164627,0.0224,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146192.164627,1792146194.798266,2.6336,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146194.798266,1792146195.119805,0.3215,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146195.119805,1792146195.441674,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146195.441674,1792146195.76399,0.3223,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146195.76399,1792146196.085692,0.3217,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146196.085692,1792146196.397898,0.3122,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146196.397898,1792146196.729165,0.3313,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146196.729165,1792146197.064257,0.3351,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146197.064257,1792146197.396269,0.332,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146197.396269,1792146197.716418,0.3201,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146197.716418,1792146198.038782,0.3224,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146198.038782,1792146198.370922,0.3321,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146198.370922,1792146198.691384,0.3205,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146198.691384,1792146199.013846,0.3225,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146199.013846,1792146199.335761,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146199.335761,1792146199.657741,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146199.657741,1792146199.979969,0.3222,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146199.979969,1792146200.301726,0.3218,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146200.301726,1792146200.62476,0.323,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146200.62476,1792146200.945809,0.321,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146200.945809,1792146201.267843,0.322,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146201.267843,1792146201.589478,0.3216,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146201.589478,1792146201.911941,0.3225,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146201.911941,1792146202.233795,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146202.233795,1792146202.55598,0.3222,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_192229,1792146202.55598,1792146202.89364,0.3377,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_192229,1792146202.89364,1792146208.620159,5.7265,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_192229,1792146208.620159,1792146208.64196,0.0218,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_192229,1792146208.64196,1792146211.207767,2.5658,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_192229,1792146211.207767,1792146211.219678,0.0119,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_192229,1792146211.219678,1792146211.381931,0.1623,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_192229,1792146211.381931,1792146211.393765,0.0118,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146211.393765,1792146214.030102,2.6363,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146214.030102,1792146214.362346,0.3322,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146214.362346,1792146214.695377,0.333,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146214.695377,1792146215.036516,0.3411,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146215.036516,1792146215.356632,0.3201,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146215.356632,1792146215.678276,0.3216,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146215.678276,1792146216.000078,0.3218,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146216.000078,1792146216.321795,0.3217,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146216.321795,1792146216.643551,0.3218,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146216.643551,1792146216.966199,0.3226,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146216.966199,1792146217.287928,0.3217,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146217.287928,1792146217.610108,0.3222,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146217.610108,1792146217.931897,0.3218,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146217.931897,1792146218.254714,0.3228,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146218.254714,1792146218.576134,0.3214,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146218.576134,1792146218.898175,0.322,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146218.898175,1792146219.219688,0.3215,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146219.219688,1792146219.542106,0.3224,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146219.542106,1792146219.864134,0.322,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146219.864134,1792146220.185828,0.3217,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146220.185828,1792146220.522909,0.3371,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146220.522909,1792146220.855917,0.333,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146220.855917,1792146221.172983,0.3171,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146221.172983,1792146221.514971,0.342,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146221.514971,1792146221.84971,0.3347,stage8_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146221.84971,1792146222.178009,0.3283,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_192229,1792146222.178009,1792146226.804527,4.6265,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261016_192229,1792146226.804527,1792146226.894215,0.0897,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146226.894215,1792146227.176971,0.2828,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146227.176971,1792146227.19885,0.0219,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146227.19885,1792146229.772932,2.5741,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146229.772932,1792146229.794034,0.0211,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_192229,1792146229.794034,1792146233.898132,4.1041,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_192229,1792146233.898132,1792146233.969889,0.0718,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146233.969889,1792146234.122001,0.1521,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146234.122001,1792146234.133897,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146234.133897,1792146236.698031,2.5641,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146236.698031,1792146237.020055,0.322,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146237.020055,1792146237.341942,0.3219,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146237.341942,1792146237.664713,0.3228,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146237.664713,1792146237.986226,0.3215,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146237.986226,1792146238.308116,0.3219,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146238.308116,1792146238.631421,0.3233,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146238.631421,1792146238.952694,0.3213,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146238.952694,1792146239.275318,0.3226,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146239.275318,1792146239.596022,0.3207,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146239.596022,1792146239.918368,0.3223,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146239.918368,1792146240.240139,0.3218,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146240.240139,1792146240.562035,0.3219,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146240.562035,1792146240.884176,0.3221,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146240.884176,1792146241.206047,0.3219,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146241.206047,1792146241.528194,0.3221,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146241.528194,1792146241.850835,0.3226,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146241.850835,1792146242.172121,0.3213,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146242.172121,1792146242.49554,0.3234,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146242.49554,1792146242.816024,0.3205,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146242.816024,1792146243.150455,0.3344,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146243.150455,1792146243.482501,0.332,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146243.482501,1792146243.81445,0.3319,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146243.81445,1792146244.142166,0.3277,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146244.142166,1792146244.480767,0.3386,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_192229,1792146244.480767,1792146244.798618,0.3179,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_192229,1792146244.798618,1792146262.571027,17.7724,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_192229,1792146262.571027,1792146262.592725,0.0217,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146262.592725,1792146265.189871,2.5971,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_192229,1792146265.189871,1792146265.210863,0.021,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_192229,1792146265.210863,1792146285.225133,20.0143,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_192229,1792146285.225133,1792146285.256697,0.0316,stage10,retreat,poll,
scripted_v1,run_0001_20261016_192229,1792146285.256697,1792146285.288631,0.0319,stage10,retreat,poll,
scripted_v1,run_0001_20261016_192229,1792146285.288631,1792146287.903574,2.6149,stage10,retreat,poll,
scripted_v1,run_0001_20261016_192229,1792146287.903574,1792146288.225577,0.322,stage10,retreat,poll,
scripted_v1,run_0001_20261016_192229,1792146288.225577,1792146288.547415,0.3218,stage10,retreat,poll,
scripted_v1,run_0001_20261016_192229,1792146288.547415,1792146288.869948,0.3225,stage10,retreat,poll,
scripted_v1,run_0001_20261016_192229,1792146288.869948,1792146288.891859,0.0219,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_194238,1792147358.914619,1792147391.796026,32.8814,stage1,home,gripper,gripper_cmd;gripper;stage;stage
scripted_v1,run_0001_20261016_194238,1792147391.796026,1792147391.807743,0.0117,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_194238,1792147391.807743,1792147394.40465,2.5969,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_194238,1792147394.40465,1792147394.726542,0.3219,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_194238,1792147394.726542,1792147395.048861,0.3223,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_194238,1792147395.048861,1792147395.370855,0.322,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_194238,1792147395.370855,1792147395.703182,0.3323,stage3_approach_pick,approach,poll,
scripted_v1,run_0001_20261016_194238,1792147395.703182,1792147395.724808,0.0216,stage3_approach_pick,approach,send,commanded
scripted_v1,run_0001_20261016_194238,1792147395.724808,1792147395.756802,0.032,stage3_approach_pick,approach,stage_change,stage
scripted_v1,run_0001_20261016_194238,1792147395.756802,1792147395.76927,0.0125,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_194238,1792147395.76927,1792147398.373727,2.6045,stage4_pick,grasp,poll,
scripted_v1,run_0001_20261016_194238,1792147398.373727,1792147398.395903,0.0222,stage4_pick,grasp,send,commanded
scripted_v1,run_0001_20261016_194238,1792147398.395903,1792147402.6013,4.2054,stage4_pick,grasp,gripper,stage;gripper_cmd;gripper;stage
scripted_v1,run_0001_20261016_194238,1792147402.6013,1792147402.632702,0.0314,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_194238,1792147402.632702,1792147405.234956,2.6023,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_194238,1792147405.234956,1792147405.557052,0.3221,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_194238,1792147405.557052,1792147405.879655,0.3226,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_194238,1792147405.879655,1792147406.20186,0.3222,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_194238,1792147406.20186,1792147406.523061,0.3212,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_194238,1792147406.523061,1792147406.844996,0.3219,stage6,carry_lift,poll,
scripted_v1,run_0001_20261016_194238,1792147406.844996,1792147406.86709,0.0221,stage6,carry_lift,send,commanded
scripted_v1,run_0001_20261016_194238,1792147406.86709,1792147431.701806,24.8347,stage6,carry_lift,stage_change,stage
scripted_v1,run_0001_20261016_194238,1792147431.701806,1792147431.733415,0.0316,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_194238,1792147431.733415,1792147434.291981,2.5586,stage7_approach_place,carry,poll,
scripted_v1,run_0001_20261016_194238,1792147434.291981,1792147434.319219,0.0272,stage7_approach_place,carry,send,commanded
scripted_v1,run_0001_20261016_194238,1792147434.319219,1792147434.531137,0.2119,stage7_approach_place,carry,stage_change,stage
scripted_v1,run_0001_20261016_194238,1792147434.531137,1792147434.543183,0.012,stage8_place,release,poll,
scripted_v1,run_0001_20261016_194238,1792147434.543183,1792147437.127159,2.584,stage8_place,release,poll,
scripted_v1,run_0001_20261016_194238,1792147437.127159,1792147437.139164,0.012,stage8_place,release,send,commanded
scripted_v1,run_0001_20261016_194238,1792147437.139164,1792147441.723435,4.5843,stage8_place,release,send,stage;commanded
scripted_v1,run_0001_20261016_194238,1792147441.723435,1792147441.805204,0.0818,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147441.805204,1792147441.917224,0.112,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147441.917224,1792147441.929107,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147441.929107,1792147444.474074,2.545,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147444.474074,1792147444.495411,0.0213,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_194238,1792147444.495411,1792147444.577275,0.0819,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147444.577275,1792147444.709452,0.1322,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147444.709452,1792147444.721371,0.0119,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147444.721371,1792147447.259068,2.5377,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147447.259068,1792147447.278295,0.0192,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_194238,1792147447.278295,1792147447.339488,0.0612,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147447.339488,1792147447.471258,0.1318,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147447.471258,1792147447.49384,0.0226,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147447.49384,1792147450.038015,2.5442,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147450.038015,1792147450.059968,0.022,stage8_5_replace_align,release,send,commanded
scripted_v1,run_0001_20261016_194238,1792147450.059968,1792147450.14222,0.0823,stage8_5_replace_align,release,poll,
scripted_v1,run_0001_20261016_194238,1792147450.14222,1792147467.983492,17.8413,stage8_5_replace_align,release,gripper,stage;gripper_cmd;stage
scripted_v1,run_0001_20261016_194238,1792147467.983492,1792147467.99539,0.0119,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_194238,1792147467.99539,1792147470.592261,2.5969,stage9b_judge_place,release,poll,
scripted_v1,run_0001_20261016_194238,1792147470.592261,1792147470.613867,0.0216,stage9b_judge_place,release,send,commanded
scripted_v1,run_0001_20261016_194238,1792147470.613867,1792147524.736258,54.1224,stage9b_judge_place,release,stage_change,stage
scripted_v1,run_0001_20261016_194238,1792147524.736258,1792147524.748486,0.0122,stage10,retreat,poll,
scripted_v1,run_0001_20261016_194238,1792147524.748486,1792147527.322048,2.5736,stage10,retreat,poll,
scripted_v1,run_0001_20261016_194238,1792147527.322048,1792147527.333946,0.0119,stage10,retreat,send,commanded
scripted_v1,run_0001_20261016_194238,1792147527.333946,1792147527.35595,0.022,stage10,retreat,poll,
scripted_v1,run_0001_20261016_194238,1792147527.35595,1792147527.367877,0.0119,stage10,retreat,poll,
scripted_v1,run_0001_20261016_194238,1792147527.367877,1792147529.975906,2.608,stage10,retreat,poll,
scripted_v1,run_0001_20261016_194238,1792147529.975906,1792147529.986883,0.011,stage10,retreat,send,commanded
```



## 判定の画面と印の道具の、この回の終わりのコード

依頼183〜198 で直したあとの、判定の画面（`pi05/verdict_viewer/`）と、依頼196 で作った2本のファイルの全文です。


### verdicts.py

```python
#!/usr/bin/env python3
"""推論の記録 (runs/pi05_policy/) の判定ファイルを読む・足す共通の部品 (依頼 183).

判定ファイル: /Volumes/KIOXIA/r2r2r-data/runs/pi05_policy_verdicts_v1.csv (MASTER の保存先テーブル)
  - 追記だけ. 既存の行は書き換えない. 同じ run_stem はいちばん新しい行 (ファイルの後ろの行) が正
  - labeler=ai の行は未確定. 確定は run_input・人の行 (human / human_fixed_ai / human_only)・rule
    (依頼 185. run_input は推論を終えたときにエイイチが y/n を打った判定なので人の確定に数える.
     rule はエイイチの決めで機械的に付けた行: 送ったチャンク 0 → not_applicable, 素材が足りない → not_judgeable)
  - 成功率は確定した回の success / (success + failure). not_applicable・not_judgeable・unknown は分母に入れない
  - 書く前に KIOXIA のマウントを確かめる. なければ止める (ローカルに逃がさない)
元の記録 (runs/pi05_policy/ の中身) は読むだけ.
"""
import csv
import fcntl
import io
import json
import os
import sys
from datetime import datetime
from pathlib import Path

KIOXIA_MOUNT = Path("/Volumes/KIOXIA")
DATA_ROOT = KIOXIA_MOUNT / "r2r2r-data"
RUNS_DIR = DATA_ROOT / "runs" / "pi05_policy"
VERDICTS_CSV = DATA_ROOT / "runs" / "pi05_policy_verdicts_v1.csv"

COLUMNS = ["labeled_at", "run_stem", "pick", "place", "outcome", "labeler",
           "ai_outcome", "ai_reason", "evidence", "note"]
PICK_PLACE = ("yes", "no", "unknown")
PLACE_VALUES = PICK_PLACE + ("not_applicable",)  # つかめず place まで行かなかった回 (依頼 193. pick には足さない)
OUTCOMES = ("success", "failure", "unknown", "not_judgeable", "not_applicable")
AI_OUTCOMES = ("success", "failure", "unknown", "not_judgeable")  # AI が付けてよい outcome (not_applicable は rule だけ)
LABELERS = ("run_input", "ai", "human", "human_fixed_ai", "human_only", "rule")
HUMAN_LABELERS = ("human", "human_fixed_ai", "human_only")
CONFIRMED_LABELERS = ("run_input",) + HUMAN_LABELERS + ("rule",)  # 確定の扱い (依頼 185)
RULE_NOTE = "エイイチの決め 2026-11-14 依頼185"
EVIDENCES = ("top.mp4", "frames", "both", "")
MAX_NOTE = 500
MAX_REASON = 2000


class NotMounted(RuntimeError):
    pass


def ensure_ssd_mounted(csv_path=VERDICTS_CSV):
    """KIOXIA の下に書くときはマウントを確かめる. なければ NotMounted (ローカルへは書かない).
    テストで KIOXIA の外の一時ファイルに書くときは確かめない."""
    p = Path(csv_path)
    if str(p).startswith(str(KIOXIA_MOUNT) + os.sep) or p == KIOXIA_MOUNT:
        if not os.path.ismount(str(KIOXIA_MOUNT)):
            raise NotMounted(f"KIOXIA がマウントされていません ({KIOXIA_MOUNT}). 書かずに止めます")
        if not p.parent.is_dir():
            raise NotMounted(f"書き込み先のフォルダがありません ({p.parent}). 書かずに止めます")


def now_iso():
    return datetime.now().astimezone().isoformat(timespec="seconds")


def validate_row(row):
    r = {c: ("" if row.get(c) is None else str(row.get(c))) for c in COLUMNS}
    # 長すぎる値は切る (csv の読み取りの上限を超えると以後読めなくなる. codex 3 回目 R3)
    for c, n in (("note", MAX_NOTE), ("ai_reason", MAX_REASON)):
        if len(r[c]) > n:
            r[c] = r[c][:n] + "…"
    if not r["run_stem"]:
        raise ValueError("run_stem が空です")
    if r["pick"] not in PICK_PLACE:
        raise ValueError(f"pick は {PICK_PLACE} のどれか: {r['pick']!r}")
    if r["place"] not in PLACE_VALUES:
        raise ValueError(f"place は {PLACE_VALUES} のどれか: {r['place']!r}")
    if r["outcome"] not in OUTCOMES:
        raise ValueError(f"outcome は {OUTCOMES} のどれか: {r['outcome']!r}")
    if r["labeler"] not in LABELERS:
        raise ValueError(f"labeler は {LABELERS} のどれか: {r['labeler']!r}")
    if r["ai_outcome"] not in OUTCOMES + ("",):
        raise ValueError(f"ai_outcome は {OUTCOMES} のどれか か空: {r['ai_outcome']!r}")
    if r["evidence"] not in EVIDENCES:
        raise ValueError(f"evidence は {EVIDENCES} のどれか: {r['evidence']!r}")
    if not r["labeled_at"]:
        r["labeled_at"] = now_iso()
    return r


class BrokenCsv(RuntimeError):
    pass


def _check_existing(data):
    """追記の前に今のファイルを確かめる. 見出しがちがう・最後が改行で終わらない・列の数がちがう行があれば止める
    (そのまま足すと既存の最後の行に続けて書いてしまう. codex R4)."""
    if not data:
        return []
    if not data.endswith(b"\n"):
        raise BrokenCsv("判定ファイルの最後が改行で終わっていません (書きかけの行がある). 書かずに止めます")
    try:  # strict: 閉じていない引用符も止める (codex 2 回目 R1)
        rows = list(csv.reader(io.StringIO(data.decode("utf-8"), newline=""), strict=True))
    except (csv.Error, UnicodeDecodeError) as e:
        raise BrokenCsv(f"判定ファイルを読めません ({e}). 書かずに止めます")
    if not rows or rows[0] != COLUMNS:
        raise BrokenCsv("判定ファイルの見出しがちがいます. 書かずに止めます")
    for i, r in enumerate(rows[1:], 2):
        if len(r) != len(COLUMNS):
            raise BrokenCsv(f"判定ファイルの {i} 行目の列の数が {len(r)} です ({len(COLUMNS)} のはず). 書かずに止めます")
    return [dict(zip(COLUMNS, r)) for r in rows[1:]]


def append_rows(rows, csv_path=VERDICTS_CSV, skip_if_labeled_by=None, forbid_dirs=()):
    """行を末尾に足すだけ. 既存のバイトは触らない (追記モードで開く). 見出しはファイルが空のときだけ書く.
    skip_if_labeled_by: この labeler の行がすでにある run_stem の行は足さない. 確かめはロックの中で行う
    (seed が人の確定のあとに AI の行を足して未確定へ戻さないため. codex R2).
    forbid_dirs: この中には書かない (使っている記録のフォルダ. codex 2 回目 R3). 書いた行を返す."""
    rows = [validate_row(r) for r in rows]
    ensure_ssd_mounted(csv_path)
    if not rows:
        return []
    p = Path(csv_path)
    if (p.suffix != ".csv" or within(RUNS_DIR, p) or within(DATA_ROOT / "datasets", p)
            or any(within(d, p) for d in forbid_dirs)):
        raise BrokenCsv(f"判定ファイルとして書けない場所です ({p}). 元の記録・datasets の中や .csv でないファイルには書きません")
    if p.is_symlink():
        raise BrokenCsv(f"判定ファイルがシンボリックリンクです ({p}). 書かずに止めます")
    fd = os.open(str(p), os.O_RDWR | os.O_APPEND | os.O_CREAT | getattr(os, "O_NOFOLLOW", 0), 0o644)
    with os.fdopen(fd, "r+b") as f:
        fcntl.flock(f, fcntl.LOCK_EX)
        try:
            f.seek(0)
            existing = _check_existing(f.read())
            if skip_if_labeled_by:
                done = {r["run_stem"] for r in existing if r.get("labeler") in skip_if_labeled_by}
                rows = [r for r in rows if r["run_stem"] not in done]
                if not rows:
                    return []
            buf = io.StringIO()
            w = csv.DictWriter(buf, fieldnames=COLUMNS, lineterminator="\n")
            if not existing and f.seek(0, os.SEEK_END) == 0:
                w.writeheader()
            for r in rows:
                w.writerow(r)
            f.write(buf.getvalue().encode("utf-8"))
            f.flush()
            os.fsync(f.fileno())
        finally:
            fcntl.flock(f, fcntl.LOCK_UN)
    return rows


def within(root, path):
    """path がリンクをたどっても root の中にあるか (codex R6)."""
    try:
        Path(path).resolve().relative_to(Path(root).resolve())
        return True
    except (ValueError, OSError):
        return False


def read_rows(csv_path=VERDICTS_CSV):
    p = Path(csv_path)
    if not p.exists():
        return []
    with open(p, newline="", encoding="utf-8") as f:
        return list(csv.DictReader(f))


def latest_by_stem(rows, labelers=None):
    """run_stem ごとにいちばん新しい行 (ファイルの後ろの行). labelers を渡すとその種類の行だけから選ぶ."""
    out = {}
    for r in rows:
        if labelers is not None and r.get("labeler") not in labelers:
            continue
        out[r["run_stem"]] = r
    return out


def current_by_stem(rows):
    """run_stem ごとの今の判定. 確定の行があればそのいちばん新しい行, なければいちばん新しい行 (AI など).
    確定のあとに足された AI の行で未確定へ戻らない."""
    out = latest_by_stem(rows)
    out.update(latest_by_stem(rows, labelers=CONFIRMED_LABELERS))
    return out


def success_rate(rows):
    """確定した回だけの成功率. 分母は success + failure (not_applicable・not_judgeable・unknown は入れない).
    {"success", "failure", "denominator", "rate" (分母 0 なら None), "confirmed", "by_outcome"}."""
    conf = latest_by_stem(rows, labelers=CONFIRMED_LABELERS)
    by = {}
    for r in conf.values():
        by[r["outcome"]] = by.get(r["outcome"], 0) + 1
    s, f = by.get("success", 0), by.get("failure", 0)
    return {"success": s, "failure": f, "denominator": s + f, "rate": (s / (s + f)) if s + f else None,
            "confirmed": len(conf), "by_outcome": by}


def rule_row(run_stem, n_exec, ai_row):
    """エイイチの決め (2026-11-14 依頼 185) に当たる回の labeler=rule の行. 当たらなければ None.
    決め 2: 送ったチャンク 0 (アームを動かしていない) → not_applicable. 2 と 3 の両方に当たれば 2
    決め 3: AI が frames/ だけで not_judgeable とした回・素材がなく API を呼ばなかった回 → not_judgeable"""
    a = ai_row or {}
    if n_exec == 0:
        oc, note = "not_applicable", f"{RULE_NOTE} 決め2: 送ったチャンク 0 (アームを動かしていない・試行になっていない)"
    elif a.get("outcome") == "not_judgeable" and a.get("evidence") in ("frames", ""):
        src = "frames/ だけ" if a.get("evidence") == "frames" else "素材なし (API を呼んでいない)"
        oc, note = "not_judgeable", f"{RULE_NOTE} 決め3: AI が not_judgeable ({src}). 人が見ずに確定"
    else:
        return None
    return {"labeled_at": now_iso(), "run_stem": run_stem, "pick": "unknown", "place": "unknown",
            "outcome": oc, "labeler": "rule", "ai_outcome": a.get("outcome", ""),
            "ai_reason": a.get("ai_reason", ""), "evidence": a.get("evidence", ""), "note": note}


def human_labeler_for(outcome, ai_row):
    """人が付けたときの labeler. AI の行がなければ human_only, 同じなら human, 違えば human_fixed_ai."""
    if not ai_row:
        return "human_only"
    return "human" if ai_row.get("outcome") == outcome else "human_fixed_ai"


# ---- 元の記録を読む (読むだけ) ----

def list_run_stems(runs_dir=RUNS_DIR):
    return sorted(d.name for d in Path(runs_dir).iterdir()
                  if d.is_dir() and d.name.startswith("pi05_") and within(runs_dir, d))


def safe_file(run_dir, *rel):
    """記録の中のファイル. リンクをたどって記録の外へ出るもの・ないものは None (codex 2 回目 R4)."""
    p = Path(run_dir).joinpath(*rel)
    return p if p.is_file() and within(run_dir, p) else None


def read_run_json(run_dir):
    p = safe_file(run_dir, f"{Path(run_dir).name}.json")
    if p is None:
        return None
    try:
        return json.loads(p.read_text(encoding="utf-8"))
    except Exception:
        return None


def frame_files(run_dir):
    d = Path(run_dir) / "frames"
    if not d.is_dir():
        return []
    return sorted(f.name for f in d.iterdir()
                  if f.suffix.lower() == ".jpg" and not f.name.startswith("._") and within(run_dir, f))


def read_log(run_dir):
    p = safe_file(run_dir, "log.jsonl")
    out = []
    if p is None:
        return out
    for line in p.read_text(encoding="utf-8", errors="replace").splitlines():
        line = line.strip()
        if not line:
            continue
        try:
            out.append(json.loads(line))
        except Exception:
            pass
    return out


def executed_chunks(log):
    """送ったチャンクの数: log.jsonl の chunk のある行のうち executed が True の行 (log.jsonl がなければ 0)."""
    return sum(1 for x in log if "chunk" in x and str(x.get("executed")) == "True")


def has_top_mp4(run_dir):
    return safe_file(run_dir, "recording", "top.mp4") is not None


def run_input_row(run_stem, run_json):
    """{run_stem}.json の outcome を写した行 (labeler=run_input). outcome がない / null なら None."""
    if not run_json or run_json.get("outcome") in (None, ""):
        return None
    oc = run_json["outcome"]
    if oc not in OUTCOMES:
        oc = "unknown"
    jd = run_json.get("judgments") or {}

    def pv(k):
        v = (jd.get(k) or {}).get("verdict")
        return v if v in PICK_PLACE else "unknown"
    return {"labeled_at": run_json.get("ended_at") or now_iso(), "run_stem": run_stem,
            "pick": pv("pick"), "place": pv("place"), "outcome": oc, "labeler": "run_input",
            "ai_outcome": "", "ai_reason": "", "evidence": "",
            "note": "{run_stem}.json の outcome を写した (記録したときの入力)"}


if __name__ == "__main__":
    rows = read_rows()
    lat = latest_by_stem(rows)
    print(f"{VERDICTS_CSV}: {len(rows)} 行 / {len(lat)} 回")
    sys.exit(0)
```


### seed_verdicts.py

```python
#!/usr/bin/env python3
"""推論の記録の判定ファイルに, 今ある判定の写しと AI の先回り判定を足す (依頼 183).

  python3 pi05/verdict_viewer/seed_verdicts.py --run-input      # {run_stem}.json の outcome を写す (labeler=run_input)
  python3 pi05/verdict_viewer/seed_verdicts.py --ai             # 印のない回を AI が判定 (labeler=ai)
  python3 pi05/verdict_viewer/seed_verdicts.py --ai --dry-run   # API を呼ばずに素材だけ数える
  python3 pi05/verdict_viewer/seed_verdicts.py --rule           # エイイチの決め (依頼 185) の行を足す (labeler=rule)

- 元の記録は読むだけ. 判定ファイルには追記だけ (verdicts.append_rows)
- すでに同じ種類の行がある回は足さない (何度流しても同じ行が増えない)
- AI の素材: recording/top.mp4 があれば, 推論が動いていた区間 (top_frame_log.csv の mode が wait / home
  でないコマ) の終わりまでから 6 コマ (後ろ寄り). なければ frames/ (各チャンクの入力画像) から最後を含む 6 枚.
  2 枚に満たなければ API を呼ばずに not_judgeable
  (終わりの wait / home では人がブロックを箱から出していることがあるので, そこは使わない)
- API は今の vlm_judge (dynamic_tracking_limits/place/place_modules/vlm_judge.py) と同じモデル・キーの読み方.
  使えない (キーがない・通信やクレジットのエラー) 回は行を書かずに飛ばし, 最後に数を出す
- --rule (依頼 185): 送ったチャンク 0 の回 → not_applicable (決め 2), AI が frames/ だけ・素材なしで
  not_judgeable とした回 → not_judgeable (決め 3). 両方なら 2. 確定の行 (run_input・人・rule) がある回には足さない
"""
import argparse
import base64
import csv
import json
import os
import sys
import time
import urllib.error
import urllib.request
from collections import Counter
from pathlib import Path

HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE))
sys.path.insert(0, str(HERE.parent.parent / "dynamic_tracking_limits" / "place" / "place_modules"))
import verdicts as V  # noqa: E402
import vlm_judge  # noqa: E402

N_IMAGES = 6
MIN_IMAGES = 2
MP4_FRACTIONS = (0.3, 0.5, 0.65, 0.8, 0.9, 1.0)
MP4_WIDTH = 960
API_TIMEOUT_SEC = 90.0
API_MAX_TOKENS = 600

PROMPT = """画像は mechArm 270 (ロボットアーム) の作業台を真上から見たもので, 時間の順に並んでいる ({n} 枚・{source}).
課題は「赤いブロックをつかみ, 白い箱の中に置く」(put the red block in the white box). AI の方策が動かしている.
{source_note}
この回について, 次を判定してください.
- pick: 赤いブロックを爪でつかんで持ち上げられたか (yes / no / unknown)
- place: 最後に赤いブロックが白い箱の中にあるか (yes / no / unknown)
- outcome: success (最後に赤いブロックが白い箱の中にある) / failure (箱の中にない・つかめていない・落とした) /
  unknown (画像はあるが判別できない) / not_judgeable (画像が終わりまで写っておらず判定できない)
以下の JSON だけで返答してください. 前置きや後置きの説明は一切含めないこと.
{{"pick": "yes|no|unknown", "place": "yes|no|unknown", "outcome": "success|failure|unknown|not_judgeable", "reason": "日本語で 1〜2 文の短い理由"}}"""

NOTE_MP4 = ("上カメラの録画から, 方策が動いていた区間の後ろ寄りのコマを選んだ. 最後の 1 枚は方策が止まる直前. "
            "人の手が写ることがある (補正や置き直し).")
NOTE_FRAMES = ("各画像は方策に渡した入力画像で, チャンク (動きのひとまとまり) を送る前に撮ったもの. "
               "最後の 1 枚は最後のチャンクを送る前なので, その後の動きは写っていない. "
               "赤いブロックが写っていない画像があってもよい (爪の中や箱の中にあることがある).")


def mp4_active_end(run_dir, n_frames):
    """top_frame_log.csv で mode が wait / home でない最後のコマ. 読めなければ最後のコマ."""
    p = V.safe_file(run_dir, "recording", "top_frame_log.csv")
    last = None
    try:
        if p is None:
            raise FileNotFoundError
        with open(p, newline="") as f:
            for r in csv.DictReader(f):
                if r.get("mode") not in ("wait", "home"):
                    last = int(r["frame_idx"])
    except Exception:
        last = None
    if last is None:
        return n_frames - 1
    return max(0, min(last, n_frames - 1))


def mp4_images(run_dir):
    import cv2
    cap = cv2.VideoCapture(str(Path(run_dir) / "recording" / "top.mp4"))
    try:
        n = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        if n <= 0:
            return [], {}
        end = mp4_active_end(run_dir, n)
        idxs = sorted(set(int(round(end * fr)) for fr in MP4_FRACTIONS))
        out = []
        for i in idxs:
            cap.set(cv2.CAP_PROP_POS_FRAMES, i)
            ok, img = cap.read()
            if not ok or img is None:
                continue
            h, w = img.shape[:2]
            if w > MP4_WIDTH:
                img = cv2.resize(img, (MP4_WIDTH, int(h * MP4_WIDTH / w)))
            ok, buf = cv2.imencode(".jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 85])
            if ok:
                out.append(buf.tobytes())
        return out, {"mp4_frames": n, "active_end": end, "picked": idxs}
    finally:
        cap.release()


def frames_images(run_dir):
    names = V.frame_files(run_dir)
    if not names:
        return [], {}
    if len(names) <= N_IMAGES:
        pick = names
    else:
        step = (len(names) - 1) / (N_IMAGES - 1)
        pick = [names[int(round(i * step))] for i in range(N_IMAGES)]
    out = [(Path(run_dir) / "frames" / nm).read_bytes() for nm in pick]
    return out, {"frames": len(names), "picked": pick}


def material(run_dir):
    """(evidence, 画像の bytes のリスト, メモ). 素材が足りなければ evidence='' で画像は空."""
    if V.has_top_mp4(run_dir):
        imgs, info = mp4_images(run_dir)
        if len(imgs) >= MIN_IMAGES:
            return "top.mp4", imgs, info
    imgs, info = frames_images(run_dir)
    if len(imgs) >= MIN_IMAGES:
        return "frames", imgs, info
    return "", [], info


def api_key():
    k = os.environ.get("ANTHROPIC_API_KEY")
    if not k:
        p = os.path.expanduser("~/.anthropic_key")
        if os.path.isfile(p):
            k = open(p).read().strip()
            # 「export ANTHROPIC_API_KEY=...」の形で置かれていることがある (2026-11-14 に確かめた)
            if k.startswith("export "):
                k = k[len("export "):].strip()
            if k.startswith("ANTHROPIC_API_KEY="):
                k = k[len("ANTHROPIC_API_KEY="):].strip()
            k = k.strip("'\"")
    return k or None


class ApiUnavailable(RuntimeError):
    pass


def call_api(key, imgs, evidence):
    source = "上カメラの録画 top.mp4 のコマ" if evidence == "top.mp4" else "frames/ の入力画像"
    note = NOTE_MP4 if evidence == "top.mp4" else NOTE_FRAMES
    content = [{"type": "image", "source": {"type": "base64", "media_type": "image/jpeg",
                                            "data": base64.b64encode(b).decode("ascii")}} for b in imgs]
    content.append({"type": "text", "text": PROMPT.format(n=len(imgs), source=source, source_note=note)})
    payload = {"model": vlm_judge.VLM_MODEL, "max_tokens": API_MAX_TOKENS,
               "messages": [{"role": "user", "content": content}]}
    req = urllib.request.Request(vlm_judge.VLM_API_URL, data=json.dumps(payload).encode("utf-8"),
                                 headers={"x-api-key": key, "anthropic-version": vlm_judge.VLM_ANTHROPIC_VERSION,
                                          "content-type": "application/json"}, method="POST")
    last_err = ""
    for attempt in range(3):
        try:
            with urllib.request.urlopen(req, timeout=API_TIMEOUT_SEC) as resp:
                body = json.loads(resp.read().decode("utf-8"))
            text = "".join(c.get("text", "") for c in body.get("content", []) if c.get("type") == "text")
            return vlm_judge._parse_json_from_text(text), text
        except urllib.error.HTTPError as e:
            last_err = f"http_{e.code}"
            if e.code in (429, 500, 502, 503, 504, 529):
                time.sleep(5 * (attempt + 1))
                continue
            raise ApiUnavailable(last_err)
        except Exception as e:
            last_err = type(e).__name__
            time.sleep(3)
    raise ApiUnavailable(last_err)


def ai_row(run_stem, parsed, evidence, n_exec):
    def pv(v):
        return v if v in V.PICK_PLACE else "unknown"
    oc = parsed.get("outcome") if isinstance(parsed, dict) else None
    oc = oc if oc in V.AI_OUTCOMES else "unknown"
    reason = str(parsed.get("reason", "")).replace("\n", " ").strip() if isinstance(parsed, dict) else ""
    return {"labeled_at": V.now_iso(), "run_stem": run_stem,
            "pick": pv(parsed.get("pick")), "place": pv(parsed.get("place")), "outcome": oc, "labeler": "ai",
            "ai_outcome": oc, "ai_reason": f"[送ったチャンク {n_exec}] {reason}", "evidence": evidence, "note": ""}


def do_run_input(csv_path, runs_dir, dry_run):
    have = V.latest_by_stem(V.read_rows(csv_path), labelers=("run_input",) + V.HUMAN_LABELERS)
    rows = []
    for stem in V.list_run_stems(runs_dir):
        if stem in have:
            continue
        r = V.run_input_row(stem, V.read_run_json(Path(runs_dir) / stem))
        if r:
            rows.append(r)
    c = Counter(r["outcome"] for r in rows)
    print(f"[COPY ] 写す行 {len(rows)} (success {c['success']} / failure {c['failure']} / unknown {c['unknown']})"
          + (" ※ dry-run なので書いていません" if dry_run else ""))
    if not dry_run:
        written = V.append_rows(rows, csv_path, skip_if_labeled_by=("run_input",) + V.HUMAN_LABELERS,
                                 forbid_dirs=(runs_dir,))
        if len(written) != len(rows):
            print(f"[COPY ] 書くまでの間に人か写しの行が足されていた {len(rows) - len(written)} 回は足さなかった")
    return c


def do_ai(csv_path, runs_dir, dry_run, limit, only):
    rows = V.read_rows(csv_path)
    marked = set(V.latest_by_stem(rows, labelers=("run_input",)))
    have_ai = set(V.latest_by_stem(rows, labelers=("ai",)))
    human = set(V.latest_by_stem(rows, labelers=V.CONFIRMED_LABELERS))  # 確定した回には AI の行を足さない (codex R2・依頼 185)
    targets = []
    for stem in V.list_run_stems(runs_dir):
        j = V.read_run_json(Path(runs_dir) / stem)
        if j and j.get("outcome") not in (None, ""):
            continue  # 印がある回は写しの対象
        if stem in marked or stem in have_ai or stem in human:
            continue
        if only and stem not in only:
            continue
        targets.append(stem)
    if limit:
        targets = targets[:limit]
    key = None if dry_run else api_key()
    counts = Counter()
    print(f"[AI   ] 対象 {len(targets)} 回 (モデル {vlm_judge.VLM_MODEL})")
    for i, stem in enumerate(targets, 1):
        rd = Path(runs_dir) / stem
        n_exec = V.executed_chunks(V.read_log(rd))
        evidence, imgs, info = material(rd)
        if not imgs:
            row = {"labeled_at": V.now_iso(), "run_stem": stem, "pick": "unknown", "place": "unknown",
                   "outcome": "not_judgeable", "labeler": "ai", "ai_outcome": "not_judgeable",
                   "ai_reason": f"[送ったチャンク {n_exec}] 素材が足りない (top.mp4 なし・frames/ {len(V.frame_files(rd))} 枚). API は呼んでいない",
                   "evidence": "", "note": ""}
        elif dry_run:
            print(f"  {i:3d} {stem} {evidence} {len(imgs)} 枚 送ったチャンク {n_exec}")
            counts["dry_run"] += 1
            continue
        elif not key:
            counts["skipped"] += 1
            print(f"  {i:3d} {stem} 飛ばした (API キーがない)")
            continue
        else:
            try:
                parsed, text = call_api(key, imgs, evidence)
            except ApiUnavailable as e:
                counts["skipped"] += 1
                print(f"  {i:3d} {stem} 飛ばした (API: {e})")
                continue
            if not isinstance(parsed, dict):
                counts["skipped"] += 1
                print(f"  {i:3d} {stem} 飛ばした (答えを読めない: {text[:80]!r})")
                continue
            row = ai_row(stem, parsed, evidence, n_exec)
        if dry_run:
            print(f"  {i:3d} {stem} not_judgeable (素材なし) 送ったチャンク {n_exec}")
            counts["not_judgeable"] += 1
            continue
        # 1 回ずつ書く (途中で止まっても済んだ回は残る). API を待つ間に人が確定していたら足さない
        if not V.append_rows([row], csv_path, skip_if_labeled_by=("ai",) + V.CONFIRMED_LABELERS,
                            forbid_dirs=(runs_dir,)):
            counts["skipped_human"] += 1
            print(f"  {i:3d} {stem} 足さなかった (待つ間に人か写しの行が足されていた)")
            continue
        counts[row["outcome"]] += 1
        print(f"  {i:3d} {stem} {row['outcome']:13s} pick={row['pick']} place={row['place']} {evidence or '-'}  {row['ai_reason'][:70]}")
    print("[AI   ] " + " / ".join(f"{k} {counts[k]}" for k in
                                  ("success", "failure", "unknown", "not_judgeable", "skipped", "skipped_human", "dry_run") if counts[k] or k not in ("dry_run", "skipped_human")))
    return counts


def do_rule(csv_path, runs_dir, dry_run):
    """エイイチの決め (2026-11-14 依頼 185) の行を足す. 送ったチャンクは log.jsonl の chunk の行で executed が True の数."""
    rows = V.read_rows(csv_path)
    conf = V.latest_by_stem(rows, labelers=V.CONFIRMED_LABELERS)
    ai = V.latest_by_stem(rows, labelers=("ai",))
    out, counts = [], Counter()
    for stem in V.list_run_stems(runs_dir):
        rd = Path(runs_dir) / stem
        n_exec = V.executed_chunks(V.read_log(rd))
        a = ai.get(stem) or {}
        hit2 = n_exec == 0
        hit3 = a.get("outcome") == "not_judgeable" and a.get("evidence") in ("frames", "")
        if stem in conf:
            if hit2 or hit3:
                counts[f"skip_{conf[stem]['labeler']}"] += 1
                print(f"  {stem} 足さない (確定の行あり: {conf[stem]['labeler']} {conf[stem]['outcome']}・"
                      f"送ったチャンク {n_exec})")
            continue
        r = V.rule_row(stem, n_exec, ai.get(stem))
        if r is None:
            continue
        counts["rule2" if hit2 else "rule3"] += 1
        counts["both"] += hit2 and hit3
        out.append(r)
    print(f"[RULE ] 足す行 {len(out)} (決め2 not_applicable {counts['rule2']} (うち 3 にも当たる {counts['both']}) / "
          f"決め3 not_judgeable {counts['rule3']})" + (" ※ dry-run なので書いていません" if dry_run else ""))
    if not dry_run and out:
        written = V.append_rows(out, csv_path, skip_if_labeled_by=V.CONFIRMED_LABELERS, forbid_dirs=(runs_dir,))
        if len(written) != len(out):
            print(f"[RULE ] 書くまでの間に確定の行が足されていた {len(out) - len(written)} 回は足さなかった")
        counts["written"] = len(written)
    return counts


def main():
    ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    ap.add_argument("--run-input", action="store_true", help="{run_stem}.json の outcome を写す")
    ap.add_argument("--ai", action="store_true", help="印のない回を AI が判定する")
    ap.add_argument("--rule", action="store_true", help="エイイチの決め (依頼 185) の行を足す")
    ap.add_argument("--dry-run", action="store_true", help="書かない・API を呼ばない")
    ap.add_argument("--limit", type=int, default=0, help="AI の対象を先頭から N 回まで")
    ap.add_argument("--stems", nargs="*", default=None, help="AI の対象をこの run_stem だけにする")
    ap.add_argument("--runs-dir", default=str(V.RUNS_DIR))
    a = ap.parse_args()
    if not (a.run_input or a.ai or a.rule):
        ap.error("--run-input か --ai か --rule を付けてください")
    try:
        csv_path = V.VERDICTS_CSV  # 書き先は保存先テーブルの 1 か所だけ (codex R3. テストは関数に渡す)
        V.ensure_ssd_mounted(csv_path)
        if a.run_input:
            do_run_input(csv_path, a.runs_dir, a.dry_run)
        if a.ai:
            do_ai(csv_path, a.runs_dir, a.dry_run, a.limit, set(a.stems) if a.stems else None)
        if a.rule:
            do_rule(csv_path, a.runs_dir, a.dry_run)
    except (V.NotMounted, V.BrokenCsv) as e:
        print(f"[ABORT] {e}")
        return 2
    return 0


if __name__ == "__main__":
    sys.exit(main())
```


### server.py

```python
#!/usr/bin/env python3
"""推論の記録に成功/失敗を付ける判定の画面 (依頼 183).

  python3 pi05/verdict_viewer/server.py            # http://localhost:8765/ をブラウザで開く
  python3 pi05/verdict_viewer/server.py --no-open  # ブラウザを開かない

- 元の記録 (runs/pi05_policy/) は読むだけ. 判定は pi05_policy_verdicts_v1.csv に 1 行ずつ追記するだけ
- 書く前に KIOXIA のマウントを確かめ, なければ書かずに画面へエラーを返す
- localhost だけで待ち受ける
"""
import argparse
import csv
import json
import mimetypes
import re
import sys
import threading
import webbrowser
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from urllib.parse import unquote, urlparse

HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE))
import verdicts as V  # noqa: E402

STEM_RE = re.compile(r"^pi05_[0-9_]+$")
FRAME_RE = re.compile(r"^[0-9A-Za-z_]+\.jpg$")
MAX_STATE_POINTS = 1500


def state_series(run_dir):
    """関節 6 本と爪の時系列. recording/states.csv があればそれ, なければ log.jsonl の state."""
    rd = Path(run_dir)
    p = V.safe_file(rd, "recording", "states.csv")
    t, joints, grip = [], [], []
    stages = []
    if p is not None:
        t0 = None
        with open(p, newline="") as f:
            for r in csv.DictReader(f):
                try:
                    ts = float(r["ts"])
                except (TypeError, ValueError):
                    continue
                t0 = ts if t0 is None else t0
                ev = r.get("event_type")
                if ev == "actual":
                    try:
                        joints.append([float(r[f"j{i}"]) for i in range(6)])
                    except (TypeError, ValueError):
                        continue
                    t.append(round(ts - t0, 3))
                elif ev == "gripper_cmd" and r.get("gripper_state") not in (None, ""):
                    try:
                        grip.append([round(ts - t0, 3), float(r["gripper_state"])])
                    except ValueError:
                        pass
                elif ev == "stage":
                    stages.append([round(ts - t0, 3), r.get("stage", "")])
        if len(t) > MAX_STATE_POINTS:
            k = len(t) / MAX_STATE_POINTS
            idx = sorted(set(int(i * k) for i in range(MAX_STATE_POINTS)) | {len(t) - 1})
            t = [t[i] for i in idx]
            joints = [joints[i] for i in idx]
        return {"source": "recording/states.csv", "t": t, "joints": joints, "grip": grip,
                "grip_label": "爪の命令 (0 開 / 1 閉)", "stages": stages, "t0": t0}
    t0 = None
    for x in V.read_log(rd):
        if "chunk" not in x or "state" not in x:
            continue
        try:
            st = json.loads(x["state"]) if isinstance(x["state"], str) else x["state"]
            ts = float(x["t"])
        except Exception:
            continue
        if not isinstance(st, list) or len(st) < 6:
            continue
        t0 = ts if t0 is None else t0
        t.append(round(ts - t0, 3))
        joints.append([float(v) for v in st[:6]])
        if len(st) >= 7:
            grip.append([round(ts - t0, 3), float(st[6])])
    return {"source": "log.jsonl の state (推論の前に読んだ値)", "t": t, "joints": joints, "grip": grip,
            "grip_label": "state の爪 (7 番目の値)", "stages": [], "t0": t0}


def video_times(run_dir, t0):
    """top.mp4 の各コマの時刻 (states の始まりからの秒). 再生位置のしるしに使う."""
    p = V.safe_file(run_dir, "recording", "top_frame_log.csv")
    if t0 is None or p is None:
        return None
    out = []
    try:
        with open(p, newline="") as f:
            for r in csv.DictReader(f):
                out.append(round(float(r["capture_ts"]) - t0, 3))
    except Exception:
        return None
    return out


class App:
    def __init__(self, runs_dir, csv_path):
        self.runs_dir = Path(runs_dir)
        self.csv_path = Path(csv_path)
        self.lock = threading.Lock()
        self.done_ops = {}  # 画面の 1 回の操作 (op_id) → 書いた行. 応答が届かず押し直しても 2 回書かない (codex R7)

    def runs_summary(self):
        rows = V.read_rows(self.csv_path)
        latest = V.current_by_stem(rows)  # 確定の行があればそれ (依頼 185)
        ai = V.latest_by_stem(rows, labelers=("ai",))
        human = V.latest_by_stem(rows, labelers=V.HUMAN_LABELERS)
        out = []
        for stem in V.list_run_stems(self.runs_dir):
            rd = self.runs_dir / stem
            lt, a, h = latest.get(stem), ai.get(stem), human.get(stem)
            out.append({
                "run_stem": stem,
                "has_mp4": V.has_top_mp4(rd),
                "n_frames": len(V.frame_files(rd)),
                "outcome": lt["outcome"] if lt else "",
                "labeler": lt["labeler"] if lt else "",
                "ai_outcome": a["outcome"] if a else "",
                "human_outcome": h["outcome"] if h else "",
                "human_at": h["labeled_at"] if h else "",  # 人が確定した時刻 (自分が確定した回の一覧. 依頼 187)
                "confirmed": bool(lt and lt["labeler"] in V.CONFIRMED_LABELERS),
            })
        return out

    def stats(self):
        """確定した回だけの成功率 (依頼 185). 記録のフォルダにある回だけ数える."""
        stems = set(V.list_run_stems(self.runs_dir))
        return V.success_rate([r for r in V.read_rows(self.csv_path) if r["run_stem"] in stems])

    def run_detail(self, stem):
        rd = self.runs_dir / stem
        rows = [r for r in V.read_rows(self.csv_path) if r["run_stem"] == stem]
        ai = [r for r in rows if r["labeler"] == "ai"]
        j = V.read_run_json(rd)
        log = V.read_log(rd)
        st = state_series(rd)
        return {
            "run_stem": stem,
            "has_mp4": V.has_top_mp4(rd),
            "frames": V.frame_files(rd),
            "states": st,
            "video_t": video_times(rd, st.get("t0")) if V.has_top_mp4(rd) else None,
            "ai": ai[-1] if ai else None,
            "latest": V.current_by_stem(rows).get(stem),
            "history": rows,
            "executed_chunks": V.executed_chunks(log),
            "end_reason": (j or {}).get("end_reason", ""),
            "model": next((x.get("model") for x in log if x.get("type") == "model"), "")
                     or ((j or {}).get("args") or {}).get("model", ""),
        }

    def add_verdict(self, body):
        stem = body.get("run_stem", "")
        if (not STEM_RE.match(stem) or not (self.runs_dir / stem).is_dir()
                or not V.within(self.runs_dir, self.runs_dir / stem)):
            raise ValueError(f"run_stem がありません: {stem!r}")
        outcome = body.get("outcome")
        if outcome not in V.OUTCOMES:
            raise ValueError(f"outcome が正しくありません: {outcome!r}")
        rd = self.runs_dir / stem
        op_id = str(body.get("op_id") or "")
        with self.lock:
            if op_id and op_id in self.done_ops:
                print(f"[SAVE ] {stem} 同じ操作の送り直し. 書いていない (op_id {op_id})")
                return self.done_ops[op_id]
            ai = V.latest_by_stem(V.read_rows(self.csv_path), labelers=("ai",)).get(stem)
            default = "yes" if outcome == "success" else "unknown"
            pick = body.get("pick") or default
            place = body.get("place") or default
            row = {"labeled_at": V.now_iso(), "run_stem": stem, "pick": pick, "place": place,
                   "outcome": outcome, "labeler": V.human_labeler_for(outcome, ai),
                   "ai_outcome": ai["outcome"] if ai else "", "ai_reason": ai["ai_reason"] if ai else "",
                   "evidence": "top.mp4" if V.has_top_mp4(rd) else ("frames" if V.frame_files(rd) else ""),
                   "note": str(body.get("note", "")).replace("\n", " ").strip()}
            written = V.append_rows([row], self.csv_path, forbid_dirs=(self.runs_dir,))[0]
            if op_id:
                self.done_ops[op_id] = written
            print(f"[SAVE ] {written['run_stem']} {written['outcome']} pick={written['pick']} "
                  f"place={written['place']} labeler={written['labeler']}")
            return written


def make_handler(app):
    class H(BaseHTTPRequestHandler):
        def log_message(self, fmt, *args):
            pass

        def _send(self, code, data, ctype="application/json; charset=utf-8", extra=None):
            if not isinstance(data, (bytes, bytearray)):
                data = json.dumps(data, ensure_ascii=False).encode("utf-8")
            self.send_response(code)
            self.send_header("Content-Type", ctype)
            self.send_header("Content-Length", str(len(data)))
            self.send_header("Cache-Control", "no-store")
            for k, v in (extra or {}).items():
                self.send_header(k, v)
            self.end_headers()
            if self.command != "HEAD":
                self.wfile.write(data)

        def _file(self, stem, *rel):
            # リンクでその回の記録の外へ出ない (codex R6・3 回目 R2)
            path = V.safe_file(app.runs_dir / stem, *rel) if V.within(app.runs_dir, app.runs_dir / stem) else None
            if path is None:
                return self._send(404, {"error": "not found"})
            size = path.stat().st_size
            ctype = mimetypes.guess_type(str(path))[0] or "application/octet-stream"
            rng = self.headers.get("Range")
            start, end = 0, size - 1
            if rng:
                m = re.match(r"bytes=(\d*)-(\d*)", rng)
                if m:
                    if m.group(1):
                        start = int(m.group(1))
                        if m.group(2):
                            end = min(int(m.group(2)), size - 1)
                    elif m.group(2):
                        start = max(0, size - int(m.group(2)))
                if start > end or start >= size:
                    self.send_response(416)
                    self.send_header("Content-Range", f"bytes */{size}")
                    self.end_headers()
                    return
            length = end - start + 1
            self.send_response(206 if rng else 200)
            self.send_header("Content-Type", ctype)
            self.send_header("Accept-Ranges", "bytes")
            self.send_header("Content-Length", str(length))
            if rng:
                self.send_header("Content-Range", f"bytes {start}-{end}/{size}")
            self.end_headers()
            if self.command == "HEAD":
                return
            with open(path, "rb") as f:
                f.seek(start)
                left = length
                while left > 0:
                    chunk = f.read(min(1 << 20, left))
                    if not chunk:
                        break
                    try:
                        self.wfile.write(chunk)
                    except (BrokenPipeError, ConnectionResetError):
                        return
                    left -= len(chunk)

        def do_HEAD(self):
            self.do_GET()

        def do_GET(self):
            u = urlparse(self.path)
            parts = [unquote(p) for p in u.path.split("/") if p]
            try:
                if not parts:
                    return self._send(200, (HERE / "index.html").read_bytes(), "text/html; charset=utf-8")
                if parts == ["api", "runs"]:
                    return self._send(200, {"runs": app.runs_summary(), "stats": app.stats(), "csv": str(app.csv_path)})
                if (len(parts) == 3 and parts[:2] == ["api", "run"] and STEM_RE.match(parts[2])
                        and (app.runs_dir / parts[2]).is_dir() and V.within(app.runs_dir, app.runs_dir / parts[2])):
                    return self._send(200, app.run_detail(parts[2]))
                if len(parts) == 3 and parts[0] == "media" and STEM_RE.match(parts[1]) and parts[2] == "top.mp4":
                    return self._file(parts[1], "recording", "top.mp4")
                if (len(parts) == 4 and parts[0] == "media" and STEM_RE.match(parts[1]) and parts[2] == "frames"
                        and FRAME_RE.match(parts[3])):
                    return self._file(parts[1], "frames", parts[3])
                return self._send(404, {"error": "not found"})
            except Exception as e:  # 画面に理由を返す
                return self._send(500, {"error": f"{type(e).__name__}: {e}"})

        def do_POST(self):
            if urlparse(self.path).path != "/api/verdict":
                return self._send(404, {"error": "not found"})
            try:
                n = int(self.headers.get("Content-Length") or 0)
                body = json.loads(self.rfile.read(n).decode("utf-8") or "{}")
                row = app.add_verdict(body)
                return self._send(200, {"ok": True, "row": row})
            except (V.NotMounted, V.BrokenCsv) as e:
                print(f"[ABORT] {e}")
                return self._send(503, {"error": str(e)})
            except ValueError as e:
                return self._send(400, {"error": str(e)})
            except Exception as e:
                return self._send(500, {"error": f"{type(e).__name__}: {e}"})
    return H


def main():
    ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    ap.add_argument("--port", type=int, default=8765)
    ap.add_argument("--no-open", action="store_true", help="ブラウザを開かない")
    ap.add_argument("--runs-dir", default=str(V.RUNS_DIR))
    ap.add_argument("--test-csv", default=None,
                    help="画面の確かめ用. 判定を保存先テーブルの CSV でなくこのファイルに書く (ふだんは付けない)")
    a = ap.parse_args()
    if not Path(a.runs_dir).is_dir():
        print(f"[ABORT] 記録のフォルダがありません ({a.runs_dir}). KIOXIA をつないでください")
        return 2
    csv_path = Path(a.test_csv) if a.test_csv else V.VERDICTS_CSV
    if a.test_csv and V.within(a.runs_dir, csv_path):
        print(f"[ABORT] --test-csv が記録のフォルダの中です ({csv_path}). 元の記録には書きません")
        return 2
    if a.test_csv:
        print(f"[TEST ] 確かめ用: 判定は {csv_path} に書きます (保存先テーブルの CSV には書きません)")
    app = App(a.runs_dir, csv_path)
    srv = ThreadingHTTPServer(("127.0.0.1", a.port), make_handler(app))
    url = f"http://localhost:{a.port}/"
    print(f"[VIEW ] {url}  (判定は {csv_path} に追記. Ctrl-C で終わる)")
    if not a.no_open:
        threading.Timer(0.5, lambda: webbrowser.open(url)).start()
    try:
        srv.serve_forever()
    except KeyboardInterrupt:
        pass
    finally:
        srv.server_close()
    return 0


if __name__ == "__main__":
    sys.exit(main())
```


### index.html

```html
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>推論の記録の判定</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=Noto+Sans+JP:wght@400;600;700&display=swap" rel="stylesheet">
<style>
  /* 見た目は配膳ロボット ブラウザ版 (pixelstomotors.com/sim/serving-robot-3d) に合わせる (依頼 186) */
  :root {
    --ink: #1d1d1b; --sub: #6b6b66; --line: #d8d6d0; --bg: #f2f1ee; --stop: #d64545; --ok: #1761e6;
    --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100; --s5: #e87ba4; --s6: #008300;
    --grip: #6b6b66;
  }
  * { box-sizing: border-box; }
  body { margin: 0; font-family: "Noto Sans JP", "Inter", system-ui, sans-serif; font-size: 13px; line-height: 1.5; color: var(--ink);
         background: var(--bg); height: 100vh; display: grid; grid-template-columns: 280px 1fr 320px; }
  /* 左の一覧 */
  #side { min-height: 0; background: #fff; border-right: 1px solid var(--line); display: flex; flex-direction: column; }
  #side header { padding: 16px; border-bottom: 1px solid var(--line); }
  #side h1 { margin: 0 0 8px; font-size: 15px; }
  #filter { width: 100%; font: inherit; border: 1px solid var(--line); border-radius: 6px; padding: 5px 40px 5px 6px; color: var(--ink); cursor: pointer;
    appearance: none; -webkit-appearance: none; height: 33px;  /* ブラウザの矢印の代わりに太い山形. 高さは元の 33px のまま (依頼 198) */
    background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%231d1d1b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 14px center / 12px 8px; }
  #count { color: var(--sub); margin-top: 6px; font-size: 11px; }
  #list { overflow-y: auto; flex: 1; }
  .item { padding: 6px 16px; border-bottom: 1px solid var(--line); cursor: pointer; display: flex; justify-content: space-between; gap: 6px; }
  .item:hover { background: var(--bg); }
  .item.sel { background: var(--ink); color: #fff; }
  .item .stem { font: 600 13px/1.3 "Inter", "Noto Sans JP", system-ui, sans-serif; }
  .item .sub { color: var(--sub); font-size: 11px; }
  .item.sel .sub { color: rgba(255,255,255,.7); }
  /* 判定の札: 形は手本の .tag. 成功は青 (手本のスタッフ)・失敗は赤 (手本の止まっている)・ほかは色なし.
     人が確定 (と記録時の入力・決め) は塗り, AI だけ (未確定) は白地に同じ色の 1px の枠と字 (依頼 189).
     枠は高さを変えないよう内側の線で引く */
  .tag { flex: none; min-width: 24px; text-align: center; font: 600 11px/18px "Inter", "Noto Sans JP", system-ui, sans-serif; border-radius: 6px;
         padding: 0 7px; background: #fff; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); white-space: nowrap; align-self: center; display: inline-block; }
  .tag.success { background: var(--ok); color: #fff; box-shadow: inset 0 0 0 1px var(--ok); }
  .tag.failure { background: var(--stop); color: #fff; box-shadow: inset 0 0 0 1px var(--stop); }
  .tag.ai.success { background: #fff; color: var(--ok); }
  .tag.ai.failure { background: #fff; color: var(--stop); }
  /* 真ん中 */
  #main { min-width: 0; overflow-y: auto; padding: 14px 16px; }
  #hud { display: inline-block; background: rgba(255,255,255,.92); padding: 10px 14px; border-radius: 8px; margin-bottom: 12px; }
  #title { font: 600 28px/1 "Inter", "Noto Sans JP", system-ui, sans-serif; }
  #meta { margin: 6px 0 0; font-size: 12px; color: var(--sub); }
  #media { width: 640px; }
  #media video, #media img { width: 640px; background: #000; display: block; border-radius: 8px; }
  #framebar { display: flex; gap: 10px; align-items: center; margin-top: 8px; background: rgba(255,255,255,.92); padding: 8px 12px; border-radius: 8px; }
  #fr { flex: 1; -webkit-appearance: none; appearance: none; height: 6px; border-radius: 3px;
        background: linear-gradient(90deg, #1d1d1b var(--done, 0%), #d8d6d0 var(--done, 0%)); }
  #fr::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 2px solid #1d1d1b; cursor: pointer; }
  #fr::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: #fff; border: 2px solid #1d1d1b; }
  #fl { font-size: 11px; color: var(--sub); white-space: nowrap; }
  #media .muted { margin-top: 4px; }
  /* 右の操作パネル */
  #panel { min-height: 0; background: #fff; border-left: 1px solid var(--line); padding: 16px; overflow: auto; font-size: 13px; }
  h2 { font-size: 12px; color: var(--sub); font-weight: 600; margin: 16px 0 6px; }
  #panel > h2:first-child { margin-top: 0; }
  .nums { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; margin-top: 4px; }
  .num { line-height: 1.25; }
  .num b { display: block; font: 600 24px/1.1 "Inter", "Noto Sans JP", system-ui, sans-serif; }
  .num small { font-size: 12px; font-weight: 400; margin-left: 2px; }
  .num > span { display: block; margin-top: 1px; line-height: 1.3; font-size: 11px; color: var(--sub); }
  .note { margin: 6px 0 0; font-size: 11px; line-height: 1.6; color: var(--sub); }
  .seg { display: flex; flex-wrap: wrap; gap: 4px; }
  .row { display: flex; gap: 6px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
  .row .lbl { width: 40px; color: var(--sub); font-size: 12px; font-weight: 600; }
  button { font: inherit; border: 1px solid var(--line); background: #fff; border-radius: 6px; padding: 5px 9px; cursor: pointer; color: var(--ink); }
  button.on { background: var(--ink); color: #fff; border-color: var(--ink); }
  button.key { flex: 1 1 calc(50% - 3px); text-align: left; }
  /* 判定するのボタン: 人の確定と押した判定を塗る. 成功は青・失敗は赤・ほかは --ink (依頼 189) */
  button.key.on[data-oc="success"] { background: var(--ok); border-color: var(--ok); }
  button.key.on[data-oc="failure"] { background: var(--stop); border-color: var(--stop); }
  /* 確定のボタン: 手本の #cta a の強さ. y/n/u/x を選ぶまでは薄く押せない (依頼 192) */
  #confirm { display: block; width: 100%; margin-top: 10px; text-align: center; background: var(--ink); color: #fff; border-color: var(--ink);
             font-weight: 600; font-size: 14px; padding: 11px 12px; border-radius: 6px; }
  #confirm:hover:not(:disabled) { background: #000; }
  #confirm:disabled { opacity: .3; cursor: default; }
  #confirm kbd { margin-left: 6px; }
  kbd { font: 600 11px/1 "Inter", system-ui, sans-serif; border: 1px solid var(--line); border-radius: 6px; padding: 2px 5px; background: var(--bg); color: var(--ink); }
  #note { width: 100%; font: inherit; padding: 5px 6px; border: 1px solid var(--line); border-radius: 6px; color: var(--ink); }
  #status { min-height: 1em; margin: 6px 0 0; font-size: 12px; color: var(--sub); }
  #status.err { color: var(--stop); font-weight: 600; }
  #status.ok { color: var(--ink); }
  .dark { background: rgba(60,62,66,.86); color: #fff; border-radius: 8px; padding: 10px 12px; font-size: 12px; }
  .dark .muted { color: #b9bcc1; }
  .big { font-size: 16px; font-weight: 600; }
  /* グラフ */
  #chart { margin-top: 12px; position: relative; background: #fff; border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }
  #chart:empty { display: none; }
  #chart svg text { font: 400 11px "Inter", "Noto Sans JP", system-ui, sans-serif; fill: var(--sub); }
  #legend { display: flex; gap: 12px; flex-wrap: wrap; font-size: 12px; color: var(--sub); margin: 0 0 4px; }
  #legend span::before { content: ""; display: inline-block; width: 14px; height: 2px; vertical-align: middle; margin-right: 4px; background: var(--c); }
  #tip { position: absolute; pointer-events: none; background: rgba(255,255,255,.92); border: 1px solid var(--line); border-radius: 6px;
         padding: 4px 6px; font-size: 11px; display: none; white-space: nowrap; }
  #tip i { display: inline-block; width: 10px; height: 2px; vertical-align: middle; margin-right: 4px; }
  table.hist { border-collapse: collapse; font-size: 11px; width: 100%; }
  table.hist td, table.hist th { border-bottom: 1px solid var(--line); padding: 4px 4px 4px 0; text-align: left; vertical-align: top; }
  table.hist th { color: var(--sub); font-weight: 600; }
  table.hist td:not(:first-child), table.hist th { white-space: nowrap; }
  .muted { color: var(--sub); }
  /* 自分が確定した回 (依頼 187). 形は button と #hud の白い札だけ */
  #recent button { display: flex; width: 100%; justify-content: space-between; gap: 6px; margin-top: 4px; text-align: left; }
  #recent .stem { font: 600 12px/1.3 "Inter", "Noto Sans JP", system-ui, sans-serif; }
  #recent button .tag { margin-right: 4px; }
  #toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: rgba(255,255,255,.92); padding: 10px 14px;
           border-radius: 8px; font-weight: 600; display: none; z-index: 10; }
  #toast .tag { margin-left: 4px; }
  #cur .tag { vertical-align: 2px; }
</style>
</head>
<body>
<div id="side">
  <header>
    <h1>推論の記録の判定</h1>
    <select id="filter">
      <option value="todo">まだ確定していない回</option>
      <option value="all">全部</option>
      <option value="failure">失敗だけ (今の判定)</option>
      <option value="diff">AI と人が違う回</option>
      <option value="mine">自分が確定した回 (新しい順)</option>
    </select>
    <div id="count"></div>
  </header>
  <div id="list"></div>
</div>
<div id="main">
  <div id="hud">
    <div id="title">—</div>
    <div id="meta"></div>
  </div>
  <div id="media"></div>
  <div id="chart"></div>
</div>
<div id="toast"></div>
<aside id="panel">
  <h2>判定する (キー)</h2>
  <div class="row">
    <button class="key" data-oc="success"><kbd>y</kbd> 成功</button>
    <button class="key" data-oc="failure"><kbd>n</kbd> 失敗</button>
    <button class="key" data-oc="unknown"><kbd>u</kbd> 分からない</button>
    <button class="key" data-oc="not_judgeable"><kbd>x</kbd> 判定できない</button>
  </div>
  <div class="row"><span class="lbl">pick</span>
    <div class="seg"><button data-pp="pick" data-v="yes">つかめた</button><button data-pp="pick" data-v="no">つかめなかった</button><button data-pp="pick" data-v="unknown">分からない</button></div></div>
  <div class="row"><span class="lbl">place</span>
    <div class="seg"><button data-pp="place" data-v="yes">置けた</button><button data-pp="place" data-v="no">置けなかった</button><button data-pp="place" data-v="not_applicable">そこまで行かなかった</button><button data-pp="place" data-v="unknown">分からない</button></div></div>
  <p class="note">選ばなければ 成功→つかめた・置けた / ほか→分からない</p>
  <button id="confirm" disabled>確定<kbd>Enter</kbd></button>
  <h2>いま確定した回 (新しい 5 回)</h2><div id="recent"></div>
  <h2>ひとこと</h2>
  <input id="note" placeholder="ひとこと (空でよい・入力中は y/n/u/x は効かない・Enter で確定)">
  <div id="status"></div>
  <p class="note"><kbd>←</kbd> <kbd>→</kbd> 前後の回 ・ <kbd>Enter</kbd> 確定 ・ <kbd>,</kbd> <kbd>.</kbd> コマ送り / 動画は <kbd>space</kbd> で再生</p>
  <h2>AI の判定 (未確定)</h2><div id="ai" class="dark"></div>
  <h2>今の判定 (いちばん新しい行)</h2><div id="cur"></div>
  <h2>成功率 (確定した回だけ)</h2>
  <div id="rate"></div>
  <h2>この回の行 (古い順)</h2><div id="hist"></div>
</aside>
<script>
const OC_JA = {success: "成功", failure: "失敗", unknown: "分からない", not_judgeable: "判定できない", not_applicable: "試行でない", "": "なし"};
// pick / place の値は yes / no / unknown (place だけ not_applicable も) のまま. 画面の字だけ日本語 (依頼 193)
const PICK_JA = {yes: "つかめた", no: "つかめなかった", unknown: "分からない"};
const PLACE_JA = {yes: "置けた", no: "置けなかった", not_applicable: "そこまで行かなかった", unknown: "分からない"};
const ppJa = r => `pick ${esc(PICK_JA[r.pick] ?? r.pick)} / place ${esc(PLACE_JA[r.place] ?? r.place)}`;
const LB_JA = {run_input: "記録時の入力", ai: "AI", human: "人 (AI と同じ)", human_fixed_ai: "人 (AI を直した)", human_only: "人 (AI なし)", rule: "決め (依頼185)", "": ""};
const COLORS = ["--s1", "--s2", "--s3", "--s4", "--s5", "--s6"].map(v => getComputedStyle(document.documentElement).getPropertyValue(v).trim());
const pendingOps = {};  // run_stem → 書けたか分からない操作 (回ごとに残す. codex 6 回目 R1)
let selSeq = 0;  // 応答が届かなかった操作. 同じ中身で押し直したら同じ op_id で送る (codex 2 回目 R2)
let runs = [], view = [], cur = null, detail = null, pp = {pick: null, place: null}, frameIdx = 0, busy = false, loading = false;
let chosen = null;  // y/n/u/x で選んだ判定. 確定するまで書かない・回を移ったら捨てる (依頼 192)

const $ = s => document.querySelector(s);
const esc = s => String(s ?? "").replace(/[&<>"]/g, c => ({"&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;"}[c]));
function status(msg, kind) { const el = $("#status"); el.textContent = msg; el.className = kind || ""; }
const HUMAN = ["human", "human_fixed_ai", "human_only"];  // 人が確定した行 (依頼 187)
const hm = iso => String(iso || "").slice(11, 16);  // 時:分 (記録した側の時刻のまま)
const byHumanAt = (a, b) => Date.parse(b.human_at) - Date.parse(a.human_at);
let toastTimer = null;
function toast(html) { const el = $("#toast"); el.innerHTML = html; el.style.display = "block"; clearTimeout(toastTimer); toastTimer = setTimeout(() => el.style.display = "none", 3000); }
function tag(oc, ai) { return oc ? `<span class="tag ${oc} ${ai ? "ai" : ""}">${ai ? "AI " : ""}${OC_JA[oc]}</span>` : `<span class="tag">印なし</span>`; }

function applyFilter() {
  const f = $("#filter").value;
  view = runs.filter(r => f === "all" ? true : f === "todo" ? !r.confirmed : f === "failure" ? r.outcome === "failure"
                          : f === "mine" ? !!r.human_at
                          : (r.ai_outcome && r.human_outcome && r.ai_outcome !== r.human_outcome));
  if (f === "mine") view.sort(byHumanAt);  // 確定した時刻が新しい順 (依頼 187)
  $("#count").textContent = `${view.length} 回 / 全 ${runs.length} 回 (確定済み ${runs.filter(r => r.confirmed).length})`;
  $("#list").innerHTML = view.map(r => `<div class="item ${cur === r.run_stem ? "sel" : ""}" data-stem="${r.run_stem}">
      <div><div class="stem">${r.run_stem.replace("pi05_", "")}</div>
      <div class="sub">${f === "mine" ? `人が確定 ${hm(r.human_at)} ・ ${LB_JA[r.labeler] || "—"}`
        : `${r.has_mp4 ? "top.mp4" : r.n_frames ? "frames " + r.n_frames : "素材なし"} ・ ${LB_JA[r.labeler] || "—"}`}</div></div>
      ${f === "mine" ? tag(r.human_outcome, false) : tag(r.outcome, r.labeler === "ai")}</div>`).join("");
  document.querySelectorAll(".item").forEach(el => el.onclick = () => select(el.dataset.stem));
  renderRecent();
}

// いま確定した回: 人の行がある回を確定した時刻の新しい順に 5 回. 押すと開く (絞り込みはそのまま. 依頼 187)
function renderRecent() {
  const rec = runs.filter(r => r.human_at).sort(byHumanAt).slice(0, 5);
  $("#recent").innerHTML = rec.length ? rec.map(r => `<button class="${cur === r.run_stem ? "on" : ""}" data-recent="${r.run_stem}">
      <span class="stem">${r.run_stem.replace("pi05_", "")}</span><span>${tag(r.human_outcome, false)}${hm(r.human_at)}</span></button>`).join("")
    : `<span class="muted">まだありません</span>`;
  document.querySelectorAll("[data-recent]").forEach(b => b.onclick = () => { b.blur(); status(""); select(b.dataset.recent); });
}

// 成功率は確定した回だけ. 分母は 成功 + 失敗 (試行でない・判定できない・分からない は入れない. 依頼 185)
function renderRate(st) {
  if (!st) { $("#rate").textContent = ""; return; }
  const b = st.by_outcome || {};
  const num = (v, unit, label) => `<div class="num"><b>${v}${unit ? `<small>${unit}</small>` : ""}</b><span>${label}</span></div>`;
  $("#rate").innerHTML = `<div class="nums">`
    + num(st.rate === null ? "—" : (st.rate * 100).toFixed(1), st.rate === null ? "" : "%", "成功率 (成功 / (成功 + 失敗))")
    + num(st.confirmed, "回", "確定した回") + num(runs.filter(r => !r.confirmed).length, "回", "まだの回")
    + num(st.success, "回", "成功") + num(st.failure, "回", "失敗") + `</div>`
    + `<p class="note">分母に入れない: 試行でない ${b.not_applicable || 0} ・ 判定できない ${b.not_judgeable || 0} ・ 分からない ${b.unknown || 0} (確定 ${st.confirmed} 回のうち)</p>`;
}

async function loadRuns() {
  const res = await fetch("/api/runs"); const j = await res.json();
  if (!res.ok || !Array.isArray(j.runs)) throw new Error(j.error || "一覧を読めません");  // 今の一覧は残す (codex 4 回目 R1)
  runs = j.runs;
  renderRate(j.stats);  // まだの回は runs から数えるので runs を入れてから
  applyFilter();
}

async function select(stem) {
  const seq = ++selSeq;  // いちばん新しい選択の応答だけ使う (codex 5 回目 R2・6 回目 R3)
  if (!stem) {  // 空の一覧: 前の回の表示と状態を残さない (codex 7 回目 R1)
    cur = null; detail = null; chartGeom = null; loading = false; pp = {pick: null, place: null}; chosen = null; markPP(); markOC(null); $("#note").value = "";
    $("#title").textContent = "この絞り込みに残っている回はありません"; $("#meta").textContent = "";
    $("#media").innerHTML = $("#chart").innerHTML = $("#ai").innerHTML = $("#cur").innerHTML = $("#hist").innerHTML = "";
    return true;
  }
  // 読み込みが終わるまでは判定を受け付けない (前の回を見ながら次の回に書かない. codex R1)
  cur = stem; detail = null; loading = true; pp = {pick: null, place: null}; chosen = null; frameIdx = 0; $("#note").value = "";
  const po = pendingOps[stem];
  if (po) {
    // 書けたか分からない操作の回に戻ったら, そのときの入力を戻す (同じ確定で同じ op_id になる. codex 5 回目 R1)
    pp = {pick: po.payload.pick, place: po.payload.place}; $("#note").value = po.payload.note; chosen = po.payload.outcome;
  }
  $("#title").textContent = stem + " (読み込み中)"; $("#media").innerHTML = ""; $("#chart").innerHTML = "";
  $("#ai").innerHTML = $("#cur").innerHTML = $("#hist").innerHTML = "";
  applyFilter(); markPP(); markOC(null);
  document.querySelector(`.item[data-stem="${stem}"]`)?.scrollIntoView({block: "nearest"});
  let d;
  try { const res = await fetch("/api/run/" + stem); d = await res.json(); if (!res.ok) throw new Error(d.error); }
  catch (e) { if (seq === selSeq) { $("#title").textContent = stem; status("この回を読めませんでした: " + e.message + " ・ 一覧でもう一度選んでください", "err"); } return false; }
  if (seq !== selSeq || d.run_stem !== cur) return false;
  detail = d; loading = false; markConfirm();
  if (!po) {  // 記録した pick / place を塗る (人の確定があればそれ, なければ確定の行. 依頼 190)
    const r = recordedRow();
    if (r) { pp = {pick: r.pick || null, place: r.place || null}; markPP(); }
  }
  $("#title").textContent = stem;
  $("#meta").textContent = `送ったチャンク ${detail.executed_chunks} ・ 終わり方 ${detail.end_reason || "記録なし"} ・ ${detail.model || ""}`;
  renderMedia(); renderInfo(); renderChart();
  return true;
}

function renderMedia() {
  const m = $("#media");
  if (detail.has_mp4) {
    m.innerHTML = `<video id="vid" controls muted preload="metadata" src="/media/${detail.run_stem}/top.mp4"></video><div class="muted">recording/top.mp4</div>`;
    const v = $("#vid");
    v.onerror = () => { if (detail.frames.length) { status("top.mp4 を再生できないので frames/ を出します", "err"); detail.has_mp4 = false; renderMedia(); } else status("top.mp4 を再生できません (frames/ もなし)", "err"); };
    v.ontimeupdate = () => cursor(v.currentTime);
  } else if (detail.frames.length) {
    const n = detail.frames.length;
    m.innerHTML = `<img id="frm"><div id="framebar"><button id="fp">‹</button><input id="fr" type="range" min="0" max="${n - 1}" value="${frameIdx}"><button id="fn">›</button><span id="fl"></span></div><div class="muted">frames/ (各チャンクの前に撮った入力画像)</div>`;
    $("#fp").onclick = () => stepFrame(-1); $("#fn").onclick = () => stepFrame(1);
    $("#fr").oninput = e => { frameIdx = +e.target.value; showFrame(); };
    showFrame();
  } else {
    m.innerHTML = `<div class="muted">映像がありません (top.mp4 も frames/ もない)</div>`;
  }
}
function showFrame() {
  const n = detail.frames.length; frameIdx = Math.max(0, Math.min(n - 1, frameIdx));
  $("#frm").src = `/media/${detail.run_stem}/frames/${detail.frames[frameIdx]}`;
  $("#fr").value = frameIdx; $("#fr").style.setProperty("--done", (n > 1 ? frameIdx / (n - 1) * 100 : 100) + "%"); $("#fl").textContent = `${frameIdx + 1} / ${n}`;
}
function stepFrame(d) { if (detail && !detail.has_mp4 && detail.frames.length && $("#frm")) { frameIdx += d; showFrame(); } }

function renderInfo() {
  const a = detail.ai, l = detail.latest;
  $("#ai").innerHTML = a ? `<div class="big">${OC_JA[a.outcome]}</div><div>${ppJa(a)} ・ 素材 ${a.evidence || "なし"}</div><div class="muted">${esc(a.ai_reason)}</div>` : `<span class="muted">AI の判定はありません</span>`;
  const h = detail.history.filter(r => HUMAN.includes(r.labeler)).pop();  // 人が確定した行 (依頼 187)
  const c = h || l;  // 札は 1 回だけ. 札・人が確定・時刻・pick / place を 1 行目に (依頼 190)
  $("#cur").innerHTML = c ? `<div>${tag(c.outcome, c.labeler === "ai")} ${h ? "<b>人が確定済み</b>" : `<span class="muted">${LB_JA[c.labeler]}</span>`} ・ ${esc(c.labeled_at.slice(0, 10))} ${hm(c.labeled_at)} ・ ${ppJa(c)}</div>${c.note ? `<div class="muted">${esc(c.note)}</div>` : ""}` : `<span class="muted">まだ判定がありません</span>`;
  markOC();
  $("#hist").innerHTML = detail.history.length ? `<table class="hist"><tr><th>時刻</th><th>判定</th><th>pick/place</th><th>付けた</th></tr>${detail.history.map(r => `<tr><td>${esc(r.labeled_at)}</td><td>${tag(r.outcome, r.labeler === "ai")}</td><td>${esc(PICK_JA[r.pick] ?? r.pick)}/${esc(PLACE_JA[r.place] ?? r.place)}</td><td>${LB_JA[r.labeler]}</td></tr>`).join("")}</table>` : `<span class="muted">なし</span>`;
}

// ---- 関節と爪のグラフ (関節は 1 本の軸・爪は下に別の帯. 2 つの縦軸は使わない) ----
let chartGeom = null;
function renderChart() {
  // 幅は #main から (空のときは #chart を隠すので. 余白 32・枠と内側 26. 依頼 186)
  const s = detail.states, el = $("#chart");
  if (!s.t.length) { el.innerHTML = `<div class="muted">関節の記録がありません (recording/states.csv も log.jsonl の state もない)</div>`; chartGeom = null; return; }
  const W = Math.max(640, ($("#main").clientWidth || 900) - 58), H = 240, GH = 44, L = 44, R = 12, T = 8, gap = 22;
  const tmax = Math.max(s.t[s.t.length - 1], ...(s.grip.map(g => g[0]))) || 1;
  let lo = Infinity, hi = -Infinity;
  s.joints.forEach(js => js.forEach(v => { lo = Math.min(lo, v); hi = Math.max(hi, v); }));
  const pad = (hi - lo) * 0.06 || 5; lo -= pad; hi += pad;
  const x = t => L + (W - L - R) * t / tmax, y = v => T + (H - T - 18) * (hi - v) / (hi - lo);
  const gy0 = H + gap, gy = v => gy0 + GH - 6 - (GH - 12) * Math.max(0, Math.min(1, v));
  const ticks = []; const step = niceStep((hi - lo) / 5);
  for (let v = Math.ceil(lo / step) * step; v <= hi; v += step) ticks.push(v);
  const tstep = niceStep(tmax / 8); const tt = []; for (let v = 0; v <= tmax; v += tstep) tt.push(v);
  let svg = `<svg width="${W}" height="${gy0 + GH + 20}" id="csvg">`;
  ticks.forEach(v => svg += `<line x1="${L}" x2="${W - R}" y1="${y(v)}" y2="${y(v)}" stroke="#eeeeea"/><text x="${L - 6}" y="${y(v) + 4}" text-anchor="end">${+v.toFixed(1)}°</text>`);
  tt.forEach(v => svg += `<text x="${x(v)}" y="${gy0 + GH + 14}" text-anchor="middle">${+v.toFixed(0)}s</text>`);
  s.stages.forEach(([t, st]) => svg += `<line x1="${x(t)}" x2="${x(t)}" y1="${T}" y2="${gy0 + GH}" stroke="#d8d6d0" stroke-dasharray="2,3"/>`);
  for (let j = 0; j < 6; j++) {
    const d = s.t.map((t, i) => `${i ? "L" : "M"}${x(t).toFixed(1)},${y(s.joints[i][j]).toFixed(1)}`).join("");
    svg += `<path d="${d}" fill="none" stroke="${COLORS[j]}" stroke-width="2" stroke-linejoin="round"/>`;
  }
  svg += `<rect x="${L}" y="${gy0}" width="${W - L - R}" height="${GH}" fill="none" stroke="#d8d6d0"/>`;
  svg += `<text x="${L - 6}" y="${gy(1) + 4}" text-anchor="end">閉</text><text x="${L - 6}" y="${gy(0) + 4}" text-anchor="end">開</text>`;
  if (s.grip.length) {
    let d = `M${x(0)},${gy(s.grip[0][1])}`, pv = s.grip[0][1];
    s.grip.forEach(([t, v]) => { d += `L${x(t).toFixed(1)},${gy(pv)}L${x(t).toFixed(1)},${gy(v)}`; pv = v; });
    d += `L${x(tmax)},${gy(pv)}`;
    svg += `<path d="${d}" fill="none" stroke="var(--grip)" stroke-width="2"/>`;
  }
  svg += `<line id="cx" x1="0" x2="0" y1="${T}" y2="${gy0 + GH}" stroke="#1d1d1b" stroke-width="1" style="display:none"/>`;
  svg += `<line id="vx" x1="0" x2="0" y1="${T}" y2="${gy0 + GH}" stroke="var(--s1)" stroke-width="1" style="display:none"/>`;
  svg += `<rect id="hit" x="${L}" y="0" width="${W - L - R}" height="${gy0 + GH}" fill="transparent"/></svg>`;
  el.innerHTML = `<div id="legend">${COLORS.map((c, j) => `<span style="--c:${c}">j${j}</span>`).join("")}<span style="--c:var(--grip)">爪 (下の帯・${esc(s.grip_label)})</span><span class="muted">${esc(s.source)}</span></div>${svg}<div id="tip"></div>`;
  chartGeom = {x, tmax, L, W, R};
  const hit = $("#hit"), tip = $("#tip"), cx = $("#cx");
  hit.onmousemove = e => {
    const r = hit.getBoundingClientRect(), t = (e.clientX - r.left) / r.width * tmax;
    let i = 0; for (let k = 0; k < s.t.length; k++) { if (s.t[k] <= t) i = k; else break; }
    let g = null; s.grip.forEach(([gt, v]) => { if (gt <= t) g = v; });
    cx.setAttribute("x1", x(s.t[i])); cx.setAttribute("x2", x(s.t[i])); cx.style.display = "";
    tip.innerHTML = `<b>${s.t[i].toFixed(1)} 秒</b><br>` + s.joints[i].map((v, j) => `<i style="background:${COLORS[j]}"></i>j${j} ${v.toFixed(1)}°`).join("<br>") + (g === null ? "" : `<br>爪 ${g}`);
    tip.style.display = "block";
    const left = e.clientX - el.getBoundingClientRect().left + 14;
    tip.style.left = Math.min(left, W - 120) + "px"; tip.style.top = "30px";
  };
  hit.onmouseleave = () => { tip.style.display = "none"; cx.style.display = "none"; };
}
function niceStep(raw) { const p = Math.pow(10, Math.floor(Math.log10(raw || 1))); const n = raw / p; return (n < 1.5 ? 1 : n < 3 ? 2 : n < 7 ? 5 : 10) * p; }
function cursor(vt) {
  if (!chartGeom || !detail.video_t || !detail.video_t.length) return;
  const v = $("#vid"); const n = detail.video_t.length;
  const i = Math.max(0, Math.min(n - 1, Math.round(vt / (v.duration || 1) * (n - 1))));
  const xx = chartGeom.x(detail.video_t[i]); const l = $("#vx"); if (!l) return;
  l.setAttribute("x1", xx); l.setAttribute("x2", xx); l.style.display = "";
}

// 判定するのボタン: 指定がなければ開いている回の人の確定を塗る (依頼 189)
// 開いた回の記録した行: 人の確定があればそれ, なければ確定の行 (AI だけの回は null. 依頼 190)
function recordedRow() {
  if (!detail) return null;
  const h = detail.history.filter(r => HUMAN.includes(r.labeler)).pop();
  const l = detail.latest;
  return h || (l && l.labeler !== "ai" ? l : null);
}
function humanOc() { const h = detail ? detail.history.filter(r => HUMAN.includes(r.labeler)).pop() : null; return h ? h.outcome : null; }
// 選んだ判定があればそれ, なければ人の確定を塗る (依頼 192)
function markOC(oc = chosen || humanOc()) { document.querySelectorAll("[data-oc]").forEach(b => b.classList.toggle("on", b.dataset.oc === oc)); markConfirm(); }
function markConfirm() { $("#confirm").disabled = !chosen || !cur || loading || !detail; }
function markPP() {
  document.querySelectorAll("[data-pp]").forEach(b => b.classList.toggle("on", pp[b.dataset.pp] === b.dataset.v));
}
document.querySelectorAll("[data-pp]").forEach(b => b.onclick = () => {
  const k = b.dataset.pp, prev = pp[k]; pp[k] = prev === b.dataset.v ? null : b.dataset.v;
  // つかめなかった → 置くは自動でそこまで行かなかった (選び直せる). つかめなかったからつかめたに戻したら置くは選んでいない状態に (依頼 193)
  if (k === "pick" && pp.pick === "no") pp.place = "not_applicable";
  else if (k === "pick" && pp.pick === "yes" && prev === "no") pp.place = null;
  markPP(); b.blur();
});
document.querySelectorAll("[data-oc]").forEach(b => b.onclick = () => { b.blur(); choose(b.dataset.oc); });
$("#confirm").onclick = () => { $("#confirm").blur(); confirmChosen(); };

// y/n/u/x は選ぶだけ (書かない. 選び直せる). 書くのは確定のボタンか Enter (依頼 192)
function choose(oc) {
  if (!cur || busy || loading || !detail || detail.run_stem !== cur) return;
  chosen = oc; markOC();
}
function confirmChosen() { if (chosen) save(chosen); }

async function save(outcome) {
  if (!cur || busy || loading || !detail || detail.run_stem !== cur) return;
  busy = true; const stem = cur;
  markOC(outcome);  // 確定したら 0.4 秒見せてから次の回へ (その間も busy なので 2 回目は書かない. 依頼 189・192)
  const shown = new Promise(r => setTimeout(r, 400));
  const payload = {run_stem: stem, outcome, pick: pp.pick, place: pp.place, note: $("#note").value};
  const key = JSON.stringify(payload);
  const prev = pendingOps[stem];
  const opId = prev && prev.key === key ? prev.opId
             : stem + ":" + Date.now() + ":" + Math.random().toString(36).slice(2);
  pendingOps[stem] = {key, opId, payload};
  const seqAtSave = selSeq;
  let saved = false;
  const posBefore = view.findIndex(r => r.run_stem === stem);
  try {
    const res = await fetch("/api/verdict", {method: "POST", headers: {"Content-Type": "application/json"},
      body: JSON.stringify(Object.assign({op_id: opId}, payload))});
    const j = await res.json();
    if (!res.ok) { delete pendingOps[stem]; markOC(); status("書けませんでした: " + j.error, "err"); return; }
    saved = true;
    toast(`確定しました：${esc(stem)}${tag(outcome, false)}`);
    status(`${stem} を「${OC_JA[outcome]}」で追記しました (${LB_JA[j.row.labeler]}・${ppJa(j.row)})`, "ok");
    await loadRuns();
    // 同じ位置 (確定で一覧から消えたらそこに来た次の回) へ進む
    let next;
    const still = view.findIndex(r => r.run_stem === stem);
    if (still >= 0) next = view[still + 1] || view[still];
    else next = view[Math.min(posBefore, view.length - 1)];
    // 画面を進め終えてから消す (読み直しや次の回の読み込みに失敗して押し直しても同じ op_id. codex 3 回目 R1・4 回目 R2)
    await shown;
    if (selSeq !== seqAtSave) { delete pendingOps[stem]; return; }  // 保存中に人が別の回を選んでいたら動かさない (codex 6 回目 R2)
    if (await select(next ? next.run_stem : null)) delete pendingOps[stem];
  } catch (e) {
    markOC();
    if (saved) { status(`${stem} は書けています. 一覧の読み直しに失敗しました: ${e} ・ 押し直しても 2 回は書きません`, "err"); return; }
    // 書けたのに応答が届かなかったこともある. 同じ回・同じ判定で押し直すと同じ op_id で送るので,
    // サーバーは 2 回書かない (codex R7. 別の回を判定してから戻っても pendingOps に残る)
    status("書けたか確かめられませんでした: " + e + " ・ そのまま確定し直すと 2 回は書きません", "err");
  }
  finally { busy = false; }
}

function move(d) {
  const i = view.findIndex(r => r.run_stem === cur);
  const n = view[i < 0 ? 0 : Math.max(0, Math.min(view.length - 1, i + d))];
  if (n) { status(""); select(n.run_stem); }
}

document.addEventListener("keydown", e => {
  // Enter は確定. ひとこと欄に入力中でも効く (変換中の Enter は確定にしない. 依頼 192)
  if (e.key === "Enter" && e.target.tagName !== "SELECT") {
    if (e.isComposing || e.keyCode === 229 || e.metaKey || e.ctrlKey || e.altKey || e.shiftKey) return;
    e.preventDefault();
    if (!e.repeat) confirmChosen();  // 押しっぱなしで次の回まで書かない (codex R5)
    return;
  }
  if (e.target.tagName === "INPUT" && e.target.type !== "range") { if (e.key === "Escape") e.target.blur(); return; }
  if (e.metaKey || e.ctrlKey || e.altKey) return;
  if (e.repeat && "ynux".includes(e.key)) return;
  const k = e.key;
  if (k === "y") choose("success"); else if (k === "n") choose("failure");
  else if (k === "u") choose("unknown"); else if (k === "x") choose("not_judgeable");
  else if (k === "ArrowRight") { e.preventDefault(); move(1); } else if (k === "ArrowLeft") { e.preventDefault(); move(-1); }
  else if (k === ".") stepFrame(1); else if (k === ",") stepFrame(-1);
  else if (k === " " && $("#vid")) { e.preventDefault(); const v = $("#vid"); v.paused ? v.play() : v.pause(); }
});
$("#filter").onchange = () => { applyFilter(); if (!view.find(r => r.run_stem === cur)) select(view[0]?.run_stem); };
window.onresize = () => detail && renderChart();
loadRuns().then(() => select(view[0]?.run_stem)).catch(e => status("一覧を読めませんでした: " + e.message + " ・ KIOXIA をつないで読み直してください", "err"));
</script>
</body>
</html>
```


### test_verdicts.py

```python
#!/usr/bin/env python3
"""判定ファイルと判定の画面のテスト (依頼 183). KIOXIA にも API にも触らない (一時フォルダだけ).

  python3 pi05/verdict_viewer/test_verdicts.py
"""
import json
import os
import sys
import tempfile
import threading
import unittest
import urllib.error
import urllib.request
from pathlib import Path
from unittest import mock

HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE))
import verdicts as V  # noqa: E402
import seed_verdicts as S  # noqa: E402
import server  # noqa: E402


def row(stem, outcome, labeler, **kw):
    r = {"run_stem": stem, "pick": "unknown", "place": "unknown", "outcome": outcome, "labeler": labeler}
    r.update(kw)
    return r


def make_runs(root):
    """偽の記録: a = json に success, b = json の outcome null, c = frames と log.jsonl だけ, d = 何もない."""
    root = Path(root)
    for stem in ("pi05_20261001_000001", "pi05_20261001_000002", "pi05_20261001_000003", "pi05_20261001_000004"):
        (root / stem).mkdir(parents=True)
    a = root / "pi05_20261001_000001"
    (a / f"{a.name}.json").write_text(json.dumps({"outcome": "success", "ended_at": "2026-10-01T00:00:10",
        "judgments": {"pick": {"verdict": "yes"}, "place": {"verdict": "yes"}}}))
    b = root / "pi05_20261001_000002"
    (b / f"{b.name}.json").write_text(json.dumps({"outcome": None}))
    c = root / "pi05_20261001_000003"
    (c / "frames").mkdir()
    for i in range(3):
        (c / "frames" / f"{i:04d}.jpg").write_bytes(b"\xff\xd8\xff\xd9")
    (c / "frames" / "._0000.jpg").write_bytes(b"x")
    (c / "log.jsonl").write_text("\n".join(json.dumps({"chunk": str(i), "t": str(100 + i), "executed": "True",
        "state": json.dumps([i, 1, 2, 3, 4, -30, 0 if i < 2 else 1])}) for i in range(3)) + "\n")
    return root


class TestAppend(unittest.TestCase):
    def setUp(self):
        self.tmp = tempfile.TemporaryDirectory()
        self.csv = Path(self.tmp.name) / "v.csv"

    def tearDown(self):
        self.tmp.cleanup()

    def test_append_only_keeps_existing_bytes(self):
        V.append_rows([row("pi05_1", "success", "run_input"), row("pi05_2", "failure", "ai")], self.csv)
        before = self.csv.read_bytes()
        V.append_rows([row("pi05_1", "failure", "human_only")], self.csv)
        after = self.csv.read_bytes()
        self.assertTrue(after.startswith(before), "既存の行が変わった")
        self.assertEqual(after.count(b"labeled_at,"), 1, "見出しが 2 回書かれた")
        self.assertEqual(len(V.read_rows(self.csv)), 3)

    def test_header_columns(self):
        V.append_rows([row("pi05_1", "success", "ai")], self.csv)
        self.assertEqual(self.csv.read_text().splitlines()[0].split(","), V.COLUMNS)

    def test_latest_row_wins(self):
        V.append_rows([row("pi05_1", "success", "ai"), row("pi05_2", "failure", "ai")], self.csv)
        V.append_rows([row("pi05_1", "failure", "human_fixed_ai")], self.csv)
        V.append_rows([row("pi05_1", "unknown", "human_only")], self.csv)
        lat = V.latest_by_stem(V.read_rows(self.csv))
        self.assertEqual(lat["pi05_1"]["outcome"], "unknown")
        self.assertEqual(lat["pi05_2"]["outcome"], "failure")
        self.assertEqual(V.latest_by_stem(V.read_rows(self.csv), labelers=("ai",))["pi05_1"]["outcome"], "success")

    def test_bad_values_write_nothing(self):
        V.append_rows([row("pi05_1", "success", "ai")], self.csv)
        before = self.csv.read_bytes()
        for bad in (row("pi05_1", "great", "ai"), row("pi05_1", "success", "robot"),
                    row("", "success", "ai"), row("pi05_1", "success", "ai", pick="maybe")):
            with self.assertRaises(ValueError):
                V.append_rows([row("pi05_9", "success", "ai"), bad], self.csv)
        self.assertEqual(self.csv.read_bytes(), before, "まちがった行のときに途中まで書いた")

    def test_place_not_applicable_only_for_place(self):
        # 依頼 193: place は not_applicable (そこまで行かなかった) を書ける. pick には書けない
        V.append_rows([row("pi05_1", "failure", "human_only", pick="no", place="not_applicable")], self.csv)
        self.assertEqual(V.read_rows(self.csv)[-1]["place"], "not_applicable")
        before = self.csv.read_bytes()
        with self.assertRaises(ValueError):
            V.append_rows([row("pi05_2", "failure", "human_only", pick="not_applicable", place="not_applicable")], self.csv)
        self.assertEqual(self.csv.read_bytes(), before)

    def test_comma_and_newline_in_reason(self):
        V.append_rows([row("pi05_1", "failure", "ai", ai_reason='箱の外, "落とした"\n2 行目')], self.csv)
        self.assertEqual(V.read_rows(self.csv)[0]["ai_reason"], '箱の外, "落とした"\n2 行目')

    def test_broken_file_stops(self):
        V.append_rows([row("pi05_1", "success", "ai")], self.csv)
        with open(self.csv, "ab") as f:
            f.write(b"2026,pi05_2,yes")  # 書きかけ (改行なし)
        before = self.csv.read_bytes()
        with self.assertRaises(V.BrokenCsv):
            V.append_rows([row("pi05_3", "success", "ai")], self.csv)
        self.assertEqual(self.csv.read_bytes(), before)
        other = Path(self.tmp.name) / "other.csv"
        other.write_text("a,b\n1,2\n")
        with self.assertRaises(V.BrokenCsv):
            V.append_rows([row("pi05_3", "success", "ai")], other)
        self.assertEqual(other.read_text(), "a,b\n1,2\n")

    def test_unclosed_quote_stops(self):
        V.append_rows([row("pi05_1", "success", "ai")], self.csv)
        with open(self.csv, "ab") as f:
            f.write(b'2026,pi05_2,yes,yes,success,ai,,,,"unfinished\n')
        before = self.csv.read_bytes()
        with self.assertRaises(V.BrokenCsv):
            V.append_rows([row("pi05_3", "success", "ai")], self.csv)
        self.assertEqual(self.csv.read_bytes(), before)

    def test_long_note_is_cut(self):
        V.append_rows([row("pi05_1", "success", "human_only", note="あ" * 200000, ai_reason="い" * 200000)], self.csv)
        r = V.read_rows(self.csv)[0]
        self.assertEqual(len(r["note"]), V.MAX_NOTE + 1)
        self.assertEqual(len(r["ai_reason"]), V.MAX_REASON + 1)
        V.append_rows([row("pi05_2", "success", "ai")], self.csv)

    def test_forbid_dirs(self):
        d = Path(self.tmp.name) / "myruns"
        d.mkdir()
        with self.assertRaises(V.BrokenCsv):
            V.append_rows([row("pi05_1", "success", "ai")], d / "v.csv", forbid_dirs=(d,))
        self.assertFalse((d / "v.csv").exists())

    def test_refuses_symlink_and_record_dirs(self):
        real = Path(self.tmp.name) / "real.csv"
        V.append_rows([row("pi05_1", "success", "ai")], real)
        link = Path(self.tmp.name) / "link.csv"
        link.symlink_to(real)
        with self.assertRaises(V.BrokenCsv):
            V.append_rows([row("pi05_2", "success", "ai")], link)
        runs = Path(self.tmp.name) / "runs"
        (runs / "pi05_1").mkdir(parents=True)
        with mock.patch.object(V, "RUNS_DIR", runs):
            with self.assertRaises(V.BrokenCsv):
                V.append_rows([row("pi05_2", "success", "ai")], runs / "pi05_1" / "x.csv")
        with self.assertRaises(V.BrokenCsv):
            V.append_rows([row("pi05_2", "success", "ai")], Path(self.tmp.name) / "x.json")
        self.assertEqual(len(V.read_rows(real)), 1)

    def test_skip_if_labeled_by(self):
        V.append_rows([row("pi05_1", "failure", "human_only")], self.csv)
        out = V.append_rows([row("pi05_1", "success", "ai"), row("pi05_2", "success", "ai")], self.csv,
                            skip_if_labeled_by=V.HUMAN_LABELERS)
        self.assertEqual([r["run_stem"] for r in out], ["pi05_2"])
        self.assertEqual(V.latest_by_stem(V.read_rows(self.csv))["pi05_1"]["labeler"], "human_only")


class TestMount(unittest.TestCase):
    def test_not_mounted_stops_and_writes_nothing(self):
        target = V.KIOXIA_MOUNT / "r2r2r-data" / "runs" / "pi05_policy_verdicts_v1_TEST_never.csv"
        with mock.patch.object(V.os.path, "ismount", lambda p: False), \
                mock.patch("builtins.open", side_effect=AssertionError("open してはいけない")):
            with self.assertRaises(V.NotMounted):
                V.append_rows([row("pi05_1", "success", "ai")], target)

    def test_mounted_check_only_for_kioxia(self):
        with mock.patch.object(V.os.path, "ismount", lambda p: False):
            V.ensure_ssd_mounted("/tmp/whatever.csv")  # KIOXIA の外は確かめない (テスト用)

    def test_seed_aborts_without_mount(self):
        with mock.patch.object(V.os.path, "ismount", lambda p: False), \
                mock.patch.object(sys, "argv", ["seed", "--run-input"]):
            self.assertEqual(S.main(), 2)

    def test_server_returns_503_without_mount(self):
        with tempfile.TemporaryDirectory() as d:
            runs = make_runs(Path(d) / "runs")
            app = server.App(runs, V.KIOXIA_MOUNT / "r2r2r-data" / "runs" / "never_TEST.csv")
            with mock.patch.object(V.os.path, "ismount", lambda p: False):
                with self.assertRaises(V.NotMounted):
                    app.add_verdict({"run_stem": "pi05_20261001_000003", "outcome": "success"})


class TestLabeler(unittest.TestCase):
    def test_labeler(self):
        self.assertEqual(V.human_labeler_for("success", None), "human_only")
        self.assertEqual(V.human_labeler_for("success", {"outcome": "success"}), "human")
        self.assertEqual(V.human_labeler_for("failure", {"outcome": "success"}), "human_fixed_ai")


class TestSeed(unittest.TestCase):
    def setUp(self):
        self.tmp = tempfile.TemporaryDirectory()
        self.runs = make_runs(Path(self.tmp.name) / "runs")
        self.csv = Path(self.tmp.name) / "v.csv"

    def tearDown(self):
        self.tmp.cleanup()

    def test_run_input_copy_once(self):
        c = S.do_run_input(self.csv, self.runs, dry_run=False)
        self.assertEqual(c["success"], 1)
        rows = V.read_rows(self.csv)
        self.assertEqual([(r["run_stem"], r["outcome"], r["labeler"], r["pick"]) for r in rows],
                         [("pi05_20261001_000001", "success", "run_input", "yes")])
        S.do_run_input(self.csv, self.runs, dry_run=False)
        self.assertEqual(len(V.read_rows(self.csv)), 1, "2 回流したら行が増えた")

    def test_ai_targets_and_not_judgeable(self):
        calls = []

        def fake_api(key, imgs, evidence):
            calls.append((len(imgs), evidence))
            return {"pick": "yes", "place": "no", "outcome": "failure", "reason": "箱の外"}, ""
        S.do_run_input(self.csv, self.runs, dry_run=False)
        with mock.patch.object(S, "api_key", lambda: "k"), mock.patch.object(S, "call_api", fake_api):
            c = S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only=None)
        self.assertEqual(calls, [(3, "frames")])  # c だけ API を呼ぶ (frames 3 枚・._ は除く)
        self.assertEqual(c["failure"], 1)
        self.assertEqual(c["not_judgeable"], 2)  # b (null・素材なし) と d (何もない)
        ai = V.latest_by_stem(V.read_rows(self.csv), labelers=("ai",))
        self.assertNotIn("pi05_20261001_000001", ai)
        self.assertEqual(ai["pi05_20261001_000003"]["ai_reason"], "[送ったチャンク 3] 箱の外")
        n = len(V.read_rows(self.csv))
        with mock.patch.object(S, "api_key", lambda: "k"), mock.patch.object(S, "call_api", fake_api):
            S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only=None)
        self.assertEqual(len(V.read_rows(self.csv)), n, "AI の行が 2 回書かれた")

    def test_ai_skips_when_api_unavailable(self):
        def boom(*a):
            raise S.ApiUnavailable("http_401")
        with mock.patch.object(S, "api_key", lambda: "k"), mock.patch.object(S, "call_api", boom):
            c = S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only=None)
        self.assertEqual(c["skipped"], 1)
        self.assertNotIn("pi05_20261001_000003", V.latest_by_stem(V.read_rows(self.csv)))

    def test_seed_never_adds_after_human(self):
        V.append_rows([row("pi05_20261001_000003", "success", "human_only"),
                       row("pi05_20261001_000001", "failure", "human_only")], self.csv)
        with mock.patch.object(S, "api_key", lambda: "k"), \
                mock.patch.object(S, "call_api", lambda *a: ({"outcome": "failure"}, "")):
            S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only=None)
        S.do_run_input(self.csv, self.runs, dry_run=False)
        lat = V.latest_by_stem(V.read_rows(self.csv))
        self.assertEqual(lat["pi05_20261001_000003"]["labeler"], "human_only")
        self.assertEqual(lat["pi05_20261001_000001"]["labeler"], "human_only")

    def test_seed_rechecks_inside_lock(self):
        # API を待つ間に人が確定した → AI の行は足さない
        def api_then_human(*a):
            V.append_rows([row("pi05_20261001_000003", "failure", "human_only")], self.csv)
            return {"outcome": "success"}, ""
        with mock.patch.object(S, "api_key", lambda: "k"), mock.patch.object(S, "call_api", api_then_human):
            c = S.do_ai(self.csv, self.runs, dry_run=False, limit=0, only={"pi05_20261001_000003"})
        self.assertEqual(c["skipped_human"], 1)
        self.assertEqual(V.latest_by_stem(V.read_rows(self.csv))["pi05_20261001_000003"]["labeler"], "human_only")

    def test_symlinked_side_files_are_ignored(self):
        outside = Path(self.tmp.name) / "outside.jsonl"
        outside.write_text(json.dumps({"chunk": "0", "executed": "True"}) + "\n")
        rd = self.runs / "pi05_20261001_000004"
        (rd / "log.jsonl").symlink_to(outside)
        (rd / f"{rd.name}.json").symlink_to(outside)
        self.assertEqual(V.read_log(rd), [])
        self.assertIsNone(V.read_run_json(rd))

    def test_server_refuses_csv_inside_runs_dir(self):
        app = server.App(self.runs, self.runs / "pi05_20261001_000003" / "v.csv")
        with self.assertRaises(V.BrokenCsv):
            app.add_verdict({"run_stem": "pi05_20261001_000003", "outcome": "success"})
        self.assertFalse((self.runs / "pi05_20261001_000003" / "v.csv").exists())

    def test_symlinked_run_and_frames_are_ignored(self):
        outside = Path(self.tmp.name) / "outside"
        (outside / "frames").mkdir(parents=True)
        (outside / "frames" / "0000.jpg").write_bytes(b"secret")
        (self.runs / "pi05_20261001_000099").symlink_to(outside)
        (self.runs / "pi05_20261001_000003" / "frames" / "0009.jpg").symlink_to(outside / "frames" / "0000.jpg")
        self.assertNotIn("pi05_20261001_000099", V.list_run_stems(self.runs))
        self.assertNotIn("0009.jpg", V.frame_files(self.runs / "pi05_20261001_000003"))

    def test_api_key_export_line(self):
        with tempfile.TemporaryDirectory() as d:
            p = Path(d) / ".anthropic_key"
            p.write_text("export ANTHROPIC_API_KEY='sk-test'\n")
            with mock.patch.dict(os.environ, {"HOME": d}, clear=False), \
                    mock.patch.dict(os.environ, {}, clear=False) as env:
                env.pop("ANTHROPIC_API_KEY", None)
                self.assertEqual(S.api_key(), "sk-test")


class TestServer(unittest.TestCase):
    def setUp(self):
        self.tmp = tempfile.TemporaryDirectory()
        self.runs = make_runs(Path(self.tmp.name) / "runs")
        self.csv = Path(self.tmp.name) / "v.csv"
        V.append_rows([row("pi05_20261001_000003", "success", "ai", ai_reason="入っている", evidence="frames")], self.csv)
        self.app = server.App(self.runs, self.csv)
        self.srv = server.ThreadingHTTPServer(("127.0.0.1", 0), server.make_handler(self.app))
        threading.Thread(target=self.srv.serve_forever, daemon=True).start()
        self.base = f"http://127.0.0.1:{self.srv.server_address[1]}"

    def tearDown(self):
        self.srv.shutdown()
        self.srv.server_close()
        self.tmp.cleanup()

    def get(self, path):
        with urllib.request.urlopen(self.base + path) as r:
            return json.loads(r.read())

    def post(self, body):
        req = urllib.request.Request(self.base + "/api/verdict", data=json.dumps(body).encode(),
                                     headers={"Content-Type": "application/json"}, method="POST")
        try:
            with urllib.request.urlopen(req) as r:
                return r.status, json.loads(r.read())
        except urllib.error.HTTPError as e:
            return e.code, json.loads(e.read())

    def test_list_and_detail(self):
        runs = {r["run_stem"]: r for r in self.get("/api/runs")["runs"]}
        self.assertEqual(len(runs), 4)
        self.assertEqual(runs["pi05_20261001_000003"]["ai_outcome"], "success")
        self.assertFalse(runs["pi05_20261001_000003"]["confirmed"])
        d = self.get("/api/run/pi05_20261001_000003")
        self.assertEqual(d["frames"], ["0000.jpg", "0001.jpg", "0002.jpg"])
        self.assertEqual(len(d["states"]["joints"]), 3)
        self.assertEqual(d["states"]["grip"][-1][1], 1.0)
        self.assertEqual(d["executed_chunks"], 3)

    def test_post_appends_and_labeler(self):
        before = self.csv.read_bytes()
        st, j = self.post({"run_stem": "pi05_20261001_000003", "outcome": "failure", "place": "no", "note": "箱の縁"})
        self.assertEqual(st, 200)
        self.assertTrue(self.csv.read_bytes().startswith(before))
        last = V.read_rows(self.csv)[-1]
        self.assertEqual((last["labeler"], last["outcome"], last["pick"], last["place"], last["ai_outcome"], last["ai_reason"],
                          last["evidence"], last["note"]),
                         ("human_fixed_ai", "failure", "unknown", "no", "success", "入っている", "frames", "箱の縁"))
        st, j = self.post({"run_stem": "pi05_20261001_000003", "outcome": "success"})
        self.assertEqual((j["row"]["labeler"], j["row"]["pick"], j["row"]["place"]), ("human", "yes", "yes"))
        st, j = self.post({"run_stem": "pi05_20261001_000004", "outcome": "not_judgeable"})
        self.assertEqual(j["row"]["labeler"], "human_only")
        runs = {r["run_stem"]: r for r in self.get("/api/runs")["runs"]}
        self.assertTrue(runs["pi05_20261001_000003"]["confirmed"])
        self.assertEqual(runs["pi05_20261001_000003"]["outcome"], "success")

    def test_post_place_not_applicable(self):
        # 依頼 193: 画面から place=not_applicable を送れる. pick=not_applicable は 400 で書かない
        st, j = self.post({"run_stem": "pi05_20261001_000003", "outcome": "failure", "pick": "no", "place": "not_applicable"})
        self.assertEqual(st, 200)
        self.assertEqual((j["row"]["pick"], j["row"]["place"]), ("no", "not_applicable"))
        before = self.csv.read_bytes()
        st, j = self.post({"run_stem": "pi05_20261001_000003", "outcome": "failure", "pick": "not_applicable"})
        self.assertEqual(st, 400)
        self.assertEqual(self.csv.read_bytes(), before)

    def test_same_op_id_writes_once(self):
        n = len(V.read_rows(self.csv))
        b = {"op_id": "abc", "run_stem": "pi05_20261001_000003", "outcome": "failure"}
        self.assertEqual(self.post(b)[0], 200)
        self.assertEqual(self.post(b)[0], 200)
        self.assertEqual(len(V.read_rows(self.csv)), n + 1)

    def test_media_link_to_other_run_is_refused(self):
        other = self.runs / "pi05_20261001_000004" / "frames"
        other.mkdir()
        (other / "0000.jpg").write_bytes(b"other")
        (self.runs / "pi05_20261001_000003" / "frames" / "0008.jpg").symlink_to(other / "0000.jpg")
        with self.assertRaises(urllib.error.HTTPError) as cm:
            urllib.request.urlopen(self.base + "/media/pi05_20261001_000003/frames/0008.jpg")
        self.assertEqual(cm.exception.code, 404)

    def test_post_rejects_bad(self):
        n = len(V.read_rows(self.csv))
        self.assertEqual(self.post({"run_stem": "pi05_20261001_000003", "outcome": "great"})[0], 400)
        self.assertEqual(self.post({"run_stem": "../etc", "outcome": "success"})[0], 400)
        self.assertEqual(self.post({"run_stem": "pi05_20990101_000000", "outcome": "success"})[0], 400)
        self.assertEqual(len(V.read_rows(self.csv)), n)

    def test_media_and_traversal(self):
        with urllib.request.urlopen(self.base + "/media/pi05_20261001_000003/frames/0001.jpg") as r:
            self.assertEqual(r.read(), b"\xff\xd8\xff\xd9")
        for p in ("/media/pi05_20261001_000003/frames/..%2Flog.jsonl", "/media/..%2F..%2Fetc/top.mp4"):
            with self.assertRaises(urllib.error.HTTPError) as cm:
                urllib.request.urlopen(self.base + p)
            self.assertEqual(cm.exception.code, 404)


class TestConfirm192(unittest.TestCase):
    """依頼 192: y/n/u/x は選ぶだけ・確定 (ボタンか Enter) で 1 行だけ書く. 画面を Chrome で動かす (playwright がなければ飛ばす)."""
    @classmethod
    def setUpClass(cls):
        try:
            from playwright.sync_api import sync_playwright
            cls.pw = sync_playwright().start()
            cls.browser = cls.pw.chromium.launch(channel="chrome")
        except Exception as e:  # noqa: BLE001
            raise unittest.SkipTest(f"playwright / Chrome がない: {e}")

    @classmethod
    def tearDownClass(cls):
        cls.browser.close()
        cls.pw.stop()

    def setUp(self):
        self.tmp = tempfile.TemporaryDirectory()
        self.runs = make_runs(Path(self.tmp.name) / "runs")
        self.csv = Path(self.tmp.name) / "v.csv"
        V.append_rows([row("pi05_20261001_000003", "success", "ai", ai_reason="入っている", evidence="frames")], self.csv)
        self.srv = server.ThreadingHTTPServer(("127.0.0.1", 0), server.make_handler(server.App(self.runs, self.csv)))
        threading.Thread(target=self.srv.serve_forever, daemon=True).start()
        self.pg = self.browser.new_page()
        self.pg.goto(f"http://127.0.0.1:{self.srv.server_address[1]}/")
        self.wait_loaded()

    def tearDown(self):
        self.pg.close()
        self.srv.shutdown()
        self.srv.server_close()
        self.tmp.cleanup()

    def wait_loaded(self):
        self.pg.wait_for_function("() => { const t = document.querySelector('#title').textContent;"
                                  " return t.startsWith('pi05_') && !t.includes('読み込み中'); }")

    def n_rows(self):
        return len(V.read_rows(self.csv))

    def on_keys(self):
        return self.pg.eval_on_selector_all("button.key.on", "e => e.map(x => x.dataset.oc)")

    def disabled(self):
        return self.pg.eval_on_selector("#confirm", "e => e.disabled")

    def test_choose_only_does_not_write(self):
        n = self.n_rows()
        self.assertTrue(self.disabled())
        self.pg.keyboard.press("n")
        self.assertEqual(self.on_keys(), ["failure"])
        self.assertFalse(self.disabled())
        self.pg.click('button.key[data-oc="success"]')  # 選び直し
        self.assertEqual(self.on_keys(), ["success"])
        self.pg.wait_for_timeout(600)
        self.assertEqual(self.n_rows(), n)

    def test_confirm_before_choose_does_nothing(self):
        n = self.n_rows()
        title = self.pg.text_content("#title")
        self.pg.keyboard.press("Enter")
        self.pg.click("#confirm", force=True)
        self.pg.wait_for_timeout(600)
        self.assertEqual(self.n_rows(), n)
        self.assertEqual(self.pg.text_content("#title"), title)

    def test_enter_writes_one_row(self):
        n = self.n_rows()
        stem = self.pg.text_content("#title")
        self.pg.keyboard.press("n")
        self.pg.keyboard.press("Enter")
        self.pg.keyboard.press("Enter")  # 0.4 秒の間の 2 回目は書かない
        self.pg.wait_for_function("() => document.querySelector('#toast').textContent.includes('確定しました')")
        self.assertIn(stem, self.pg.text_content("#toast"))
        self.pg.wait_for_timeout(800)
        rows = V.read_rows(self.csv)
        self.assertEqual(len(rows), n + 1)
        self.assertEqual((rows[-1]["run_stem"], rows[-1]["outcome"]), (stem, "failure"))

    def test_button_writes_one_row(self):
        n = self.n_rows()
        stem = self.pg.text_content("#title")
        self.pg.keyboard.press("y")
        self.pg.click("#confirm")
        self.pg.click("#confirm", force=True)
        self.pg.wait_for_timeout(1000)
        rows = V.read_rows(self.csv)
        self.assertEqual(len(rows), n + 1)
        self.assertEqual((rows[-1]["run_stem"], rows[-1]["outcome"]), (stem, "success"))

    def test_enter_in_note_confirms_but_keys_do_not_choose(self):
        n = self.n_rows()
        self.pg.keyboard.press("u")
        self.pg.click("#note")
        self.pg.keyboard.type("yn")
        self.assertEqual(self.on_keys(), ["unknown"])
        self.pg.keyboard.press("Enter")
        self.pg.wait_for_timeout(1000)
        rows = V.read_rows(self.csv)
        self.assertEqual(len(rows), n + 1)
        self.assertEqual((rows[-1]["outcome"], rows[-1]["note"]), ("unknown", "yn"))

    def test_moving_discards_choice(self):
        n = self.n_rows()
        stem = self.pg.text_content("#title")
        self.pg.keyboard.press("n")
        self.pg.keyboard.press("ArrowRight")
        self.wait_loaded()
        self.assertNotEqual(self.pg.text_content("#title"), stem)
        self.assertEqual(self.on_keys(), [])
        self.assertTrue(self.disabled())
        self.pg.keyboard.press("ArrowLeft")
        self.wait_loaded()
        self.assertEqual(self.pg.text_content("#title"), stem)
        self.assertEqual(self.on_keys(), [])
        self.pg.keyboard.press("Enter")
        self.pg.wait_for_timeout(600)
        self.assertEqual(self.n_rows(), n)

    # ---- 依頼 193: つかむ / 置くを日本語に・つかめなかったで置くは自動でそこまで行かなかった ----
    def pp_on(self):
        return self.pg.eval_on_selector_all("[data-pp].on", "e => e.map(x => x.dataset.pp + '=' + x.dataset.v)")

    def test_pp_labels_are_japanese(self):
        got = self.pg.eval_on_selector_all("[data-pp]", "e => e.map(x => x.dataset.pp + '=' + x.dataset.v + ':' + x.textContent)")
        self.assertEqual(got, ["pick=yes:つかめた", "pick=no:つかめなかった", "pick=unknown:分からない",
                               "place=yes:置けた", "place=no:置けなかった", "place=not_applicable:そこまで行かなかった",
                               "place=unknown:分からない"])
        self.assertEqual(self.pg.eval_on_selector_all("#panel .row .lbl", "e => e.map(x => x.textContent)"), ["pick", "place"])

    def test_pick_no_selects_place_not_applicable(self):
        n = self.n_rows()
        self.pg.click('[data-pp="pick"][data-v="no"]')
        self.assertEqual(self.pp_on(), ["pick=no", "place=not_applicable"])
        self.pg.click('[data-pp="place"][data-v="unknown"]')  # 選び直せる
        self.assertEqual(self.pp_on(), ["pick=no", "place=unknown"])
        self.pg.click('[data-pp="pick"][data-v="yes"]')  # つかめたに戻すと置くは選んでいない
        self.assertEqual(self.pp_on(), ["pick=yes"])
        self.pg.click('[data-pp="pick"][data-v="no"]')
        self.pg.wait_for_timeout(300)
        self.assertEqual(self.n_rows(), n)  # 選ぶだけでは書かない
        stem = self.pg.text_content("#title")
        self.pg.keyboard.press("n")
        self.pg.keyboard.press("Enter")
        self.pg.wait_for_timeout(1000)
        rows = V.read_rows(self.csv)
        self.assertEqual(len(rows), n + 1)
        self.assertEqual((rows[-1]["run_stem"], rows[-1]["pick"], rows[-1]["place"]), (stem, "no", "not_applicable"))


class TestRule185(unittest.TestCase):
    """エイイチの決め (2026-11-14 依頼 185): run_input も確定・送ったチャンク 0 → not_applicable・素材不足 → not_judgeable."""
    def setUp(self):
        self.tmp = tempfile.TemporaryDirectory()
        self.runs = Path(self.tmp.name) / "runs"
        self.csv = Path(self.tmp.name) / "v.csv"
        # stem: (送ったチャンク, 先に入れる行)
        self.case = {
            "pi05_20261002_000001": (0, [row("pi05_20261002_000001", "not_judgeable", "ai", evidence="frames")]),  # 2 と 3 → 2
            "pi05_20261002_000002": (2, [row("pi05_20261002_000002", "not_judgeable", "ai", evidence="frames")]),  # 3
            "pi05_20261002_000003": (2, [row("pi05_20261002_000003", "not_judgeable", "ai", evidence="")]),        # 3 (素材なし)
            "pi05_20261002_000004": (0, [row("pi05_20261002_000004", "failure", "ai", evidence="top.mp4")]),       # 2
            "pi05_20261002_000005": (0, [row("pi05_20261002_000005", "not_judgeable", "ai", evidence="frames"),
                                         row("pi05_20261002_000005", "failure", "human_fixed_ai")]),             # 人の行 → 足さない
            "pi05_20261002_000006": (2, [row("pi05_20261002_000006", "not_judgeable", "ai", evidence=""),
                                         row("pi05_20261002_000006", "success", "human_only")]),                 # 人の行 → 足さない
            "pi05_20261002_000007": (0, [row("pi05_20261002_000007", "success", "run_input")]),                  # run_input → 足さない
            "pi05_20261002_000008": (2, [row("pi05_20261002_000008", "not_judgeable", "ai", evidence="top.mp4")]),  # 当たらない
            "pi05_20261002_000009": (3, [row("pi05_20261002_000009", "failure", "ai", evidence="frames")]),       # 当たらない
        }
        rows = []
        for stem, (n, rs) in self.case.items():
            d = self.runs / stem
            d.mkdir(parents=True)
            lines = [{"type": "model"}] + [{"chunk": str(i), "executed": "True"} for i in range(n)] + [{"chunk": "9", "executed": "False"}]
            (d / "log.jsonl").write_text("\n".join(json.dumps(x) for x in lines) + "\n")
            rows += rs
        V.append_rows(rows, self.csv)

    def tearDown(self):
        self.tmp.cleanup()

    def rule_rows(self):
        return {r["run_stem"]: r for r in V.read_rows(self.csv) if r["labeler"] == "rule"}

    def test_rule_rows(self):
        c = S.do_rule(self.csv, self.runs, dry_run=False)
        got = {k[-1]: v["outcome"] for k, v in self.rule_rows().items()}
        self.assertEqual(got, {"1": "not_applicable", "2": "not_judgeable", "3": "not_judgeable", "4": "not_applicable"})
        self.assertEqual((c["rule2"], c["rule3"], c["both"]), (2, 2, 1))
        for r in self.rule_rows().values():
            self.assertIn("エイイチの決め 2026-11-14 依頼185", r["note"])
        self.assertIn("決め2", self.rule_rows()["pi05_20261002_000001"]["note"])
        self.assertIn("決め3", self.rule_rows()["pi05_20261002_000002"]["note"])

    def test_rule_never_after_human_or_run_input(self):
        S.do_rule(self.csv, self.runs, dry_run=False)
        for stem in ("pi05_20261002_000005", "pi05_20261002_000006", "pi05_20261002_000007"):
            self.assertNotIn(stem, self.rule_rows())

    def test_rule_twice_adds_nothing(self):
        S.do_rule(self.csv, self.runs, dry_run=False)
        before = self.csv.read_bytes()
        S.do_rule(self.csv, self.runs, dry_run=False)
        self.assertEqual(self.csv.read_bytes(), before)

    def test_rule_rechecks_inside_lock(self):
        # 一覧を読んだあとに人の行が足されたら, rule の行は足さない
        real = V.read_rows
        def late_human(p):
            rows = real(p)
            V.append_rows([row("pi05_20261002_000002", "failure", "human")], self.csv)
            return rows
        with mock.patch.object(V, "read_rows", side_effect=late_human):
            S.do_rule(self.csv, self.runs, dry_run=False)
        self.assertNotIn("pi05_20261002_000002", self.rule_rows())

    def test_confirmed_and_success_rate(self):
        S.do_rule(self.csv, self.runs, dry_run=False)
        app = server.App(self.runs, self.csv)
        conf = {r["run_stem"][-1]: r["confirmed"] for r in app.runs_summary()}
        self.assertEqual(conf, {"1": True, "2": True, "3": True, "4": True, "5": True, "6": True, "7": True,
                                "8": False, "9": False})
        st = app.stats()
        # 確定: success 2 (6・7) / failure 1 (5). not_applicable 2・not_judgeable 2 は分母に入れない. AI の行も入れない
        self.assertEqual((st["success"], st["failure"], st["denominator"], st["confirmed"]), (2, 1, 3, 7))
        self.assertAlmostEqual(st["rate"], 2 / 3)
        self.assertEqual(st["by_outcome"]["not_applicable"], 2)

    def test_success_rate_denominator(self):
        rows = [row("a", "success", "human"), row("b", "failure", "run_input"), row("c", "unknown", "human"),
                row("d", "not_judgeable", "rule"), row("e", "not_applicable", "rule"), row("f", "success", "ai"),
                row("b", "success", "human_fixed_ai")]  # b は後ろの人の行が正
        st = V.success_rate(rows)
        self.assertEqual((st["success"], st["failure"], st["denominator"]), (2, 0, 2))
        self.assertEqual(st["rate"], 1.0)
        self.assertIsNone(V.success_rate([row("x", "not_applicable", "rule")])["rate"])

    def test_ai_after_confirmed_does_not_unconfirm(self):
        rows = [row("a", "not_applicable", "rule"), row("a", "failure", "ai")]
        self.assertEqual(V.current_by_stem(rows)["a"]["labeler"], "rule")

    def test_ai_cannot_write_not_applicable(self):
        r = S.ai_row("pi05_x", {"outcome": "not_applicable", "pick": "no", "place": "no"}, "frames", 0)
        self.assertEqual(r["outcome"], "unknown")


if __name__ == "__main__":
    unittest.main(verbosity=1)
```


### 判定の画面を開く.command

```bash
#!/bin/zsh
# 判定の画面 (依頼 183) を立ち上げてブラウザで開く. ダブルクリックで動く.
# すでに 8765 番で動いていれば立ち上げ直さずに開くだけ.
PORT=8765
URL="http://localhost:${PORT}/"
LOG="$HOME/r2r2r-scripts/logs/verdict_viewer_server.log"

if lsof -i :${PORT} >/dev/null 2>&1; then
  echo "[VIEWER] すでに ${PORT} 番で動いています"
else
  echo "[VIEWER] 立ち上げます (ログ: ${LOG})"
  cd "$HOME"
  if command -v setsid >/dev/null 2>&1; then
    nohup setsid python3 "$HOME/r2r2r-scripts/pi05/verdict_viewer/server.py" --no-open > "$LOG" 2>&1 &
  else
    nohup python3 "$HOME/r2r2r-scripts/pi05/verdict_viewer/server.py" --no-open > "$LOG" 2>&1 &
    disown
  fi
  # 応答が返るまで最大 10 秒待つ
  for i in {1..20}; do
    code=$(curl -s -o /dev/null -w '%{http_code}' "$URL")
    [ "$code" = 200 ] && break
    sleep 0.5
  done
  if [ "$code" != 200 ]; then
    echo "[VIEWER] 立ち上がりませんでした. ログを見てください: ${LOG}"
    tail -n 20 "$LOG"
    exit 1
  fi
fi

open "$URL"
```


### test_state_source.py

```python
#!/usr/bin/env python3
"""test_state_source.py — 1 コマごとの state の出どころ (state_source. 依頼 196) の確かめ.

  python3 pi05/test_state_source.py -v

前半はファイルを読まない部分だけ. 後半 (TestSameAsBefore) は KIOXIA の runs/pi05_policy を読み,
直す前のコード (git の HEAD) と今のコードで /tmp に作り, state / actions / t がバイト単位で同じことを見る
(KIOXIA がなければ飛ばす. データセットにもアームにも触らない).
"""
import importlib.util
import json
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
from types import SimpleNamespace

import numpy as np

_HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(_HERE))

import build_correction_episodes as bce  # noqa: E402


def samples(still=False):
    """0〜1 秒は 0.1 秒おき → 1.0〜2.6 秒は抜け (j1 が 6° 動く. still なら動かない) → 2.6〜3.6 秒は 0.1 秒おき."""
    a = np.round(np.arange(0.0, 1.01, 0.1), 3)
    b = np.round(np.arange(2.6, 3.61, 0.1), 3)
    at = np.concatenate([a, b])
    aq = np.zeros((len(at), 6))
    if not still:
        aq[len(a):, 1] = 6.0
    return at, aq


def runs_of_nonzero(src):
    nz = np.r_[0, (np.asarray(src) != 0).astype(int)]
    return int((np.diff(nz) == 1).sum())


class TestFlags(unittest.TestCase):
    def test_motion_gap_is_1(self):
        at, aq = samples()
        t = np.arange(0.0, 3.6, 0.1)
        src = bce.gap_fill_flags(t, at, aq)
        self.assertEqual(src.dtype, np.int8)
        inside = (t > 1.0) & (t < 2.6)
        self.assertTrue(np.all(src[inside] == bce.SRC_FILLED_MOVE))
        self.assertTrue(np.all(src[~inside] == bce.SRC_MEASURED))

    def test_still_gap_is_2(self):
        at, aq = samples(still=True)
        t = np.arange(0.0, 3.6, 0.1)
        src = bce.gap_fill_flags(t, at, aq)
        self.assertEqual(set(np.unique(src)), {bce.SRC_MEASURED, bce.SRC_FILLED_STILL})

    def test_flags_mark_exactly_what_speed20_changes(self):
        """speed20 が線形補間から変えたコマは, すべて印が 0 でないコマ."""
        at, aq = samples()
        t = np.arange(0.0, 3.6, 0.1)
        q_lin, _ = bce.fill_motion_gaps(t, at, aq, mode="linear")
        q_sp, _ = bce.fill_motion_gaps(t, at, aq, mode="speed20")
        src = bce.gap_fill_flags(t, at, aq)
        changed = np.any(np.abs(q_lin - q_sp) > 1e-9, axis=1)
        self.assertTrue(changed.any())
        self.assertTrue(np.all(src[changed] != bce.SRC_MEASURED))

    def test_no_gap_no_flag(self):
        at = np.round(np.arange(0.0, 3.01, 0.1), 3)
        aq = np.cumsum(np.ones((len(at), 6)), axis=0)
        self.assertEqual(int(bce.gap_fill_flags(np.arange(0.0, 3.0, 0.1), at, aq).sum()), 0)

    def test_compat_ignores_state_source(self):
        """お手本にない state_source のキーがあっても check_compat はキーの違いとして数えない."""
        with tempfile.TemporaryDirectory() as d:
            import cv2
            for name, extra in (("ours", True), ("ref", False)):
                ep = Path(d) / name / "e0"
                (ep / "frames").mkdir(parents=True)
                cv2.imwrite(str(ep / "frames" / "000000.jpg"), np.zeros((4, 6, 3), np.uint8))
                kw = {"state_source": np.zeros(1, np.int8)} if extra else {}
                np.savez_compressed(ep / "episode.npz", t=np.zeros(1), t_orig=np.zeros(1),
                                    state=np.zeros((1, 7), np.float32), actions=np.zeros((1, 7), np.float32), **kw)
                (ep / "meta.json").write_text(json.dumps({"fps": 10, "image_size": [6, 4], "state_dim": 7,
                                                          "state_names": [], "task": "x"}))
            self.assertEqual(bce.check_compat(Path(d) / "ours", Path(d) / "ref"), [])


def _old_module():
    """直す前の build_correction_episodes.py (git の HEAD) を別の名前で読み込む."""
    src = subprocess.run(["git", "show", "HEAD:pi05/build_correction_episodes.py"], cwd=_HERE,
                         capture_output=True, text=True, check=True).stdout
    tmp = Path(tempfile.mkdtemp()) / "bce_old.py"
    tmp.write_text(src)
    spec = importlib.util.spec_from_file_location("bce_old", tmp)
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod


# 補正の多い本・巻き戻しのある本など. 依頼 196 の時点で KIOXIA にあるもの
SAMPLE_RUNS = ("pi05_20261031_175527", "pi05_20261031_180435")


@unittest.skipUnless(Path("/Volumes/KIOXIA").is_mount() and bce.RUNS_ROOT.is_dir(), "KIOXIA がない")
class TestSameAsBefore(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.old = _old_module()

    def _build(self, mod, run, d, gap_fill, trim_hold):
        args = SimpleNamespace(gap_fill=gap_fill, trim_hold=trim_hold, no_trim_mid_idle=False,
                               max_protrude_px=None, force=True)
        out = Path(d) / mod.__name__ / f"{gap_fill}_{trim_hold}" / run
        res = mod.build_one(bce.RUNS_ROOT / run, out, args)
        self.assertTrue(res.get("used"), res)
        z = np.load(out / "episode.npz")
        return {k: z[k] for k in z.files}, json.loads((out / "meta.json").read_text())

    def test_bytes_and_counts(self):
        with tempfile.TemporaryDirectory() as d:
            for run in SAMPLE_RUNS:
                if not (bce.RUNS_ROOT / run).is_dir():
                    self.skipTest(f"{run} がない")
                for gap_fill, trim_hold in (("linear", False), ("speed20", False), ("speed20", True)):
                    with self.subTest(run=run, gap_fill=gap_fill, trim_hold=trim_hold):
                        a, _ = self._build(self.old, run, d, gap_fill, trim_hold)
                        b, meta = self._build(bce, run, d, gap_fill, trim_hold)
                        self.assertNotIn("state_source", a)
                        for k in ("t", "t_orig", "state", "actions"):
                            self.assertEqual(a[k].dtype, b[k].dtype, k)
                            self.assertEqual(a[k].tobytes(), b[k].tobytes(), k)
                        src = b["state_source"]
                        self.assertEqual(src.dtype, np.int8)
                        self.assertEqual(len(src), len(b["state"]))
                        self.assertTrue(set(np.unique(src)) <= set(bce.STATE_SOURCE_CODES))
                        gf = meta["gap_fill"]
                        filled = int((src != 0).sum())
                        self.assertEqual(meta["filled_steps"], filled)
                        self.assertEqual(meta["filled_motion_steps"], int((src == 1).sum()))
                        self.assertAlmostEqual(meta["filled_ratio"], filled / len(src), places=4)
                        # 印のつながりの数は抜けの数を超えない (1 つの抜けが印を 2 つに分けることはない)
                        self.assertLessEqual(runs_of_nonzero(src), gf["gaps"])
                        self.assertLessEqual(runs_of_nonzero(src == 1), gf["motion_gaps"])
                        if gf["gaps"] == 0:
                            self.assertEqual(filled, 0)


if __name__ == "__main__":
    unittest.main()
```


### diag_fill_flags.py

```python
#!/usr/bin/env python3
"""diag_fill_flags.py — 既存の補正データセットで, 実測角の抜けを埋めたコマの割合を測る (2026-11-14 依頼 196).

datasets/ の名前に corr / deep_even10 が入るデータセットの, 補正エピソード (meta.json の source が pi05_policy)
ごとに, 元の runs/pi05_policy/{run_stem}/ から build_correction_episodes.build_one を meta.json と同じ条件
(gap_fill の mode・trim_mid_idle・trim_hold) で /tmp に作り直し, state_source (コマごとの印) を数える.
作り直した state / actions / t がデータセットの episode.npz と一致しない本は数えない (理由を CSV に残す).

データセット・元の記録は読むだけ (書かない). 書くのは /tmp と diag/fill_flags_20261114/ だけ.

  python3 pi05/diag_fill_flags.py
"""
import argparse
import csv
import json
import sys
from pathlib import Path
from types import SimpleNamespace

import numpy as np

_HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(_HERE))

import build_correction_episodes as bce  # noqa: E402
import build_demo_episodes as bde  # noqa: E402

OUT_NAME = "fill_flags_20261114"
TMP_ROOT = Path("/tmp") / OUT_NAME
# 学習に使ったことがあるデータセットを先に並べる (依頼 196)
TRAINED_FIRST = ("mecharm_redblock_box_teach_v1_trim2_corr_v5", "mecharm_redblock_box_deep_even10_v1",
                 "mecharm_redblock_box_teach_v1_trim2_corr_v5_deep")


def target_datasets(ds_root):
    names = sorted(p.name for p in ds_root.iterdir()
                   if p.is_dir() and not p.name.startswith(".") and ("corr" in p.name or "deep_even10" in p.name))
    return sorted(names, key=lambda n: (n not in TRAINED_FIRST, TRAINED_FIRST.index(n) if n in TRAINED_FIRST else 0, n))


def rebuild(run_stem, meta, cache):
    """meta.json と同じ条件で /tmp に作り直す. 戻り値: (npz の中身 dict / None, 理由)."""
    gf = meta.get("gap_fill") or {}
    key = (run_stem, gf.get("mode"), bool(meta.get("trim_mid_idle")), meta.get("trim_hold") is not None)
    if key in cache:
        return cache[key]
    out = TMP_ROOT / "rebuild" / "_".join(str(k) for k in key) / run_stem
    args = SimpleNamespace(gap_fill=gf.get("mode") or "linear", trim_hold=key[3],
                           no_trim_mid_idle=not key[2], max_protrude_px=None, force=True)
    res = bce.build_one(bce.RUNS_ROOT / run_stem, out, args)
    if not res.get("used"):
        cache[key] = (None, f"作り直せない: {res.get('reason')}")
    else:
        z = np.load(out / "episode.npz")
        cache[key] = ({k: z[k] for k in z.files}, "ok")
    return cache[key]


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--dataset", action="append", help="このデータセットだけ (複数可)")
    args = ap.parse_args()
    bde.ensure_ssd()
    ds_root = bde.DATA_ROOT / "datasets"
    out_dir = bde.DATA_ROOT / "diag" / OUT_NAME
    if out_dir.exists():
        sys.exit(f"[ABORT] 出力先がもうある: {out_dir}")
    names = args.dataset or target_datasets(ds_root)
    rows, cache = [], {}
    for name in names:
        for mp in sorted((ds_root / name / "raw_episodes").glob("[!.]*/meta.json")):
            meta = json.loads(mp.read_text())
            if not str(meta.get("source", "")).startswith("pi05_policy"):
                continue
            ep = mp.parent
            stem = meta.get("run_stem", ep.name)
            z = np.load(ep / "episode.npz")
            row = {"dataset": name, "episode": ep.name, "run_stem": stem,
                   "gap_fill": (meta.get("gap_fill") or {}).get("mode"),
                   "trim_hold": meta.get("trim_hold") is not None, "steps": len(z["state"]),
                   "filled_steps": "", "filled_motion_steps": "", "filled_ratio": "",
                   "gaps": (meta.get("gap_fill") or {}).get("gaps"),
                   "motion_gaps": (meta.get("gap_fill") or {}).get("motion_gaps"), "status": ""}
            new, why = rebuild(stem, meta, cache)
            if new is None:
                row["status"] = why
            elif not all(k in new and new[k].shape == z[k].shape and new[k].tobytes() == z[k].tobytes()
                         for k in ("state", "actions", "t")):
                row["status"] = "state が一致しない (数えない)"
            else:
                src = new["state_source"]
                n_f = int((src != bce.SRC_MEASURED).sum())
                row.update(filled_steps=n_f, filled_motion_steps=int((src == bce.SRC_FILLED_MOVE).sum()),
                           filled_ratio=round(n_f / len(src), 4), status="ok")
            rows.append(row)
            print(f"{name}  {ep.name}  {row['status']}  {row['filled_steps']}/{row['steps']}")

    if not rows:   # codex P2: 出力先を作る前に止める (空のまま作ると次に走らせられない)
        sys.exit("[ABORT] 対象の補正エピソードがない")
    out_dir.mkdir(parents=True)
    with (out_dir / "episodes.csv").open("w", newline="") as f:
        w = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
        w.writeheader(); w.writerows(rows)
    summ = []
    for name in names:
        rs = [r for r in rows if r["dataset"] == name]
        ok = [r for r in rs if r["status"] == "ok"]
        steps = sum(r["steps"] for r in ok); filled = sum(r["filled_steps"] for r in ok)
        top = max(ok, key=lambda r: r["filled_ratio"]) if ok else None
        summ.append({"dataset": name, "corr_episodes": len(rs), "counted": len(ok),
                     "not_counted": len(rs) - len(ok), "steps": steps, "filled_steps": filled,
                     "filled_motion_steps": sum(r["filled_motion_steps"] for r in ok),
                     "filled_ratio": round(filled / steps, 4) if steps else "",
                     "max_episode": top["episode"] if top else "",
                     "max_episode_ratio": top["filled_ratio"] if top else ""})
    with (out_dir / "summary.csv").open("w", newline="") as f:
        w = csv.DictWriter(f, fieldnames=list(summ[0].keys()))
        w.writeheader(); w.writerows(summ)
    (out_dir / "README.md").write_text(
        "# fill_flags_20261114 (依頼 196)\n\n"
        "既存の補正データセットで, 実測角の抜けを埋めたコマ (state_source が 1 または 2) の数と割合。\n"
        "`python3 pi05/diag_fill_flags.py` で作った。データセットは読むだけ。作り直しは /tmp。\n\n"
        "- state_source: 0 = 実測角 / 1 = 動いた抜けを埋めた値 / 2 = 動かなかった抜けを埋めた値\n"
        "- filled_ratio = (1 と 2 のコマ) / 全コマ。filled_motion_steps は 1 のコマの数\n"
        "- status が ok でない本 (作り直した state / actions / t がデータセットと一致しない・作り直せない) は数えない\n"
        "- episodes.csv: 本ごと / summary.csv: データセットごと (max_episode = 割合がいちばん多い本)\n")
    print(f"→ {out_dir}")
    return 0


if __name__ == "__main__":
    sys.exit(main())
```


## 次にやること：案1で手教示の記録を直し、撮り直したお手本で成功率59.8%と比べる

この回で、データの質を測る道具と、比べるための基準の数字がそろいました。次は次の順で進めます。

| 順 | やること | 要るもの |
|---|---|---|
| 1 | 案1（電流の記録の角度を手教示の記録にも書く）を作る。実装・テスト・レビューまで | 依頼箱 |
| 2 | 実機で1本、次に5本で確かめる。その前に Pi の daemon が11月5日の版かを確かめる | 実機・Pi |
| 3 | 直した記録でお手本を撮り直す | 実機 |
| 4 | 学習し直す | Runpod の GPU |
| 5 | 実機で推論し、判定の画面で成否を付けて、59.8%と比べる | 実機・判定の画面 |

既存の補正のお手本は、作り直していません。印はこの回の道具（`diag_fill_flags.py`）でいつでも数えられるので、次にそのデータで学習するときに印付きで作ります。


## 出典

- ものづくり太郎チャンネル「[【予言的中？】製造現場のAI活用はどこまで来たか？](https://www.youtube.com/watch?v=GmwphgG7cG4)」
- IT Business Today「[Airion と矢崎総業の提携](https://itbusinesstoday.com/ja/tech/ai/airion-yazaki-team-up-on-autonomous-physical-ai/)」
- Physical Intelligence「[π0.5](https://www.pi.website/blog/pi05)」
