splitsmith 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. splitsmith-0.3.0/CHANGELOG.md +34 -0
  2. {splitsmith-0.2.0 → splitsmith-0.3.0}/PKG-INFO +23 -24
  3. {splitsmith-0.2.0 → splitsmith-0.3.0}/README.md +22 -23
  4. {splitsmith-0.2.0 → splitsmith-0.3.0}/pyproject.toml +1 -1
  5. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/__init__.py +1 -1
  6. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/config.py +2 -3
  7. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/fcpxml_gen.py +1 -1
  8. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/__init__.py +1 -2
  9. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/server.py +13 -5
  10. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/AuditControls.tsx +8 -6
  11. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/BeepSection.tsx +226 -57
  12. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/HelpOverlay.tsx +7 -5
  13. splitsmith-0.3.0/src/splitsmith/ui_static/src/components/audit/BeepAnomalyBanner.tsx +71 -0
  14. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/BeepStatusChip.tsx +17 -38
  15. splitsmith-0.3.0/src/splitsmith/ui_static/src/components/audit/ShortcutHints.tsx +148 -0
  16. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/StageActionBar.tsx +8 -5
  17. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/api.ts +11 -3
  18. splitsmith-0.3.0/src/splitsmith/ui_static/src/lib/keyboard.ts +45 -0
  19. splitsmith-0.3.0/src/splitsmith/ui_static/src/lib/platform.ts +50 -0
  20. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Audit.tsx +132 -368
  21. splitsmith-0.3.0/src/splitsmith/ui_static/src/pages/BeepReview.tsx +1049 -0
  22. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Coach.tsx +5 -0
  23. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Design.tsx +3 -2
  24. splitsmith-0.3.0/src/splitsmith/ui_static/tsconfig.app.tsbuildinfo +1 -0
  25. {splitsmith-0.2.0 → splitsmith-0.3.0}/uv.lock +1 -1
  26. splitsmith-0.2.0/CHANGELOG.md +0 -19
  27. splitsmith-0.2.0/src/splitsmith/ui_static/src/components/audit/SyncBanner.tsx +0 -157
  28. splitsmith-0.2.0/src/splitsmith/ui_static/src/pages/BeepReview.tsx +0 -759
  29. splitsmith-0.2.0/src/splitsmith/ui_static/tsconfig.app.tsbuildinfo +0 -1
  30. {splitsmith-0.2.0 → splitsmith-0.3.0}/.gitignore +0 -0
  31. {splitsmith-0.2.0 → splitsmith-0.3.0}/LICENSE +0 -0
  32. {splitsmith-0.2.0 → splitsmith-0.3.0}/docs/local-slim/README.md +0 -0
  33. {splitsmith-0.2.0 → splitsmith-0.3.0}/docs/saas-readiness/README.md +0 -0
  34. {splitsmith-0.2.0 → splitsmith-0.3.0}/site/README.md +0 -0
  35. {splitsmith-0.2.0 → splitsmith-0.3.0}/skills/splitsmith-match/README.md +0 -0
  36. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/audit.py +0 -0
  37. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/automation.py +0 -0
  38. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/backup.py +0 -0
  39. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/beep_calibration.py +0 -0
  40. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/beep_detect.py +0 -0
  41. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/cleanup.py +0 -0
  42. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/cli.py +0 -0
  43. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/coach.py +0 -0
  44. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/coach_distributions.py +0 -0
  45. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/compare/__init__.py +0 -0
  46. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/compare/cli.py +0 -0
  47. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/compare/emitter.py +0 -0
  48. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/compare/filler.py +0 -0
  49. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/compare/layout.py +0 -0
  50. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/compare/manifest.py +0 -0
  51. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/compare/project_loader.py +0 -0
  52. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/composition.py +0 -0
  53. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/cross_align.py +0 -0
  54. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/csv_gen.py +0 -0
  55. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/ensemble_calibration.json +0 -0
  56. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/fonts/Antonio-OFL.txt +0 -0
  57. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/fonts/Antonio-VariableFont.ttf +0 -0
  58. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/fonts/JetBrainsMono-Bold.ttf +0 -0
  59. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/fonts/JetBrainsMono-OFL.txt +0 -0
  60. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/overlay_theme.json +0 -0
  61. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/templates/action-cut.yaml +0 -0
  62. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/templates/match-recap.yaml +0 -0
  63. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/voter_c_gbdt.joblib +0 -0
  64. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/data/voter_e_visual_probe.joblib +0 -0
  65. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/__init__.py +0 -0
  66. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/agc_state.py +0 -0
  67. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/api.py +0 -0
  68. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/backend.py +0 -0
  69. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/calibration.py +0 -0
  70. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/clap_mel.py +0 -0
  71. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/features.py +0 -0
  72. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/fixtures.py +0 -0
  73. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/tta.py +0 -0
  74. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/visual.py +0 -0
  75. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ensemble/voters.py +0 -0
  76. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/fcp7xml_render.py +0 -0
  77. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/fixture_schema.py +0 -0
  78. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/lab/__init__.py +0 -0
  79. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/lab/core.py +0 -0
  80. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/lab/promote.py +0 -0
  81. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/lab/snap_window.py +0 -0
  82. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/lab/sweeps.py +0 -0
  83. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/lab_cli.py +0 -0
  84. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/match_cli.py +0 -0
  85. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/match_model.py +0 -0
  86. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/match_registry.py +0 -0
  87. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/mcp/__init__.py +0 -0
  88. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/mcp/__main__.py +0 -0
  89. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/mcp/detect_tools.py +0 -0
  90. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/mcp/export_tools.py +0 -0
  91. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/mcp/sandbox.py +0 -0
  92. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/mcp/server.py +0 -0
  93. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/mcp/tools.py +0 -0
  94. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/mcp/write_tools.py +0 -0
  95. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/model_cli.py +0 -0
  96. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/models/__init__.py +0 -0
  97. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/models/cache.py +0 -0
  98. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/models/download.py +0 -0
  99. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/models/errors.py +0 -0
  100. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/models/manifest.py +0 -0
  101. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/models/registry.py +0 -0
  102. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/mp4_render.py +0 -0
  103. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/overlay_render.py +0 -0
  104. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/overlay_theme.py +0 -0
  105. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/relink.py +0 -0
  106. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/report.py +0 -0
  107. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/runtime.py +0 -0
  108. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/shot_detect.py +0 -0
  109. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/shot_refine.py +0 -0
  110. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/system_check.py +0 -0
  111. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/templates.py +0 -0
  112. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/thumbnail.py +0 -0
  113. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/trim.py +0 -0
  114. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/audio.py +0 -0
  115. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/embedded.py +0 -0
  116. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/exports.py +0 -0
  117. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/jobs.py +0 -0
  118. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/logging_setup.py +0 -0
  119. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/match_exports.py +0 -0
  120. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/project.py +0 -0
  121. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/scoreboard/__init__.py +0 -0
  122. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/scoreboard/cache.py +0 -0
  123. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/scoreboard/http.py +0 -0
  124. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/scoreboard/local.py +0 -0
  125. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/scoreboard/models.py +0 -0
  126. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui/scoreboard/protocol.py +0 -0
  127. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/.gitignore +0 -0
  128. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/index.html +0 -0
  129. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/package-lock.json +0 -0
  130. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/package.json +0 -0
  131. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/pnpm-lock.yaml +0 -0
  132. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/App.tsx +0 -0
  133. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/AddFootageModal.tsx +0 -0
  134. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/AppShell.tsx +0 -0
  135. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/CameraModelSelect.tsx +0 -0
  136. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/CleanupDialog.tsx +0 -0
  137. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/DirectoryPickerModal.tsx +0 -0
  138. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/FolderPicker.tsx +0 -0
  139. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/HitlQueuePanel.tsx +0 -0
  140. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/Jobs.tsx +0 -0
  141. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ListDrawer.tsx +0 -0
  142. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/MarkerGlyph.tsx +0 -0
  143. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/MarkerLayer.tsx +0 -0
  144. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/MountSelect.tsx +0 -0
  145. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/RelinkDialog.tsx +0 -0
  146. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/SettingProvenance.tsx +0 -0
  147. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ShooterScopedRoute.tsx +0 -0
  148. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ShotStepper.tsx +0 -0
  149. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/StageTimeSection.tsx +0 -0
  150. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/SweepsCard.tsx +0 -0
  151. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/VideoPanel.tsx +0 -0
  152. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/Waveform.tsx +0 -0
  153. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/AnomalyChips.tsx +0 -0
  154. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/AnomalyPins.tsx +0 -0
  155. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/CamGridModal.tsx +0 -0
  156. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/CamSyncPill.tsx +0 -0
  157. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/MultiCamColumn.tsx +0 -0
  158. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/PrereqGate.tsx +0 -0
  159. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/SessionSummary.tsx +0 -0
  160. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/audit/StageChipRail.tsx +0 -0
  161. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/developer/DeveloperShell.tsx +0 -0
  162. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/match/MatchShell.tsx +0 -0
  163. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/match/MatchSidebar.tsx +0 -0
  164. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/match/ShooterChipStrip.tsx +0 -0
  165. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/AvatarStack.tsx +0 -0
  166. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/Brand.tsx +0 -0
  167. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/ContextBar.tsx +0 -0
  168. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/DisplayHeading.tsx +0 -0
  169. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/IconButton.tsx +0 -0
  170. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/Kbd.tsx +0 -0
  171. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/Kicker.tsx +0 -0
  172. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/ModeSwitch.tsx +0 -0
  173. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/Readout.tsx +0 -0
  174. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/ShotTimerShell.tsx +0 -0
  175. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/StageDot.tsx +0 -0
  176. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/StatusPill.tsx +0 -0
  177. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/Tick.tsx +0 -0
  178. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/badge.tsx +0 -0
  179. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/button.tsx +0 -0
  180. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/card.tsx +0 -0
  181. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/index.ts +0 -0
  182. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/components/ui/skeleton.tsx +0 -0
  183. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/anomalies.ts +0 -0
  184. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/audit-input.ts +0 -0
  185. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/audit-next-step.ts +0 -0
  186. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/features.ts +0 -0
  187. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/matchHref.ts +0 -0
  188. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/mode.tsx +0 -0
  189. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/slugify.ts +0 -0
  190. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/stageStatus.ts +0 -0
  191. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/lib/utils.ts +0 -0
  192. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/main.tsx +0 -0
  193. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Compare.tsx +0 -0
  194. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/CreateMatch.tsx +0 -0
  195. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Export.tsx +0 -0
  196. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Home.tsx +0 -0
  197. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Ingest.tsx +0 -0
  198. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Lab.tsx +0 -0
  199. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/MergeMatches.tsx +0 -0
  200. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Pick.tsx +0 -0
  201. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/PromoteReview.tsx +0 -0
  202. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Review.tsx +0 -0
  203. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/Shooters.tsx +0 -0
  204. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/dev/DevCorpus.tsx +0 -0
  205. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/dev/DevRetrain.tsx +0 -0
  206. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/dev/DevReviewQueue.tsx +0 -0
  207. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/pages/dev/DevValidate.tsx +0 -0
  208. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/src/styles/index.css +0 -0
  209. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/tsconfig.app.json +0 -0
  210. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/tsconfig.json +0 -0
  211. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/tsconfig.node.json +0 -0
  212. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/tsconfig.node.tsbuildinfo +0 -0
  213. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/ui_static/vite.config.ts +0 -0
  214. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/user_config.py +0 -0
  215. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/video_match.py +0 -0
  216. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/video_probe.py +0 -0
  217. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/waveform.py +0 -0
  218. {splitsmith-0.2.0 → splitsmith-0.3.0}/src/splitsmith/youtube_sidecar.py +0 -0
  219. {splitsmith-0.2.0 → splitsmith-0.3.0}/tests/fixtures/beep_calibration/README.md +0 -0
  220. {splitsmith-0.2.0 → splitsmith-0.3.0}/tests/fixtures/schemas/README.md +0 -0
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ ## [0.3.0](https://github.com/mandakan/splitsmith/compare/v0.2.1...v0.3.0) (2026-05-25)
4
+
5
+
6
+ ### Features
7
+
8
+ * **beep-review:** single home for beep work; trim audit page ([#399](https://github.com/mandakan/splitsmith/issues/399)) ([9ecf999](https://github.com/mandakan/splitsmith/commit/9ecf9998f94edeb5420e3a982f97ae4edb2114f0))
9
+ * **brand:** hero + og:image, new tagline, audit shortcut hints ([#401](https://github.com/mandakan/splitsmith/issues/401)) ([40aa55a](https://github.com/mandakan/splitsmith/commit/40aa55ac56da0e9c81ae373554b9dc8816f4b2e0))
10
+
11
+ ## [0.2.1](https://github.com/mandakan/splitsmith/compare/v0.2.0...v0.2.1) (2026-05-24)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * **docs:** use absolute GitHub URLs for README images on PyPI ([#398](https://github.com/mandakan/splitsmith/issues/398)) ([de435a6](https://github.com/mandakan/splitsmith/commit/de435a6981b0532f05c159a73da86a9d107bf6af))
17
+
18
+ ## 0.2.0 (2026-05-24)
19
+
20
+ First public release.
21
+
22
+ Extract IPSC shot splits from head-mounted camera footage. Detect shots
23
+ via a 3-voter ensemble (envelope onset / CLAP / GBDT-with-PANN), produce
24
+ a CSV of splits, and emit an FCPXML timeline with per-shot markers and
25
+ optional overlay clips for Final Cut Pro.
26
+
27
+ Install:
28
+
29
+ ```
30
+ uv tool install splitsmith
31
+ ```
32
+
33
+ After install, run `splitsmith fetch-models` to pre-download the ~440 MB
34
+ of ONNX detection artifacts (otherwise they download on first detection).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: splitsmith
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Extract IPSC shot splits from head-mounted camera footage
5
5
  Author: Mathias Axell
6
6
  License: MIT
@@ -29,9 +29,14 @@ Description-Content-Type: text/markdown
29
29
 
30
30
  # splitsmith
31
31
 
32
+ [![PyPI version](https://img.shields.io/pypi/v/splitsmith.svg)](https://pypi.org/project/splitsmith/)
33
+ [![Python versions](https://img.shields.io/pypi/pyversions/splitsmith.svg)](https://pypi.org/project/splitsmith/)
34
+ [![License](https://img.shields.io/pypi/l/splitsmith.svg)](https://github.com/mandakan/splitsmith/blob/main/LICENSE)
35
+ [![CI](https://img.shields.io/github/actions/workflow/status/mandakan/splitsmith/ci.yml?branch=main&label=ci)](https://github.com/mandakan/splitsmith/actions/workflows/ci.yml)
36
+
32
37
  Extract per-shot split times from head-mounted camera footage of IPSC matches and generate Final Cut Pro timelines with per-shot markers.
33
38
 
34
- ![audit view](docs/screenshots/audit.png)
39
+ ![Splitsmith -- Detect. Coach. Cut.](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/hero.png)
35
40
 
36
41
  Built to do two things from a single stage video: get per-shot splits for analysis and coaching, and prepare frame-marked clips for match-footage review. Your head-mounted cam (Insta360 Go 3S in this case) already captures audio of every shot; the RO's timer only records your total stage time, so the splits live in the video and nowhere else. Splitsmith extracts them and turns them into a CSV plus an FCPXML timeline with per-shot markers you can step through in Final Cut Pro.
37
42
 
@@ -42,30 +47,24 @@ Built to do two things from a single stage video: get per-shot splits for analys
42
47
 
43
48
  | | |
44
49
  |---|---|
45
- | ![ingest](docs/screenshots/ingest.png) | **Ingest.** Drop a folder of GoPro clips; the engine auto-matches them to stages by file timestamp. |
46
- | ![beep review](docs/screenshots/beep-review.png) | **Beep review.** Auto-snap to the start beep on each stage; low-confidence detections land in a HITL queue. |
47
- | ![audit](docs/screenshots/audit.png) | **Audit.** Waveform + per-shot markers from the 3-voter ensemble. Click a marker to inspect votes; drag to fine-tune. |
48
- | ![compare](docs/screenshots/compare.png) | **Compare.** Multi-shooter grid, all beep-aligned to t=0. Audio from one shooter, video tiles for everyone else. |
49
- | ![export](docs/screenshots/export.png) | **Export.** Per-stage or whole-match FCPXML. Open in Final Cut Pro, M / Shift+M to navigate markers. |
50
+ | ![ingest](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/ingest.png) | **Ingest.** Drop a folder of GoPro clips; the engine auto-matches them to stages by file timestamp. |
51
+ | ![beep review](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/beep-review.png) | **Beep review.** Auto-snap to the start beep on each stage; low-confidence detections land in a HITL queue. |
52
+ | ![audit](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/audit.png) | **Audit.** Waveform + per-shot markers from the 3-voter ensemble. Click a marker to inspect votes; drag to fine-tune. |
53
+ | ![compare](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/compare.png) | **Compare.** Multi-shooter grid, all beep-aligned to t=0. Audio from one shooter, video tiles for everyone else. |
54
+ | ![export](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/export.png) | **Export.** Per-stage or whole-match FCPXML. Open in Final Cut Pro, M / Shift+M to navigate markers. |
50
55
 
51
- > Screenshots regenerate from a live `splitsmith ui` via `scripts/capture_screenshots.py`. See [issue tracking the local run](#regenerating-screenshots) below.
56
+ > Screenshots regenerate from a live `splitsmith ui` via `scripts/capture_screenshots.py`. See [Regenerating screenshots](#regenerating-screenshots) below.
52
57
 
53
58
  ## Quickstart
54
59
 
55
- > The slim wheel install (`uv tool install splitsmith`) is the target end-user path once the wheel is published to PyPI -- the engine work is done (#377), publishing is the next step. Until then, install from source as described below.
56
-
57
- You need: `uv`, `ffmpeg`/`ffprobe` on PATH, and (for source checkouts) Node 20 + `pnpm` to build the SPA. See [Install](#install) for OS-specific package commands.
60
+ You need: `uv` and `ffmpeg`/`ffprobe` on PATH. See [Install](#install) for OS-specific package commands.
58
61
 
59
62
  ```bash
60
- # Install from source (today's recommended path)
61
- git clone https://github.com/mandakan/splitsmith.git
62
- cd splitsmith
63
- uv sync # slim runtime deps only (~100 MB)
64
- (cd src/splitsmith/ui_static && pnpm install && pnpm build)
65
- uv run splitsmith fetch-models # ~440 MB ONNX artifacts; one-time
63
+ uv tool install splitsmith # slim runtime, ~100 MB
64
+ splitsmith fetch-models # ~440 MB ONNX artifacts; one-time
66
65
 
67
66
  # Bring your own head-cam clip and stage time (or use any IPSC video at hand)
68
- uv run splitsmith single \
67
+ splitsmith single \
69
68
  --video path/to/your_stage.mp4 \
70
69
  --time 14.74 \
71
70
  --output ./demo_analysis \
@@ -79,7 +78,7 @@ cat ./demo_analysis/stage3_per-told-me-to-do-it_report.txt
79
78
  For the full ingest -> audit -> export workflow with persistent project state, use the UI:
80
79
 
81
80
  ```bash
82
- uv run splitsmith ui --project ~/matches/your-match
81
+ splitsmith ui --project ~/matches/your-match
83
82
  ```
84
83
 
85
84
  The repo ships a real Stage 3 audio sample at `tests/fixtures/stage-shots-tallmilan-2026-stage3-s97dcec94.wav` (Tallmilan 2026, 14.74s, 14 audited shots) plus its sibling JSON with ground-truth shot times. The companion source MP4 is gitignored -- bring your own video to exercise the full ingest pipeline.
@@ -105,17 +104,17 @@ The repo ships a real Stage 3 audio sample at `tests/fixtures/stage-shots-tallmi
105
104
 
106
105
  `splitsmith ui` checks for both on first launch and prints a copy-pasteable install hint if they're missing.
107
106
 
108
- ### Option 1: slim wheel (end users, ~100 MB) -- pending first PyPI release
109
-
110
- The shipped install will be `uv tool install splitsmith` once the first release-please release lands on `main` (see [Releases](#releases) below). Detection models (~440 MB total) download from `models.splitsmith.app` on first detection -- pre-fetch with `splitsmith fetch-models`. No torch, transformers, or panns_inference in the install.
107
+ ### Option 1: slim wheel (end users, ~100 MB)
111
108
 
112
109
  ```bash
113
- uv tool install splitsmith # available after the first 0.x.y release; see Option 2 below until then
110
+ uv tool install splitsmith # from PyPI
114
111
  splitsmith fetch-models # pre-fetch ONNX artifacts (optional)
115
112
  splitsmith ui --project ~/matches/your-match
116
113
  ```
117
114
 
118
- ### Option 2: from source (today's recommended path; required for contributors)
115
+ Detection models (~440 MB total) download from `models.splitsmith.app` on first detection -- pre-fetch with `splitsmith fetch-models`. No torch, transformers, or panns_inference in the install.
116
+
117
+ ### Option 2: from source (required for contributors)
119
118
 
120
119
  ```bash
121
120
  git clone https://github.com/mandakan/splitsmith.git
@@ -1,8 +1,13 @@
1
1
  # splitsmith
2
2
 
3
+ [![PyPI version](https://img.shields.io/pypi/v/splitsmith.svg)](https://pypi.org/project/splitsmith/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/splitsmith.svg)](https://pypi.org/project/splitsmith/)
5
+ [![License](https://img.shields.io/pypi/l/splitsmith.svg)](https://github.com/mandakan/splitsmith/blob/main/LICENSE)
6
+ [![CI](https://img.shields.io/github/actions/workflow/status/mandakan/splitsmith/ci.yml?branch=main&label=ci)](https://github.com/mandakan/splitsmith/actions/workflows/ci.yml)
7
+
3
8
  Extract per-shot split times from head-mounted camera footage of IPSC matches and generate Final Cut Pro timelines with per-shot markers.
4
9
 
5
- ![audit view](docs/screenshots/audit.png)
10
+ ![Splitsmith -- Detect. Coach. Cut.](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/hero.png)
6
11
 
7
12
  Built to do two things from a single stage video: get per-shot splits for analysis and coaching, and prepare frame-marked clips for match-footage review. Your head-mounted cam (Insta360 Go 3S in this case) already captures audio of every shot; the RO's timer only records your total stage time, so the splits live in the video and nowhere else. Splitsmith extracts them and turns them into a CSV plus an FCPXML timeline with per-shot markers you can step through in Final Cut Pro.
8
13
 
@@ -13,30 +18,24 @@ Built to do two things from a single stage video: get per-shot splits for analys
13
18
 
14
19
  | | |
15
20
  |---|---|
16
- | ![ingest](docs/screenshots/ingest.png) | **Ingest.** Drop a folder of GoPro clips; the engine auto-matches them to stages by file timestamp. |
17
- | ![beep review](docs/screenshots/beep-review.png) | **Beep review.** Auto-snap to the start beep on each stage; low-confidence detections land in a HITL queue. |
18
- | ![audit](docs/screenshots/audit.png) | **Audit.** Waveform + per-shot markers from the 3-voter ensemble. Click a marker to inspect votes; drag to fine-tune. |
19
- | ![compare](docs/screenshots/compare.png) | **Compare.** Multi-shooter grid, all beep-aligned to t=0. Audio from one shooter, video tiles for everyone else. |
20
- | ![export](docs/screenshots/export.png) | **Export.** Per-stage or whole-match FCPXML. Open in Final Cut Pro, M / Shift+M to navigate markers. |
21
+ | ![ingest](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/ingest.png) | **Ingest.** Drop a folder of GoPro clips; the engine auto-matches them to stages by file timestamp. |
22
+ | ![beep review](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/beep-review.png) | **Beep review.** Auto-snap to the start beep on each stage; low-confidence detections land in a HITL queue. |
23
+ | ![audit](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/audit.png) | **Audit.** Waveform + per-shot markers from the 3-voter ensemble. Click a marker to inspect votes; drag to fine-tune. |
24
+ | ![compare](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/compare.png) | **Compare.** Multi-shooter grid, all beep-aligned to t=0. Audio from one shooter, video tiles for everyone else. |
25
+ | ![export](https://raw.githubusercontent.com/mandakan/splitsmith/main/docs/screenshots/export.png) | **Export.** Per-stage or whole-match FCPXML. Open in Final Cut Pro, M / Shift+M to navigate markers. |
21
26
 
22
- > Screenshots regenerate from a live `splitsmith ui` via `scripts/capture_screenshots.py`. See [issue tracking the local run](#regenerating-screenshots) below.
27
+ > Screenshots regenerate from a live `splitsmith ui` via `scripts/capture_screenshots.py`. See [Regenerating screenshots](#regenerating-screenshots) below.
23
28
 
24
29
  ## Quickstart
25
30
 
26
- > The slim wheel install (`uv tool install splitsmith`) is the target end-user path once the wheel is published to PyPI -- the engine work is done (#377), publishing is the next step. Until then, install from source as described below.
27
-
28
- You need: `uv`, `ffmpeg`/`ffprobe` on PATH, and (for source checkouts) Node 20 + `pnpm` to build the SPA. See [Install](#install) for OS-specific package commands.
31
+ You need: `uv` and `ffmpeg`/`ffprobe` on PATH. See [Install](#install) for OS-specific package commands.
29
32
 
30
33
  ```bash
31
- # Install from source (today's recommended path)
32
- git clone https://github.com/mandakan/splitsmith.git
33
- cd splitsmith
34
- uv sync # slim runtime deps only (~100 MB)
35
- (cd src/splitsmith/ui_static && pnpm install && pnpm build)
36
- uv run splitsmith fetch-models # ~440 MB ONNX artifacts; one-time
34
+ uv tool install splitsmith # slim runtime, ~100 MB
35
+ splitsmith fetch-models # ~440 MB ONNX artifacts; one-time
37
36
 
38
37
  # Bring your own head-cam clip and stage time (or use any IPSC video at hand)
39
- uv run splitsmith single \
38
+ splitsmith single \
40
39
  --video path/to/your_stage.mp4 \
41
40
  --time 14.74 \
42
41
  --output ./demo_analysis \
@@ -50,7 +49,7 @@ cat ./demo_analysis/stage3_per-told-me-to-do-it_report.txt
50
49
  For the full ingest -> audit -> export workflow with persistent project state, use the UI:
51
50
 
52
51
  ```bash
53
- uv run splitsmith ui --project ~/matches/your-match
52
+ splitsmith ui --project ~/matches/your-match
54
53
  ```
55
54
 
56
55
  The repo ships a real Stage 3 audio sample at `tests/fixtures/stage-shots-tallmilan-2026-stage3-s97dcec94.wav` (Tallmilan 2026, 14.74s, 14 audited shots) plus its sibling JSON with ground-truth shot times. The companion source MP4 is gitignored -- bring your own video to exercise the full ingest pipeline.
@@ -76,17 +75,17 @@ The repo ships a real Stage 3 audio sample at `tests/fixtures/stage-shots-tallmi
76
75
 
77
76
  `splitsmith ui` checks for both on first launch and prints a copy-pasteable install hint if they're missing.
78
77
 
79
- ### Option 1: slim wheel (end users, ~100 MB) -- pending first PyPI release
80
-
81
- The shipped install will be `uv tool install splitsmith` once the first release-please release lands on `main` (see [Releases](#releases) below). Detection models (~440 MB total) download from `models.splitsmith.app` on first detection -- pre-fetch with `splitsmith fetch-models`. No torch, transformers, or panns_inference in the install.
78
+ ### Option 1: slim wheel (end users, ~100 MB)
82
79
 
83
80
  ```bash
84
- uv tool install splitsmith # available after the first 0.x.y release; see Option 2 below until then
81
+ uv tool install splitsmith # from PyPI
85
82
  splitsmith fetch-models # pre-fetch ONNX artifacts (optional)
86
83
  splitsmith ui --project ~/matches/your-match
87
84
  ```
88
85
 
89
- ### Option 2: from source (today's recommended path; required for contributors)
86
+ Detection models (~440 MB total) download from `models.splitsmith.app` on first detection -- pre-fetch with `splitsmith fetch-models`. No torch, transformers, or panns_inference in the install.
87
+
88
+ ### Option 2: from source (required for contributors)
90
89
 
91
90
  ```bash
92
91
  git clone https://github.com/mandakan/splitsmith.git
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "splitsmith"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  description = "Extract IPSC shot splits from head-mounted camera footage"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,3 +1,3 @@
1
1
  """splitsmith: extract IPSC shot splits from head-mounted camera footage."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.3.0"
@@ -328,8 +328,7 @@ class ShotRefineConfig(BaseModel):
328
328
  method: Literal["envelope", "aic"] = "envelope"
329
329
  # Half-width of the audio window scanned around each approximate time.
330
330
  # 200 ms covers reverb-anchored cases where the candidate generator
331
- # placed its rise foot 100-200 ms after the true onset (see
332
- # PRECISION_LIMITS.md section 4a).
331
+ # placed its rise foot 100-200 ms after the true onset.
333
332
  search_half_window_ms: float = 200.0
334
333
  # Reject refinements whose confidence falls below this threshold and
335
334
  # keep the original timestamp instead. 0.0 = always accept.
@@ -338,7 +337,7 @@ class ShotRefineConfig(BaseModel):
338
337
  # least this much louder than the local-position peak. Small ratios
339
338
  # (< 2.0) mean the original was already on a peak; tight rise-foot
340
339
  # adjustment is used instead. Mirrors the same heuristic as the
341
- # candidate-time reverb-chain re-anchor (PRECISION_LIMITS section 4a).
340
+ # candidate-time reverb-chain re-anchor.
342
341
  reanchor_ratio: float = 2.0
343
342
  # AIC-only: bandpass before AIC. Muzzle-blast energy concentrates above
344
343
  # ~500 Hz; bandpassing reduces wind/handling noise that can mask the
@@ -1,6 +1,6 @@
1
1
  """Generate Final Cut Pro XML timelines (FCPXML 1.10).
2
2
 
3
- v1 scope (per FIRST_PROMPT.md, fcpxml is intentionally minimal):
3
+ v1 scope (intentionally minimal):
4
4
  - One asset (the trimmed video) + one sequence at the source frame rate.
5
5
  - V1 = ref-clip of the trimmed video.
6
6
  - One ``<marker>`` per shot, frame-aligned, with a descriptive name that
@@ -1,8 +1,7 @@
1
1
  """Production UI package for splitsmith.
2
2
 
3
3
  The UI is a localhost SPA driven by a FastAPI backend that orchestrates the
4
- existing engine modules unchanged. See docs/PRODUCTION_UI.md and issue #11
5
- for the v1 contract.
4
+ existing engine modules unchanged.
6
5
 
7
6
  Sub-packages:
8
7
  - ``project``: Pydantic models for the on-disk match-project layout
@@ -1059,7 +1059,7 @@ class BeepQueueItem(BaseModel):
1059
1059
  beep_time: float | None
1060
1060
  beep_confidence: float | None
1061
1061
  beep_reviewed: bool
1062
- status: Literal["missing", "low_confidence", "unreviewed"]
1062
+ status: Literal["missing", "low_confidence", "unreviewed", "confirmed"]
1063
1063
  alt_candidates: list[BeepQueueAltCandidate]
1064
1064
  # Auto-computed cross-align suggestion for secondaries lives on the
1065
1065
  # shooter's other videos; the SPA fetches them lazily if needed.
@@ -7257,16 +7257,21 @@ def create_app(
7257
7257
  # ----------------------------------------------------------------------
7258
7258
 
7259
7259
  @app.get("/api/match/beep-queue", response_model=BeepQueueResponse)
7260
- def get_beep_queue() -> BeepQueueResponse:
7260
+ def get_beep_queue(include_confirmed: bool = Query(default=False)) -> BeepQueueResponse:
7261
7261
  """Pending beep items across every shooter in the bound match.
7262
7262
 
7263
- Surfaces three states per primary video:
7263
+ Surfaces three pending states per primary video:
7264
7264
  - ``missing``: detector hasn't run or didn't find a beep
7265
7265
  - ``low_confidence``: detector found one but below the project's
7266
7266
  auto-trust threshold
7267
7267
  - ``unreviewed``: detector found one above threshold but the
7268
7268
  user hasn't yet listened + approved
7269
7269
 
7270
+ When ``include_confirmed`` is true the response also includes
7271
+ items whose beep has been reviewed, with ``status="confirmed"``.
7272
+ The SPA uses this for the "Show confirmed" toggle so the user
7273
+ can revisit a settled beep without having to clear-and-redo it.
7274
+
7270
7275
  Items are grouped by stage; per-stage shot detection is gated on
7271
7276
  every shooter's primary in that stage being ``beep_reviewed``.
7272
7277
  """
@@ -7320,12 +7325,15 @@ def create_app(
7320
7325
  elif primary.beep_reviewed:
7321
7326
  grp.confirmed += 1
7322
7327
  total_confirmed += 1
7323
- continue
7328
+ if not include_confirmed:
7329
+ continue
7330
+ status = "confirmed"
7324
7331
  elif primary.beep_confidence is not None and primary.beep_confidence < threshold:
7325
7332
  status = "low_confidence"
7326
7333
  else:
7327
7334
  status = "unreviewed"
7328
- total_pending += 1
7335
+ if status != "confirmed":
7336
+ total_pending += 1
7329
7337
  alts = [
7330
7338
  BeepQueueAltCandidate(
7331
7339
  time=cand.time,
@@ -12,6 +12,7 @@ import { Maximize2, Minus, Plus } from "lucide-react";
12
12
 
13
13
  import { MarkerGlyph, type MarkerKind } from "@/components/MarkerGlyph";
14
14
  import { Button } from "@/components/ui/button";
15
+ import { modKeyLabel } from "@/lib/platform";
15
16
  import { cn } from "@/lib/utils";
16
17
 
17
18
  export interface MarkerFilters {
@@ -152,6 +153,7 @@ export function ZoomControls({ zoom, onZoomChange, className }: ZoomControlsProp
152
153
  const next = base / ZOOM_STEP;
153
154
  onZoomChange(next <= MIN_ZOOM ? null : next);
154
155
  };
156
+ const mod = modKeyLabel();
155
157
 
156
158
  return (
157
159
  <div className={cn("inline-flex items-center gap-1", className)} role="group" aria-label="Zoom">
@@ -159,8 +161,8 @@ export function ZoomControls({ zoom, onZoomChange, className }: ZoomControlsProp
159
161
  size="sm"
160
162
  variant="ghost"
161
163
  onClick={zoomOut}
162
- aria-label="Zoom out (Cmd+3)"
163
- title="Zoom out (Cmd+3)"
164
+ aria-label={`Zoom out (${mod}+3)`}
165
+ title={`Zoom out (${mod}+3)`}
164
166
  >
165
167
  <Minus className="size-3" />
166
168
  </Button>
@@ -168,8 +170,8 @@ export function ZoomControls({ zoom, onZoomChange, className }: ZoomControlsProp
168
170
  size="sm"
169
171
  variant="ghost"
170
172
  onClick={() => onZoomChange(null)}
171
- aria-label="Fit waveform (Cmd+2)"
172
- title="Fit waveform (Cmd+2)"
173
+ aria-label={`Fit waveform (${mod}+2)`}
174
+ title={`Fit waveform (${mod}+2)`}
173
175
  aria-pressed={zoom == null}
174
176
  >
175
177
  <Maximize2 className="size-3" />
@@ -178,8 +180,8 @@ export function ZoomControls({ zoom, onZoomChange, className }: ZoomControlsProp
178
180
  size="sm"
179
181
  variant="ghost"
180
182
  onClick={zoomIn}
181
- aria-label="Zoom in (Cmd+1)"
182
- title="Zoom in (Cmd+1)"
183
+ aria-label={`Zoom in (${mod}+1)`}
184
+ title={`Zoom in (${mod}+1)`}
183
185
  >
184
186
  <Plus className="size-3" />
185
187
  </Button>