You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Checklist from an audit comparing sleap-app's training/inference pipeline against sleap-nn's actual CLI/config surface and the legacy ../sleap GUI. Same pass that caught and fixed the invalid --anchor_part inference flag (#... see recent history) and the "entire video" LabelsProvider bug (talmolab/sleap#2848 parity).
Training
(@gitttt-1234 ) "Resume training" / "Reuse model" options are non-functional — training always runs from scratch regardless of selection. hp.trainingMode only locks UI fields (TrainingConfigDialog.tsx); resume_ckpt_path is never set anywhere in trainingStore.ts. Either wire it up for real or remove the misleading radio options. - feat(training): wire up Resume training and Fine-tune modes #305
(@alicup29 ) WandB integration is minimal — only use_wandb/entity/project exposed out of ~13 WandBConfig fields (no viz logging, offline mode, run grouping, etc.). — 🔧 feat(training): WandB offline mode + API key field #312 (draft): adds offline mode + a password-masked API Key field with mode-aware UX. (Several fields were already wired since the audit: save_viz_imgs_wandb/prv_runid/group.) Now also includes auth-status detection (native check_wandb_auth: env WANDB_API_KEY + cached ~/.netrc → green "Authenticated — API key optional", à la PyQt; desktop-only).
(@alicup29 ) No multi-GPU device/strategy control — trainer_device_indices (pick specific GPUs) and trainer_strategy (ddp/fsdp) aren't exposed. — ✅ feat(training): multi-GPU strategy dropdown (trainer_strategy) (#288) #335: added a trainer_strategy dropdown (auto/ddp/fsdp) in the Full Configuration Performance row (serialized to trainer_config.trainer_strategy, machine-specific reset-on-import). trainer_device_indices (GPU-index picker) deferred — needs a new GPU-enumeration command + is CUDA-only.
No instance-size-distribution visualizer — legacy sleap/gui/learning/size.py equivalent; the receptive-field preview is already ported but this one isn't.
(@alicup29 ) Online hard-keypoint-mining is half-ported — missing hard_to_easy_ratio / loss_scale, easy finish since the rest of the plumbing already exists.
(@gitttt-1234 ) Auto-compute max_stride and crop size from the loaded project's instance sizes (like sleap-nn's config-picker's avgAnimalSize thresholds), instead of the current static default + manual medium/large-RF profile pick — crop size needs to account for rotation (and scale) augmentation padding so a rotated animal doesn't get clipped, and ModelStatsPreview's crop preview needs to reflect the auto-computed value. - feat(training): auto max_stride/crop_size recommendations + GPU/cache memory estimates #334
(@alicup29 ) Full training configuration: manually changing the crop size for centered-instance doesn't update the crop visualization at the top — ModelStatsPreview should react to the manual value, not only the auto-computed one (cf. the max_stride/crop auto-compute item above). — ✅ feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307 (draft): ModelStatsPreview now uses the manual hp.cropSize (falls back to auto only in Auto mode), so the crop number + drawn box track edits live.
(@gitttt-1234) No inference-time confidence/visibility result filtering — --filter_min_visible_nodes, --filter_min_visible_node_fraction, --filter_min_mean_node_score, --filter_min_instance_score have no UI/CLI wiring (only the overlap filter is exposed). Not a regression — legacy sleap doesn't have these either, it's unclaimed new sleap-nn capability. - feat(inference): expose full sleap-nn tracking + post-processing filter params #309
(@alicup29 ) "Existing predictions" Replace / Clear-all is inert — stale predictions are never removed. The existingPredictions setting (Training dialog, default replace) is threaded into startTraining but never read; all three merge-backs (inferenceStore random path, loadAndMergeResults, trainingStore.mergeOutputSlp) call MergePredictions with no strategy, so it defaults to "auto" (keeps non-overlapping old predictions). Re-running inference therefore stacks duplicates — repro sleap-app-tutorial/sleap-tutorial-data/labels.v001.slp has 23/50 frames with 4 predicted instances on a 2-fly video (old 2 + new 2). Also: regular inference has no existing-predictions control at all, and io's Labels.merge only visits frames present in the new output, so even replace_predictions leaves stale predictions on frames the new run didn't cover → Clear-all needs a project-/video-scoped DeleteAllPredictions before merge.
Data I/O
(@alicup29 ) Support .avi / .mpeg / .mj2 (and .wmv) in Add Video. Collaborators can't select .avi in the Add-Video picker and have to pre-convert with sleap-io first (sio reencode in.avi -o out.mp4). Today SUPPORTED_VIDEO_EXTS (src/lib/resolveVideos.ts) is mp4/webm/mkv/mov/ogg/ogv/ts/seq and .avi is intentionally excluded ("no sleap-io.js backend decodes it") — so closing this needs transcode-on-import (desktop: shell out to sleap-io/ffmpeg on add), not just widening the file filter.
(@alicup29 ) Skeleton builder: should clarify what the intent is (not detailed labeling yet), doesnt matter where you put the nodes; Make removing nodes action clear -- want to minimize user fear of clicking on the wrong things
(@alicup29 ) Add a view filter to hide predicted instances (or make predictions visually more distinct from user labels) — currently there's no toggle to hide predictions, and predicted vs user-labeled can be hard to tell apart at a glance. — ✅ feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307 (draft): no filter (per decision) — predicted edges now render dashed (on top of the existing thinner + dimmer styling) so predictions read as clearly tentative. Open to a different cue (opacity/tint/badge) if preferred.
(@alicup29 ) window.confirm / alert / prompt are broken in the Tauri (desktop) WebView — they silently no-op, and one of the bypasses is a data-loss risk. The Tauri dialog shim routes these to a nonexistent dialog|confirm command (@tauri-apps/plugin-dialog v2.7.1 only ships message/open/save), so the call rejects and sync code like if (!window.confirm()) treats the rejected Promise as truthy → the guarded action runs anyway with no dialog ever shown. Worst case: unsavedGuard.ts (confirmDiscardUnsavedWork) is bypassed, so New / Open / Import discard unsaved work without prompting (silent data loss on desktop). Other broken callers: App.tsx:286, MenuBar.tsx:894 (confirm); TrainingConfigDialog.tsx:391/397 (alert); navCommands.ts:241 (rename node) + VideoPlayer.tsx:2248 (go-to-frame) (prompt). Fix: route confirm-callers through the in-app confirmDialog() promise helper (@/stores/confirmStore + ConfirmDialog, added in feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307); alert → a message/info variant; prompt → needs a new in-app text-input dialog (bigger lift). confirmDiscardUnsavedWork becomes async (~13 callers await it — all already in async fns, so typecheck catches any miss). Surfaced during feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307: the Clear-cache confirm was silently wiping the transcode cache with no dialog until it was switched to the in-app confirmDialog.
Checklist from an audit comparing sleap-app's training/inference pipeline against sleap-nn's actual CLI/config surface and the legacy
../sleapGUI. Same pass that caught and fixed the invalid--anchor_partinference flag (#... see recent history) and the "entire video" LabelsProvider bug (talmolab/sleap#2848 parity).Training
hp.trainingModeonly locks UI fields (TrainingConfigDialog.tsx);resume_ckpt_pathis never set anywhere intrainingStore.ts. Either wire it up for real or remove the misleading radio options. - feat(training): wire up Resume training and Fine-tune modes #305reduce_lr_on_plateau,step_lr,cosine_annealing_warmup,linear_warmup_linear_decay;trainer_config.lr_scheduleris never set. - feat(training): add LR scheduler, checkpoint retention, and eval-metric controls #342save_top_k/save_last) — no way to also keeplast.ckptalongside the best checkpoint. - feat(training): add LR scheduler, checkpoint retention, and eval-metric controls #342use_wandb/entity/projectexposed out of ~13WandBConfigfields (no viz logging, offline mode, run grouping, etc.). — 🔧 feat(training): WandB offline mode + API key field #312 (draft): adds offline mode + a password-masked API Key field with mode-aware UX. (Several fields were already wired since the audit: save_viz_imgs_wandb/prv_runid/group.) Now also includes auth-status detection (nativecheck_wandb_auth: envWANDB_API_KEY+ cached~/.netrc→ green "Authenticated — API key optional", à la PyQt; desktop-only).EvalConfig) — no live OKS/PCK/centroid-distance metrics during training, only post-hoc. - feat(training): add LR scheduler, checkpoint retention, and eval-metric controls #342trainer_device_indices(pick specific GPUs) andtrainer_strategy(ddp/fsdp) aren't exposed. — ✅ feat(training): multi-GPU strategy dropdown (trainer_strategy) (#288) #335: added atrainer_strategydropdown (auto/ddp/fsdp) in the Full Configuration Performance row (serialized totrainer_config.trainer_strategy, machine-specific reset-on-import).trainer_device_indices(GPU-index picker) deferred — needs a new GPU-enumeration command + is CUDA-only.sleap/gui/learning/size.pyequivalent; the receptive-field preview is already ported but this one isn't.hard_to_easy_ratio/loss_scale, easy finish since the rest of the plumbing already exists.max_strideand crop size from the loaded project's instance sizes (like sleap-nn's config-picker'savgAnimalSizethresholds), instead of the current static default + manual medium/large-RF profile pick — crop size needs to account for rotation (and scale) augmentation padding so a rotated animal doesn't get clipped, andModelStatsPreview's crop preview needs to reflect the auto-computed value. - feat(training): auto max_stride/crop_size recommendations + GPU/cache memory estimates #334ModelStatsPreviewshould react to the manual value, not only the auto-computed one (cf. themax_stride/crop auto-compute item above). — ✅ feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307 (draft):ModelStatsPreviewnow uses the manualhp.cropSize(falls back to auto only in Auto mode), so the crop number + drawn box track edits live.ErrorOutput(with a brief "Copied" confirm).Inference
sleap-nn exportUI, and--runtime(onnx/tensorrt) is never emitted bybuildInferenceArgs. — ✅ feat(inference): ONNX/TensorRT runtime selection (--runtime) (#288) #337 (inference Runtime dropdown auto/onnx/tensorrt +--runtimeemission, TensorRT gated to CUDA) + feat(export): in-app ONNX/TensorRT model exporter + on-demand install (#288) #338 (in-app Export→ONNX/TensorRT dialog viasleap-nn export+ on-demand[export]install + post-training entry point). End-to-end train→export→onnx-infer not yet desktop-verified.--filter_min_visible_nodes,--filter_min_visible_node_fraction,--filter_min_mean_node_score,--filter_min_instance_scorehave no UI/CLI wiring (only the overlap filter is exposed). Not a regression — legacy sleap doesn't have these either, it's unclaimed new sleap-nn capability. - feat(inference): expose full sleap-nn tracking + post-processing filter params #309existingPredictionssetting (Training dialog, defaultreplace) is threaded intostartTrainingbut never read; all three merge-backs (inferenceStorerandom path,loadAndMergeResults,trainingStore.mergeOutputSlp) callMergePredictionswith nostrategy, so it defaults to"auto"(keeps non-overlapping old predictions). Re-running inference therefore stacks duplicates — reprosleap-app-tutorial/sleap-tutorial-data/labels.v001.slphas 23/50 frames with 4 predicted instances on a 2-fly video (old 2 + new 2). Also: regular inference has no existing-predictions control at all, and io'sLabels.mergeonly visits frames present in the new output, so evenreplace_predictionsleaves stale predictions on frames the new run didn't cover → Clear-all needs a project-/video-scopedDeleteAllPredictionsbefore merge.Data I/O
.avi/.mpeg/.mj2(and.wmv) in Add Video. Collaborators can't select.aviin the Add-Video picker and have to pre-convert with sleap-io first (sio reencode in.avi -o out.mp4). TodaySUPPORTED_VIDEO_EXTS(src/lib/resolveVideos.ts) ismp4/webm/mkv/mov/ogg/ogv/ts/seqand.aviis intentionally excluded ("no sleap-io.js backend decodes it") — so closing this needs transcode-on-import (desktop: shell out to sleap-io/ffmpeg on add), not just widening the file filter..avi/.wmv(H.264/MJPEG, browser and desktop, nosio reencodepre-convert) viaAviVideoBackend— feat(video): AviVideoBackend — in-browser .avi/.wmv decode (web-demuxer + WebCodecs/ImageDecoder) sleap-io.js#252 + app wiring feat(video): in-app .avi/.wmv labeling (sleap-io.js AviVideoBackend) #306 — plus a desktop ffmpeg-sidecar transcode for codecs WebCodecs can't decode (Xvid/DivX = MPEG-4 ASP, WMV3/VC-1, MPEG-1/2, 10-bit HEVC) and.mpeg/.mpg— feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307: a bundled ffmpeg converts once to a frame-exact H.264 MP4 cached in the app cache dir (frame count preserved 1:1 so labels stay aligned), with an opt-in "temporary copy for viewing — original file +.slpunchanged" prompt, live progress + cancel, and a Clear-cache menu. So legacy codecs convert automatically instead of a manual pre-convert..mj2(Motion JPEG 2000) still open — WebCodecs/web-demuxer don't decode JPEG 2000; route via the feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307 ffmpeg path or an opt-in@cornerstonejs/codec-openjpegbranch. (detail in comment below)UI/UX
Noticed during a tutorial-session passthrough (@alicup29).
devicePixelRatioand rescale reactively on window/zoom resize so it stays sharp (DPI-correct text). — header frame-markers ✅ fix(ux): tutorial-session UX batch (6 fixes) — magnifier, predicted marks, epoch count, suggestions scroll, header DPI, training freeze #295 (rescale on resize); keypoint-label blur still open (needs screen-space text rendering)sidebarMultiPaneldefaults on)labels.vNNN.slp+ add versioning — follow PyQt SLEAP as the ground truth for the naming convention (auto-increment the.vNNNsuffix on save; see legacysleap's save/SaveProjectAsbehavior). — ✅ feat(ux): OS-correct shortcut labels, multi-panel default, labels.vNNN.slp auto-versioning (#288) #302 (getNewVersionFilename; Save As bumps, Save overwrites; unversioned names start at.v001)formatShortcutchoke-point across menus, palette, shortcuts dialog, context menu)Alt+modifier accelerators in the menus should render as ⌥ Option (gap in the feat(ux): OS-correct shortcut labels, multi-panel default, labels.vNNN.slp auto-versioning (#288) #302formatShortcutpass — some menu Alt-based hints aren't being converted). — ✅ feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307 (draft): addedaltKey(⌥ on macOS) toplatform.ts; the four hardcodedAlt+…menu items now use it.duration: Infinitywith only a "Send diagnostics" action; added a Dismiss button (and it now dismisses on "Send diagnostics" too). Desktop-only path.window.confirm/alert/promptare broken in the Tauri (desktop) WebView — they silently no-op, and one of the bypasses is a data-loss risk. The Tauri dialog shim routes these to a nonexistentdialog|confirmcommand (@tauri-apps/plugin-dialogv2.7.1 only shipsmessage/open/save), so the call rejects and sync code likeif (!window.confirm())treats the rejected Promise as truthy → the guarded action runs anyway with no dialog ever shown. Worst case:unsavedGuard.ts(confirmDiscardUnsavedWork) is bypassed, so New / Open / Import discard unsaved work without prompting (silent data loss on desktop). Other broken callers:App.tsx:286,MenuBar.tsx:894(confirm);TrainingConfigDialog.tsx:391/397(alert);navCommands.ts:241(rename node) +VideoPlayer.tsx:2248(go-to-frame) (prompt). Fix: route confirm-callers through the in-appconfirmDialog()promise helper (@/stores/confirmStore+ConfirmDialog, added in feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307);alert→ amessage/info variant;prompt→ needs a new in-app text-input dialog (bigger lift).confirmDiscardUnsavedWorkbecomesasync(~13 callers await it — all already in async fns, so typecheck catches any miss). Surfaced during feat(video): desktop legacy-codec transcode fallback (Xvid/WMV/MPEG → H.264) #307: the Clear-cache confirm was silently wiping the transcode cache with no dialog until it was switched to the in-appconfirmDialog.