Skip to content

feat: preflight verifiers for record and train, fix training subprocess env - #96

Open
pearlq12345 wants to merge 8 commits into
MINT-SJTU:mainfrom
pearlq12345:feat/record-train-preflight
Open

feat: preflight verifiers for record and train, fix training subprocess env#96
pearlq12345 wants to merge 8 commits into
MINT-SJTU:mainfrom
pearlq12345:feat/record-train-preflight

Conversation

@pearlq12345

@pearlq12345 pearlq12345 commented May 5, 2026

Copy link
Copy Markdown

What

  • Add RecordPreflightVerifier: validates record args before spawning LeRobot (repo_id, root, num_episodes, episode_time_s, fps, task, arm config)
  • Add TrainPreflightVerifier: validates training args before spawning lerobot-train (dataset_name, policy_type, steps, device)
  • Fix CommandBuilder.train() using bare lerobot-train command — now uses sys.executable -m lerobot.scripts.lerobot_train to respect active Python env
  • HTTP route returns 400 on validation errors; frontend shows error message below action buttons

Testing

  • 20 unit tests in tests/verification/test_record_train_preflight.py
  • End-to-end: training job runs successfully with pusht dataset

Xiaofang Wu added 8 commits May 4, 2026 22:03
RecordPreflightVerifier — validates before spawning lerobot record:
- wrapper action is 'record'
- required dataset args present (repo_id, root, num_episodes, episode_time_s)
- num_episodes / episode_time_s within sane bounds
- fps in [1, 120]
- non-empty task string
- at least one follower arm; bimanual requires left+right

TrainPreflightVerifier — validates before dispatching lerobot-train:
- non-empty dataset_name
- policy_type in {act, diffusion, tdmpc, vqbet}
- steps in [1, 10_000_000]
- non-empty device
- warns (not blocks) if dataset path not yet local

EmbodiedService.start_recording() now runs RecordPreflightVerifier.
EmbodiedService.start_training() new method runs TrainPreflightVerifier
and replaces the raw service.train.train() call in the HTTP route.

Tests: 20 passed (test_record_train_preflight.py)
- Move _verify_train_preflight() before require_local_dataset() so bad
  params (empty name, unsupported policy_type, invalid steps) are
  rejected immediately without touching the filesystem
- Add try/except RuntimeError in train_start route so ActionError
  surfaces as HTTP 400 instead of 500
- TrainPreflightVerifier now imports TRAIN_POLICY_TYPES from
  CommandBuilder instead of maintaining a separate hardcoded set,
  so smolvla/pi0/groot/etc are accepted without manual sync
- doTrainStart catches API errors and writes them to trainJobMessage
- TrainingCenterPage renders trainJobMessage as a red banner below
  the action buttons so preflight rejections are visible to the user
- Use list_local_datasets() instead of resolve_runtime_dataset() to
  find dataset by runtime name, avoiding the symlink path-traversal
  check that rejects valid datasets under symlinked directories
- Call SubprocessExecutor directly instead of TrainSession.train()
  to avoid double dataset resolution
- Catch ValueError in train route (not just RuntimeError)
- Show trainJobMessage as red banner in TrainingCenterPage
@pearlq12345

Copy link
Copy Markdown
Author

The one remaining test failure (test_recovery_faults_return_current_faults) is pre-existing on main — /api/recovery/faults returns 404 regardless of this PR. test_dashboard_routes.py is untouched in this branch.

hzhe0083-source pushed a commit to Shiki42/RoboClaw that referenced this pull request May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant