The proper supervised training pipeline in training_api.rs (with
real_training_loop using analytical gradients on a regularised
linear model + RecordedFrame deserialisation + .rvf export) was
implemented but never wired into the http_app router.
main.rs registered stub handlers at /api/v1/train/{start,status,stop}
that just flipped a String field. POST /train/start returned
"running" without invoking any training; GET /train/status returned
the stub string instead of a TrainingStatus struct.
This change:
- Declares `mod training_api;` in main.rs so its routes are reachable
- Replaces AppStateInner's `training_status: String` and
`training_config: Option<serde_json::Value>` with the proper
`training_state: training_api::TrainingState` and
`training_progress_tx: broadcast::Sender<String>` fields the
real handlers require
- Removes the three stub handlers (train_status/train_start/
train_stop) and their .route() registrations
- Adds `.merge(training_api::routes())` to expose the real pipeline
plus /ws/train/progress, /train/pretrain, /train/lora
- Inlines RECORDINGS_DIR + RecordedFrame into training_api.rs so we
do not also have to declare `mod recording;` in main.rs
(recording.rs references AppStateInner::recording_state which is
not present on the production AppStateInner; pulling it in
cascades into further refactoring)
- Switches training_api.rs's `crate::path_safety::safe_id` to
`wifi_densepose_sensing_server::path_safety::safe_id` because
path_safety lives in the library tree while training_api lives
in the binary tree
After this change, POST /api/v1/train/start actually trains, and
GET /api/v1/train/status returns the documented TrainingStatus
struct (active, epoch, total_epochs, train_loss, val_pck, val_oks,
lr, best_pck, best_epoch, patience_remaining, eta_secs, phase).
Verified end-to-end locally on an 80k-frame recording — early-stop
fired at epoch 40, .rvf written to data/models/.
Co-Authored-By: claude-flow <ruv@ruv.net>