kinemotion 0.60.0__tar.gz → 0.60.1__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.
Potentially problematic release.
This version of kinemotion might be problematic. Click here for more details.
- {kinemotion-0.60.0 → kinemotion-0.60.1}/CHANGELOG.md +6 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/PKG-INFO +1 -1
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/pyproject.toml +1 -1
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/analysis_api.py +3 -9
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/app/config.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/app/main.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/app.py +8 -22
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/auth.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/database.py +5 -15
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/middleware.py +2 -7
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/models/database.py +3 -9
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/models/responses.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/models/storage.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/routes/health.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/services/analysis_service.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/services/storage_service.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/services/validation.py +1 -2
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/tests/conftest.py +1 -2
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/tests/test_error_handling.py +3 -9
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/tests/test_r2_integration.py +3 -9
- {kinemotion-0.60.0 → kinemotion-0.60.1}/pyproject.toml +1 -1
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cmj/analysis.py +4 -12
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cmj/api.py +5 -15
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cmj/cli.py +9 -25
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cmj/debug_overlay.py +3 -9
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cmj/kinematics.py +11 -31
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cmj/metrics_validator.py +27 -67
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cmj/validation_bounds.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/auto_tuning.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/debug_overlay_utils.py +4 -13
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/determinism.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/filtering.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/pipeline_utils.py +2 -5
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/pose.py +4 -12
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/quality.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/smoothing.py +3 -9
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/validation.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/dropjump/analysis.py +9 -26
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/dropjump/api.py +4 -12
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/dropjump/cli.py +5 -14
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/dropjump/debug_overlay.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/dropjump/kinematics.py +9 -27
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/dropjump/metrics_validator.py +7 -20
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/dropjump/validation_bounds.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cli/test_cmj.py +24 -72
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cli/test_dropjump.py +7 -21
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cmj/test_analysis.py +16 -46
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cmj/test_api.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cmj/test_joint_angles.py +15 -44
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cmj/test_kinematics.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cmj/test_physiological_bounds.py +12 -46
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_cli_utils.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_filtering.py +6 -18
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_pipeline_utils.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_pose.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_quality.py +6 -18
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_smoothing.py +26 -78
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_validation.py +3 -9
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_video_io.py +4 -12
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/dropjump/test_adaptive_threshold.py +3 -9
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/dropjump/test_analysis.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/dropjump/test_api.py +1 -3
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/dropjump/test_contact_detection.py +2 -6
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/dropjump/test_kinematics.py +2 -7
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/dropjump/test_physiological_bounds.py +12 -50
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/dropjump/test_validation_integration.py +3 -9
- {kinemotion-0.60.0 → kinemotion-0.60.1}/uv.lock +1 -1
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/api/api-reference-quick-commands.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/api/cloud-run-cpu-specifications-investigation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/api/supabase-authentication-setup-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/authentication/auth-provider-comparison-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/authentication/auth-providers-comparison-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/authentication/supabase-authentication-quick-start.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/authentication/supabase-authentication-setup-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/authentication/supabase-authentication-technical-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/authentication/supabase-google-oauth-setup-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/authentication/supabase-production-setup-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/authentication/supabase-quick-start-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/biomechanics/camera-angle-empirical-validation-results-45-superior-for-media-pipe.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/biomechanics/camera-perspective-analysis-45deg-vs-lateral.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/biomechanics/cmj-landing-detection-window-validation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/biomechanics/cmj-physiological-bounds-for-validation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/biomechanics/cmj-validation-implementation-complete.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/biomechanics/drop-jump-vs-cmj-key-differences.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/biomechanics/technical-implementation-45deg-perspective-correction.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/codebase/codebase-architecture-overview.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/codebase/validation-architecture-visual-hierarchy-after-refactoring.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/codebase/validation-code-duplication-evidence.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/codebase/validation-module-architecture-analysis.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/codebase/validation-refactoring-complete-architecture-improvement.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/automated-deployment-setup-git-hub-actions-with-workload-identity-federation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/backend-repository-split-migration-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/backend-repository-split-step-by-step-execution-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/cloud-run-security-least-privilege-service-account-setup.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/cors-and-memory-issues-production-debugging-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/current-kinemotion-architecture-correct-deployment-setup.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/frontend-repository-split-migration-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/frontend-repository-split-step-by-step-execution-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/production-deployment-guide-vercel-google-cloud-run.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/quick-deployment-commands-vercel-and-cloud-run.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/deployment/vercel-monorepo-deployment-best-practice.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/athlete-pose3d-and-cross-platform-determinism-investigation-complete.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/athlete-pose3d-final-strategy-accuracy-and-robustness.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/athlete-pose3d-media-pipe-enhancement-plan.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/athlete-pose3d-phase-1-implementation-complete.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/backend-authentication-and-logging-status.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/backend-code-coverage-analysis.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/backend-code-duplication-analysis.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/backend-granular-logging-implementation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/backend-kinemotion-decoupling-strategy.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/backend-sonar-cloud-integration-status.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/basic-memory-naming-hook-analysis.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/ci-caching-issue-investigation-deep-squat-test-failure.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/ci-vs-local-test-failure-investigation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/claude-code-hook-configuration.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/cmj-phase-detection-testing-gap-analysis.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/commit-review-r2-video-storage-migration-fe74d1f.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/comprehensive-timing-instrumentation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/cross-platform-determinism-analysis-final-results.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/database-setup-scripts-complete-implementation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/development-standards-quality-gates.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/drop-jump-detection-complete-fix-all-metrics-within-target.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/drop-jump-detection-failure-analysis-per-video-breakdown.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/drop-jump-fix-drop-start-successful-landing-and-takeoff-remain.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/fast-api-app.py Refactoring Plan - Modular Architecture.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/fast-api-refactoring-completion-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/feature-request-system-configuration.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/follow-up-improvements-to-r2-video-storage-migration.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/frontend-dependencies-analysis-nov-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/google-oauth-setup-script-final-review-production-ready.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/google-oauth-setup-script-review-issues-and-recommendations.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/hook-complete-audit-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/hook-configuration-audit.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/hook-quick-reference.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/i18n-implementation-plan-for-validation-messages.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/keyboard-interrupt-test-suite-failure-analysis.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/model-import-conflict-resolution-fast-api-refactoring.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/non-deterministic-analysis-root-cause-and-solution.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/optimal-timing-implementation-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/p0-p1-p2-test-suite-fixes-final-report.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/pose-detection-baseline-evaluation-results.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/pose-detection-optimization-complete-success-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/pose-detection-parameter-optimization-framework.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/structured-logging-implementation-complete.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/structured-logging-implementation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/supabase-dashboard-navigation-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/supabase-database-integration-setup.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/supabase-documentation-validation-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/test-coverage-asymmetry-analysis-cmj-vs-drop-jump.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/test-coverage-equivalence-achievement-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/test-suite-comprehensive-review-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/test-suite-comprehensive-review-structure-and-gaps.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/test-suite-p0-p1-p2-fixes-complete-report.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/test-suite-p0-p1-p2-fixes-progress-report.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/unused-and-experimental-features-strategy.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/unused-code-detection-prompt-template.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/unused-code-identification-and-decorator-application-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/unused-code-verification-final-pass-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/using-multiple-mcp-reasoning-servers-simultaneously.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/velocity-threshold-empirical-validation-study.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/development/vercel-authentication-options-for-user-id-tracking.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/agent-documentation-standards-update.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/documentation-audit-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/i18n-documentation-cleanup-completed.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/issue-12-mvp-scaffolding-complete.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/issue-12-unblocked-tasks-breakdown.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/issue-12-use-real-metrics-now.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/kinemotion-project-setup-complete.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/kinemotion-supabase-production-configuration.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/mcp-sequential-thinking-alternatives-analysis.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/performance-optimization-pose-tracker-pool-timing-instrumentation-complete.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/project-state-summary-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/specialized-subagents-routing-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/supabase-setup-instructions-for-kinemotion.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/project-management/version-mismatch-analysis-kinemotion-0370-vs-0300.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/research/performance-improvement-analysis-30s-18s.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/strategy/deployment-decision-analysis-for-kinemotion.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/strategy/mvp-feedback-collection-plan.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/strategy/mvp-first-strategic-direction.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/strategy/mvp-validation-checkpoints.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/strategy/pose2sim-migration-evaluation-and-strategy.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/strategy/strategic-priority-tasks-current-roadmap.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.basic-memory/strategy/third-party-auth-providers-with-free-tiers-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/agents/biomechanics-specialist.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/agents/computer-vision-engineer.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/agents/devops-cicd-engineer.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/agents/frontend-developer.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/agents/ml-data-scientist.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/agents/project-manager.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/agents/python-backend-developer.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/agents/qa-test-engineer.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/agents/technical-writer.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.claude/settings.local.json +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.cursor/mcp.json +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.dockerignore +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.envrc +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.gitattributes +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.github/dependabot.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.github/pull_request_template.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.github/workflows/deploy-backend.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.github/workflows/docs.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.github/workflows/release.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.github/workflows/test.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.gitignore +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.mcp.json +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.pre-commit-config.yaml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.readthedocs.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/.gitignore +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/backend-cors-fastapi-middleware-order.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/camera-perspective-validation-study.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/code_style_and_conventions.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/current-project-architecture.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/deployment-checklist-and-known-issues.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/deployment-setup-complete.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/github-project-setup-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/mvp-first-strategy.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/mvp-roadmap-and-priorities.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/project_overview.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/specialist-agents-routing.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/memories/suggested_commands.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.serena/project.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.tool-versions +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/.vercelignore +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/CLAUDE.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/CODE_OF_CONDUCT.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/CONTRIBUTING.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/Dockerfile +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/GEMINI.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/LICENSE +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/SECURITY.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/.coveragerc +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/.dockerignore +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/.env.example +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/Dockerfile +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/docs/fly-deployment.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/docs/implementation-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/docs/setup.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/docs/tests.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/app/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/app/dependencies.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/app/exceptions.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/logging_config.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/models/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/routes/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/routes/analysis.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/routes/database.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/routes/platform.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/services/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/services/video_processor.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/types.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/utils/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/utils/rate_limiter.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/supabase-schema.sql +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/tests/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/tests/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/tests/test_api_endpoints.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/tests/test_health.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/backend/tests/test_validation.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/api/cmj.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/api/core.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/api/dropjump.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/api/overview.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/I18N-README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/agents-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/errors-findings.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/feature-request-system.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/feedback-system-setup.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/i18n-architecture-diagram.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/i18n-cheat-sheet.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/i18n-quick-start-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/i18n-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/i18n-validation-messages-specification.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/supabase-database-setup.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/test-suite-review-december-2025.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/testing-standards.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/testing.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/type-hints.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/validation-plan.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/validation-roadmap.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/development/wallball-norep-detection.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/bulk-processing.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/camera-setup.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/cloud-run-deployment.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/cmj-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/cmj-recording-protocol-es.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/cmj-recording-protocol.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/deployment-checklist.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/local-testing.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/setup-issue-12.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/supabase-setup/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/supabase-setup/quickstart.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/supabase-setup/scripts-reference.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/guides/supabase-setup/setup-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/index.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/quick-start.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/reference/cloud-run-quick-reference.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/reference/json-output-format.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/reference/json-structure-comparison.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/reference/parameters.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/reference/pose-systems.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/paper-downloader/HOW-TO-FIND-DOIS.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/paper-downloader/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/paper-downloader/dois.txt +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/paper-downloader/download.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/paper-downloader/pyproject.toml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/paper-downloader/uv.lock +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/sports-biomechanics-pose-estimation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/MANUAL-DOWNLOAD-GUIDE.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/convert_pdfs.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/athlete-monitoring/2001_Foster_Session-RPE-Training-Monitoring.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/athlete-monitoring/2015_Buchheit_GPS-Accelerometers-Stride-Stiffness.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Flatt_HRV-Recovery-Swimmers.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Saw_Training-Camps-Monitoring.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Ward_Putting-i-in-Team.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2011_Petersen_Nordic-Hamstring-Prevention.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2011_Wilk_Shoulder-GIRD-Baseball-Pitchers.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2012_Hewit_Multidirectional-Leg-Asymmetry.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2015_Ford_Hip-Neuromuscular-Exercise-Valgus.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2015_Mosler_Hip-Groin-Pain-Factors.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2015_Sconce_Nordic-Hamstring-Validity.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2016_Mendez-Villanueva_Hamstring-MRI-Regional.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2016_Read_Youth-Soccer-Injury-Risk.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2017_Mason-Mackay_Ankle-Dorsiflexion-Landing.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2017_Mendiguchia_Hamstring-Treatment-Algorithm.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2018_Balsalobre-Fernandez_Ankle-Dorsiflexion-App.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2018_Bramah_Pathological-Gait-Running-Injuries.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/injury-prevention/2020_Fidai_Fatigue-Knee-Valgus-Youth.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/jump-performance/2011_Harper_10-to-5-Jump-Test.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/jump-performance/2012_Samozino_Optimal-Force-Velocity-Profile.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/jump-performance/2014_Samozino_FV-Imbalance.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/jump-performance/2016_Jimenez-Reyes_Force-Velocity-Training.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/jump-performance/2016_Morin-Samozino_Power-Force-Velocity-Profiles.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/jump-performance/2018_Garcia-Ramos_Two-Point-Method-Optimization.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/jump-performance/2022_Wells_Golf-Clubhead-CMJ.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/running-biomechanics/2005_Morin_Running-Stiffness-Measurement.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/running-biomechanics/2015_Balsalobre-Fernandez_Strength-Training-Running-Economy.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/running-biomechanics/2016_Balsalobre-Fernandez_iPhone-Running-Mechanics.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/running-biomechanics/2016_Moore_Economical-Running-Technique.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/running-biomechanics/2020_Filter_Curve-Sprint-Test-Soccer.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/running-biomechanics/2020_Harper_Horizontal-Deceleration-Radar.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/running-biomechanics/2021_vanOeveren_Running-Biomechanics-Synthesis.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/running-biomechanics/2024_Bramah_Sprint-Mechanics-Assessment-Score.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/smartphone-technology/2015_Balsalobre-Fernandez_iPhone-Vertical-Jump.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/smartphone-technology/2022_Bishop_MyJumpLab-Validation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/velocity-based-training/2011_Jidovtseff_Load-Velocity-1RM-Prediction.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/velocity-based-training/2016_Conceicao_Movement-Velocity-Lower-Limb.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/velocity-based-training/2016_Pareja-Blanco_Velocity-Loss-Training.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/velocity-based-training/2017_Balsalobre-Fernandez_Barbell-Velocity-1RM.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/velocity-based-training/2020_Balsalobre-Fernandez_Barbell-Trajectory-Snatch.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/markdown/velocity-based-training/2023_Balsalobre-Fernandez_AI-Barbell-Velocity.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/online-references-for-papers.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2001_Foster_Session-RPE-Training-Monitoring.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2015_Buchheit_GPS-Accelerometers-Stride-Stiffness.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Flatt_HRV-Recovery-Swimmers.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Saw_Training-Camps-Monitoring.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Ward_Putting-i-in-Team.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2011_Petersen_Nordic-Hamstring-Prevention.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2011_Wilk_Shoulder-GIRD-Baseball-Pitchers.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2012_Hewit_Multidirectional-Leg-Asymmetry.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2015_Ford_Hip-Neuromuscular-Exercise-Valgus.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2015_Mosler_Hip-Groin-Pain-Factors.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2015_Sconce_Nordic-Hamstring-Validity.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2016_Mendez-Villanueva_Hamstring-MRI-Regional.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2016_Read_Youth-Soccer-Injury-Risk.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2017_Mason-Mackay_Ankle-Dorsiflexion-Landing.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2017_Mendiguchia_Hamstring-Treatment-Algorithm.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2018_Balsalobre-Fernandez_Ankle-Dorsiflexion-App.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2018_Bramah_Pathological-Gait-Running-Injuries.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/injury-prevention/2020_Fidai_Fatigue-Knee-Valgus-Youth.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/jump-performance/2011_Harper_10-to-5-Jump-Test.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/jump-performance/2012_Samozino_Optimal-Force-Velocity-Profile.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/jump-performance/2014_Samozino_FV-Imbalance.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/jump-performance/2016_Jimenez-Reyes_Force-Velocity-Training.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/jump-performance/2016_Morin-Samozino_Power-Force-Velocity-Profiles.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/jump-performance/2018_Garcia-Ramos_Two-Point-Method-Optimization.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/jump-performance/2022_Wells_Golf-Clubhead-CMJ.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/running-biomechanics/2005_Morin_Running-Stiffness-Measurement.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/running-biomechanics/2015_Balsalobre-Fernandez_Strength-Training-Running-Economy.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/running-biomechanics/2016_Balsalobre-Fernandez_iPhone-Running-Mechanics.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/running-biomechanics/2016_Moore_Economical-Running-Technique.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/running-biomechanics/2020_Filter_Curve-Sprint-Test-Soccer.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/running-biomechanics/2020_Harper_Horizontal-Deceleration-Radar.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/running-biomechanics/2021_vanOeveren_Running-Biomechanics-Synthesis.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/running-biomechanics/2024_Bramah_Sprint-Mechanics-Assessment-Score.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/smartphone-technology/2015_Balsalobre-Fernandez_iPhone-Vertical-Jump.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/smartphone-technology/2022_Bishop_MyJumpLab-Validation.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/velocity-based-training/2011_Jidovtseff_Load-Velocity-1RM-Prediction.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/velocity-based-training/2016_Conceicao_Movement-Velocity-Lower-Limb.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/velocity-based-training/2016_Pareja-Blanco_Velocity-Loss-Training.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/velocity-based-training/2017_Balsalobre-Fernandez_Barbell-Velocity-1RM.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/velocity-based-training/2020_Balsalobre-Fernandez_Barbell-Trajectory-Snatch.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/research/thirdparty/pdfs/velocity-based-training/2023_Balsalobre-Fernandez_AI-Barbell-Velocity.pdf +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/1-STRATEGIC_SUMMARY.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/2-STRATEGIC_ANALYSIS.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/MVP_FEEDBACK_COLLECTION.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/MVP_VALIDATION_CHECKPOINTS.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/STYLE_GUIDE.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/01-executive-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/02-technical-assessment.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/03-refactoring-roadmap.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/BIOMECHANICS/01-executive-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/BIOMECHANICS/02-technical-assessment.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/BIOMECHANICS/03-reference-guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/BIOMECHANICS/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/COMPUTER_VISION/01-executive-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/COMPUTER_VISION/02-real-time-architecture.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/COMPUTER_VISION/03-implementation-checklist.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/COMPUTER_VISION/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/CONSOLIDATED/01-agent-consensus.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/CONSOLIDATED/02-critical-findings.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/CONSOLIDATED/03-roadmap-adjustments.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/CONSOLIDATED/04-decision-points.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/CONSOLIDATED/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/CONSOLIDATED/risk-register.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/CONSOLIDATED/timeline-roadmap.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/DEVOPS_CI_CD/01-executive-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/DEVOPS_CI_CD/02-infrastructure-assessment.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/DEVOPS_CI_CD/03-implementation-roadmap.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/DEVOPS_CI_CD/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/01-executive-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/02-technical-assessment.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/03-parameter-specifications.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/QA_TESTING/01-executive-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/QA_TESTING/02-roadmap-assessment.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/QA_TESTING/03-testing-checklists.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/QA_TESTING/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/TECHNICAL_WRITING/01-executive-summary.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/TECHNICAL_WRITING/02-documentation-strategy.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/TECHNICAL_WRITING/03-action-plan.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/agent-assessments/TECHNICAL_WRITING/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/strategy/pose2sim-migration-evaluation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/technical/framerate.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/technical/implementation-details.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/technical/imu-metadata.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/technical/real-time-analysis.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/technical/triple-extension.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/translations/es/camera-setup.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/validation/determinism-test.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/validation/known-height-validation.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/docs/validation-status.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/examples/bulk/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/examples/bulk/bulk_processing.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/examples/bulk/simple_example.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/examples/programmatic_usage.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/.editorconfig +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/.env.example +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/.gitattributes +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/.gitignore +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/.yarn/releases/yarn-4.12.0.cjs +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/.yarnrc.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/index.html +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/package.json +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/App.i18n.integration.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/App.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/App.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/Auth.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/Auth.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/ErrorBoundary.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/ErrorBoundary.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/ErrorDisplay.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/FeatureRequestButton.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/FeedbackForm.css +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/FeedbackForm.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/FeedbackForm.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/LanguageSwitcher.css +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/LanguageSwitcher.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/LanguageSwitcher.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/LoadingSpinner.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/LoadingSpinner.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/RecentUploads.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/RecentUploads.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/ResultsDisplay.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/ResultsDisplay.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/ResultsSkeleton.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/UploadForm.test.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/components/UploadForm.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/config/links.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/hooks/useAnalysis.test.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/hooks/useAnalysis.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/hooks/useAuth.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/hooks/useBackendVersion.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/hooks/useDatabaseStatus.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/hooks/useLanguage.test.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/hooks/useLanguage.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/hooks/useRecentUploads.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/i18n/config.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/i18n/locales/en/translation.json +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/i18n/locales/es/translation.json +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/i18n/locales/fr/translation.json +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/index.css +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/lib/supabase.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/main.tsx +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/test/setup.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/types/api.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/src/vite-env.d.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/vercel.json +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/vite.config.ts +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/frontend/yarn.lock +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/justfile +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/local_dev.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/mkdocs.yml +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/.gitignore +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/demos/.gitignore +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/demos/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/demos/api_demo.ipynb +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/demos/batch_processing_demo.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/demos/sample_data/.gitkeep +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/presentation_guide.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/revealjs/.gitignore +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/revealjs/Makefile +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/revealjs/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/revealjs/slides.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/presentation/speaker_script.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/requirements-docs.txt +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/samples/cmjs/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/SCRIPTS_QUICKREF.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/analyze_determinism_variance.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/basic-memory-utils.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/debug_contact_states.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/debug_detection.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/find_unused_features.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/generate_test_data.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/optimize_detection_params.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/plot_cmj_velocities.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/plot_validation_results.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/plot_velocities.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/prepare_ground_truth.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/project/README.md +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/project/add-issue.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/project/batch-set-fields.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/project/helpers.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/project/list.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/project/set-field.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/project/set-status.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/project/summary.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/project.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/setup-github-deploy.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/setup-google-oauth.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/setup-supabase-local.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/setup-supabase-production.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/supabasedb/setup-supabase-database.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/supabasedb/setup_supabase_db.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/test_acceleration_standing.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/test_determinism.sh +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/test_drop_start_debug.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/scripts/validate_known_heights.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/sonar-project.properties +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/api.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cli.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cmj/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/cmj/joint_angles.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/cli_utils.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/experimental.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/formatting.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/metadata.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/timing.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/core/video_io.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/dropjump/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/src/kinemotion/py.typed +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cli/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cli/test_imports.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cmj/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/cmj/test_cli.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/conftest.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_auto_tuning.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_formatting.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_metadata.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/core/test_timing.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/dropjump/__init__.py +0 -0
- {kinemotion-0.60.0 → kinemotion-0.60.1}/tests/dropjump/test_cli.py +0 -0
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
<!-- version list -->
|
|
9
9
|
|
|
10
|
+
## kinemotion-v0.60.1 (2025-12-15)
|
|
11
|
+
|
|
12
|
+
### Fix
|
|
13
|
+
|
|
14
|
+
- prevent auth_duration_ms from polluting non-auth logs
|
|
15
|
+
|
|
10
16
|
## kinemotion-v0.60.0 (2025-12-15)
|
|
11
17
|
|
|
12
18
|
### Feat
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kinemotion
|
|
3
|
-
Version: 0.60.
|
|
3
|
+
Version: 0.60.1
|
|
4
4
|
Summary: Video-based kinematic analysis for athletic performance
|
|
5
5
|
Project-URL: Homepage, https://github.com/feniix/kinemotion
|
|
6
6
|
Project-URL: Repository, https://github.com/feniix/kinemotion
|
|
@@ -118,9 +118,7 @@ async def get_user_analysis_sessions(
|
|
|
118
118
|
)
|
|
119
119
|
|
|
120
120
|
db_client = get_database_client()
|
|
121
|
-
sessions = await db_client.get_user_analysis_sessions(
|
|
122
|
-
user_id=user_id, limit=limit
|
|
123
|
-
)
|
|
121
|
+
sessions = await db_client.get_user_analysis_sessions(user_id=user_id, limit=limit)
|
|
124
122
|
|
|
125
123
|
logger.info(
|
|
126
124
|
"user_analysis_sessions_api_retrieved",
|
|
@@ -164,9 +162,7 @@ async def get_analysis_session(
|
|
|
164
162
|
"""
|
|
165
163
|
try:
|
|
166
164
|
db_client = get_database_client()
|
|
167
|
-
session = await db_client.get_analysis_session(
|
|
168
|
-
session_id=session_id, user_id=user_id
|
|
169
|
-
)
|
|
165
|
+
session = await db_client.get_analysis_session(session_id=session_id, user_id=user_id)
|
|
170
166
|
|
|
171
167
|
if not session:
|
|
172
168
|
raise HTTPException(
|
|
@@ -185,9 +181,7 @@ async def get_analysis_session(
|
|
|
185
181
|
)
|
|
186
182
|
|
|
187
183
|
session_with_feedback = AnalysisSessionWithFeedback(**session)
|
|
188
|
-
session_with_feedback.feedback = [
|
|
189
|
-
CoachFeedbackResponse(**fb) for fb in feedback
|
|
190
|
-
]
|
|
184
|
+
session_with_feedback.feedback = [CoachFeedbackResponse(**fb) for fb in feedback]
|
|
191
185
|
|
|
192
186
|
return session_with_feedback
|
|
193
187
|
|
|
@@ -31,9 +31,7 @@ class Settings:
|
|
|
31
31
|
R2_SECRET_KEY: str = os.getenv("R2_SECRET_KEY", "")
|
|
32
32
|
R2_BUCKET_NAME: str = os.getenv("R2_BUCKET_NAME", "kinemotion")
|
|
33
33
|
R2_PUBLIC_BASE_URL: str = os.getenv("R2_PUBLIC_BASE_URL", "").rstrip("/")
|
|
34
|
-
R2_PRESIGN_EXPIRATION_S: int = int(
|
|
35
|
-
os.getenv("R2_PRESIGN_EXPIRATION_S", "604800")
|
|
36
|
-
) # 7 days
|
|
34
|
+
R2_PRESIGN_EXPIRATION_S: int = int(os.getenv("R2_PRESIGN_EXPIRATION_S", "604800")) # 7 days
|
|
37
35
|
|
|
38
36
|
# Security settings
|
|
39
37
|
TESTING: bool = os.getenv("TESTING", "").lower() == "true"
|
|
@@ -114,18 +114,14 @@ def _add_exception_handlers(app: FastAPI) -> None:
|
|
|
114
114
|
from fastapi import HTTPException, Request
|
|
115
115
|
from fastapi.responses import JSONResponse
|
|
116
116
|
|
|
117
|
-
async def http_exception_handler(
|
|
118
|
-
request: Request, exc: HTTPException
|
|
119
|
-
) -> JSONResponse:
|
|
117
|
+
async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
|
|
120
118
|
"""Handle HTTP exceptions."""
|
|
121
119
|
return JSONResponse(
|
|
122
120
|
status_code=exc.status_code,
|
|
123
121
|
content={"message": exc.detail},
|
|
124
122
|
)
|
|
125
123
|
|
|
126
|
-
async def general_exception_handler(
|
|
127
|
-
request: Request, exc: Exception
|
|
128
|
-
) -> JSONResponse:
|
|
124
|
+
async def general_exception_handler(request: Request, exc: Exception) -> JSONResponse:
|
|
129
125
|
"""Handle general exceptions."""
|
|
130
126
|
logger.error(f"Unhandled exception: {exc}", exc_info=True)
|
|
131
127
|
return JSONResponse(
|
|
@@ -118,9 +118,7 @@ class R2StorageClient:
|
|
|
118
118
|
self.public_base_url = (os.getenv("R2_PUBLIC_BASE_URL") or "").rstrip("/")
|
|
119
119
|
# Fallback: presigned URL expiration seconds (default 7 days, S3 max)
|
|
120
120
|
try:
|
|
121
|
-
self.presign_expiration_s = int(
|
|
122
|
-
os.getenv("R2_PRESIGN_EXPIRATION_S") or "604800"
|
|
123
|
-
)
|
|
121
|
+
self.presign_expiration_s = int(os.getenv("R2_PRESIGN_EXPIRATION_S") or "604800")
|
|
124
122
|
except ValueError:
|
|
125
123
|
self.presign_expiration_s = 604800
|
|
126
124
|
|
|
@@ -171,9 +169,7 @@ class R2StorageClient:
|
|
|
171
169
|
normalized_key = key.lstrip("/")
|
|
172
170
|
if self.public_base_url:
|
|
173
171
|
return f"{self.public_base_url}/{normalized_key}"
|
|
174
|
-
return self.generate_presigned_url(
|
|
175
|
-
normalized_key, expiration=self.presign_expiration_s
|
|
176
|
-
)
|
|
172
|
+
return self.generate_presigned_url(normalized_key, expiration=self.presign_expiration_s)
|
|
177
173
|
|
|
178
174
|
def upload_file(self, local_path: str, remote_key: str) -> str:
|
|
179
175
|
"""Upload file to R2 storage.
|
|
@@ -386,8 +382,7 @@ def _validate_video_file(file: UploadFile) -> None:
|
|
|
386
382
|
file_ext = Path(file.filename).suffix.lower()
|
|
387
383
|
if file_ext not in valid_extensions:
|
|
388
384
|
raise ValueError(
|
|
389
|
-
f"Invalid video format: {file_ext}. "
|
|
390
|
-
f"Supported formats: {', '.join(valid_extensions)}"
|
|
385
|
+
f"Invalid video format: {file_ext}. Supported formats: {', '.join(valid_extensions)}"
|
|
391
386
|
)
|
|
392
387
|
|
|
393
388
|
# Check file size (max 500MB for practical limits)
|
|
@@ -650,9 +645,7 @@ async def analyze_video(
|
|
|
650
645
|
upload_start = time.time()
|
|
651
646
|
r2_video_key = f"videos/{jump_type}/{upload_id}{upload_suffix}"
|
|
652
647
|
try:
|
|
653
|
-
original_video_url = r2_client.upload_file(
|
|
654
|
-
temp_video_path, r2_video_key
|
|
655
|
-
)
|
|
648
|
+
original_video_url = r2_client.upload_file(temp_video_path, r2_video_key)
|
|
656
649
|
upload_duration = time.time() - upload_start
|
|
657
650
|
logger.info(
|
|
658
651
|
"timing_r2_input_video_upload",
|
|
@@ -700,8 +693,7 @@ async def analyze_video(
|
|
|
700
693
|
timing_breakdown = metrics["metadata"]["processing"]["timing_breakdown_ms"]
|
|
701
694
|
# Normalize keys: remove special chars, spaces → underscores, lowercase
|
|
702
695
|
normalized_timings = {
|
|
703
|
-
re.sub(r"[^\w\s]", "", stage).lower().replace(" ", "_")
|
|
704
|
-
+ "_ms": duration
|
|
696
|
+
re.sub(r"[^\w\s]", "", stage).lower().replace(" ", "_") + "_ms": duration
|
|
705
697
|
for stage, duration in timing_breakdown.items()
|
|
706
698
|
}
|
|
707
699
|
# Log each timing stage as a separate event for granular monitoring
|
|
@@ -728,9 +720,7 @@ async def analyze_video(
|
|
|
728
720
|
try:
|
|
729
721
|
results_upload_start = time.time()
|
|
730
722
|
results_json = json.dumps(metrics, indent=2)
|
|
731
|
-
results_url = r2_client.put_object(
|
|
732
|
-
r2_results_key, results_json.encode()
|
|
733
|
-
)
|
|
723
|
+
results_url = r2_client.put_object(r2_results_key, results_json.encode())
|
|
734
724
|
results_upload_duration = time.time() - results_upload_start
|
|
735
725
|
logger.info(
|
|
736
726
|
"timing_r2_results_upload",
|
|
@@ -740,9 +730,7 @@ async def analyze_video(
|
|
|
740
730
|
)
|
|
741
731
|
except OSError as e:
|
|
742
732
|
# Log error but don't fail - results still available in response
|
|
743
|
-
logger.warning(
|
|
744
|
-
"r2_results_upload_failed", error=str(e), key=r2_results_key
|
|
745
|
-
)
|
|
733
|
+
logger.warning("r2_results_upload_failed", error=str(e), key=r2_results_key)
|
|
746
734
|
|
|
747
735
|
# Upload Debug Video if it was created
|
|
748
736
|
if (
|
|
@@ -892,9 +880,7 @@ async def analyze_video(
|
|
|
892
880
|
Path(temp_video_path).unlink()
|
|
893
881
|
logger.debug("temp_file_cleaned", path=temp_video_path)
|
|
894
882
|
except OSError as e:
|
|
895
|
-
logger.warning(
|
|
896
|
-
"temp_file_cleanup_failed", path=temp_video_path, error=str(e)
|
|
897
|
-
)
|
|
883
|
+
logger.warning("temp_file_cleanup_failed", path=temp_video_path, error=str(e))
|
|
898
884
|
|
|
899
885
|
# Clean up temporary debug video file
|
|
900
886
|
if temp_debug_video_path and Path(temp_debug_video_path).exists():
|
|
@@ -110,9 +110,7 @@ class SupabaseAuth:
|
|
|
110
110
|
# Fallback: Verify via Supabase Auth server (works for all projects)
|
|
111
111
|
return self._verify_via_auth_server(token, start_time)
|
|
112
112
|
|
|
113
|
-
def _verify_via_auth_server(
|
|
114
|
-
self, token: str, overall_start_time: float
|
|
115
|
-
) -> dict[str, Any]:
|
|
113
|
+
def _verify_via_auth_server(self, token: str, overall_start_time: float) -> dict[str, Any]:
|
|
116
114
|
"""Verify token by calling Supabase Auth server.
|
|
117
115
|
|
|
118
116
|
This is the recommended fallback for HS256 tokens per Supabase docs.
|
|
@@ -70,9 +70,7 @@ class DatabaseClient:
|
|
|
70
70
|
"upload_id": upload_id,
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
response = (
|
|
74
|
-
self.client.table("analysis_sessions").insert(session_data).execute()
|
|
75
|
-
)
|
|
73
|
+
response = self.client.table("analysis_sessions").insert(session_data).execute()
|
|
76
74
|
|
|
77
75
|
if response.data:
|
|
78
76
|
session_data = response.data[0]
|
|
@@ -140,9 +138,7 @@ class DatabaseClient:
|
|
|
140
138
|
)
|
|
141
139
|
raise
|
|
142
140
|
|
|
143
|
-
async def get_analysis_session(
|
|
144
|
-
self, session_id: str, user_id: str
|
|
145
|
-
) -> dict[str, Any] | None:
|
|
141
|
+
async def get_analysis_session(self, session_id: str, user_id: str) -> dict[str, Any] | None:
|
|
146
142
|
"""Get a specific analysis session.
|
|
147
143
|
|
|
148
144
|
Args:
|
|
@@ -160,9 +156,7 @@ class DatabaseClient:
|
|
|
160
156
|
self.client.table("analysis_sessions")
|
|
161
157
|
.select("*")
|
|
162
158
|
.eq("id", session_id)
|
|
163
|
-
.eq(
|
|
164
|
-
"user_id", user_id
|
|
165
|
-
) # Ensure user can only access their own sessions
|
|
159
|
+
.eq("user_id", user_id) # Ensure user can only access their own sessions
|
|
166
160
|
.single()
|
|
167
161
|
.execute()
|
|
168
162
|
)
|
|
@@ -217,9 +211,7 @@ class DatabaseClient:
|
|
|
217
211
|
"tags": tags or [],
|
|
218
212
|
}
|
|
219
213
|
|
|
220
|
-
response = (
|
|
221
|
-
self.client.table("coach_feedback").insert(feedback_data).execute()
|
|
222
|
-
)
|
|
214
|
+
response = self.client.table("coach_feedback").insert(feedback_data).execute()
|
|
223
215
|
|
|
224
216
|
if response.data:
|
|
225
217
|
feedback_data = response.data[0]
|
|
@@ -246,9 +238,7 @@ class DatabaseClient:
|
|
|
246
238
|
)
|
|
247
239
|
raise
|
|
248
240
|
|
|
249
|
-
async def get_session_feedback(
|
|
250
|
-
self, analysis_session_id: str
|
|
251
|
-
) -> list[dict[str, Any]]:
|
|
241
|
+
async def get_session_feedback(self, analysis_session_id: str) -> list[dict[str, Any]]:
|
|
252
242
|
"""Get all feedback for an analysis session.
|
|
253
243
|
|
|
254
244
|
Args:
|
|
@@ -19,9 +19,7 @@ try:
|
|
|
19
19
|
supabase_auth = SupabaseAuth()
|
|
20
20
|
logger.info("supabase_auth_initialized")
|
|
21
21
|
except ValueError:
|
|
22
|
-
logger.warning(
|
|
23
|
-
"supabase_auth_not_configured", message="Supabase credentials not provided"
|
|
24
|
-
)
|
|
22
|
+
logger.warning("supabase_auth_not_configured", message="Supabase credentials not provided")
|
|
25
23
|
|
|
26
24
|
|
|
27
25
|
class RequestLoggingMiddleware(BaseHTTPMiddleware):
|
|
@@ -62,11 +60,10 @@ class RequestLoggingMiddleware(BaseHTTPMiddleware):
|
|
|
62
60
|
user_email = supabase_auth.get_user_email(token)
|
|
63
61
|
auth_duration_ms = (time.time() - auth_start) * 1000
|
|
64
62
|
|
|
65
|
-
# Bind user info to logging context
|
|
63
|
+
# Bind user info to logging context (auth_duration_ms only in auth event)
|
|
66
64
|
structlog.contextvars.bind_contextvars(
|
|
67
65
|
user_id=user_id,
|
|
68
66
|
user_email=user_email,
|
|
69
|
-
auth_duration_ms=round(auth_duration_ms, 2),
|
|
70
67
|
)
|
|
71
68
|
|
|
72
69
|
# Store in request state for use in endpoints
|
|
@@ -75,8 +72,6 @@ class RequestLoggingMiddleware(BaseHTTPMiddleware):
|
|
|
75
72
|
|
|
76
73
|
logger.info(
|
|
77
74
|
"user_authenticated",
|
|
78
|
-
user_id=user_id,
|
|
79
|
-
email=user_email,
|
|
80
75
|
auth_duration_ms=round(auth_duration_ms, 2),
|
|
81
76
|
)
|
|
82
77
|
except Exception as e:
|
|
@@ -14,15 +14,11 @@ class AnalysisSessionCreate(BaseModel):
|
|
|
14
14
|
quality_preset: str = Field(
|
|
15
15
|
..., description="Analysis quality: 'fast', 'balanced', or 'accurate'"
|
|
16
16
|
)
|
|
17
|
-
original_video_url: str | None = Field(
|
|
18
|
-
None, description="R2 URL for original video"
|
|
19
|
-
)
|
|
17
|
+
original_video_url: str | None = Field(None, description="R2 URL for original video")
|
|
20
18
|
debug_video_url: str | None = Field(None, description="R2 URL for debug video")
|
|
21
19
|
results_json_url: str | None = Field(None, description="R2 URL for results JSON")
|
|
22
20
|
analysis_data: dict[str, Any] = Field(..., description="Analysis results as JSON")
|
|
23
|
-
processing_time_s: float | None = Field(
|
|
24
|
-
None, description="Processing time in seconds"
|
|
25
|
-
)
|
|
21
|
+
processing_time_s: float | None = Field(None, description="Processing time in seconds")
|
|
26
22
|
upload_id: str | None = Field(None, description="Upload ID from analysis system")
|
|
27
23
|
|
|
28
24
|
@field_validator("jump_type")
|
|
@@ -65,9 +61,7 @@ class CoachFeedbackCreate(BaseModel):
|
|
|
65
61
|
analysis_session_id: UUID = Field(..., description="ID of the analysis session")
|
|
66
62
|
notes: str | None = Field(None, description="Coach notes about the analysis")
|
|
67
63
|
rating: int | None = Field(None, ge=1, le=5, description="Rating from 1-5")
|
|
68
|
-
tags: list[str] = Field(
|
|
69
|
-
default_factory=list, description="Tags for categorizing feedback"
|
|
70
|
-
)
|
|
64
|
+
tags: list[str] = Field(default_factory=list, description="Tags for categorizing feedback")
|
|
71
65
|
|
|
72
66
|
@field_validator("rating")
|
|
73
67
|
@classmethod
|
|
@@ -14,9 +14,7 @@ class ValidationIssue(BaseModel):
|
|
|
14
14
|
class ValidationResults(BaseModel):
|
|
15
15
|
"""Validation results from analysis."""
|
|
16
16
|
|
|
17
|
-
status: str = Field(
|
|
18
|
-
..., description="Status: PASS, FAIL, WARNING, or PASS_WITH_WARNINGS"
|
|
19
|
-
)
|
|
17
|
+
status: str = Field(..., description="Status: PASS, FAIL, WARNING, or PASS_WITH_WARNINGS")
|
|
20
18
|
issues: list[ValidationIssue] = Field(
|
|
21
19
|
default_factory=list, description="List of validation issues"
|
|
22
20
|
)
|
|
@@ -26,9 +24,7 @@ class MetricsData(BaseModel):
|
|
|
26
24
|
"""Analysis metrics with optional metadata and validation."""
|
|
27
25
|
|
|
28
26
|
data: dict[str, Any] | None = Field(None, description="Actual metric values")
|
|
29
|
-
metadata: dict[str, Any] | None = Field(
|
|
30
|
-
None, description="Metric metadata and descriptions"
|
|
31
|
-
)
|
|
27
|
+
metadata: dict[str, Any] | None = Field(None, description="Metric metadata and descriptions")
|
|
32
28
|
validation: ValidationResults | None = Field(
|
|
33
29
|
None, description="Validation results for metrics"
|
|
34
30
|
)
|
|
@@ -21,9 +21,7 @@ class R2StorageClient:
|
|
|
21
21
|
self.public_base_url = (os.getenv("R2_PUBLIC_BASE_URL") or "").rstrip("/")
|
|
22
22
|
# Fallback: presigned URL expiration seconds (default 7 days, S3 max)
|
|
23
23
|
try:
|
|
24
|
-
self.presign_expiration_s = int(
|
|
25
|
-
os.getenv("R2_PRESIGN_EXPIRATION_S") or "604800"
|
|
26
|
-
)
|
|
24
|
+
self.presign_expiration_s = int(os.getenv("R2_PRESIGN_EXPIRATION_S") or "604800")
|
|
27
25
|
except ValueError:
|
|
28
26
|
self.presign_expiration_s = 604800
|
|
29
27
|
|
|
@@ -74,9 +72,7 @@ class R2StorageClient:
|
|
|
74
72
|
normalized_key = key.lstrip("/")
|
|
75
73
|
if self.public_base_url:
|
|
76
74
|
return f"{self.public_base_url}/{normalized_key}"
|
|
77
|
-
return self.generate_presigned_url(
|
|
78
|
-
normalized_key, expiration=self.presign_expiration_s
|
|
79
|
-
)
|
|
75
|
+
return self.generate_presigned_url(normalized_key, expiration=self.presign_expiration_s)
|
|
80
76
|
|
|
81
77
|
def upload_file(self, local_path: str, remote_key: str) -> str:
|
|
82
78
|
"""Upload file to R2 storage.
|
|
@@ -19,9 +19,7 @@ async def health_check() -> dict[str, str | bool]:
|
|
|
19
19
|
"""
|
|
20
20
|
# Check R2 configuration
|
|
21
21
|
r2_configured = bool(
|
|
22
|
-
os.getenv("R2_ENDPOINT")
|
|
23
|
-
and os.getenv("R2_ACCESS_KEY")
|
|
24
|
-
and os.getenv("R2_SECRET_KEY")
|
|
22
|
+
os.getenv("R2_ENDPOINT") and os.getenv("R2_ACCESS_KEY") and os.getenv("R2_SECRET_KEY")
|
|
25
23
|
)
|
|
26
24
|
|
|
27
25
|
return {
|
{kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/services/analysis_service.py
RENAMED
|
@@ -110,9 +110,7 @@ class AnalysisService:
|
|
|
110
110
|
temp_debug = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
|
|
111
111
|
temp_debug_video_path = temp_debug.name
|
|
112
112
|
temp_debug.close()
|
|
113
|
-
logger.info(
|
|
114
|
-
"debug_video_path_created", debug_video_path=temp_debug_video_path
|
|
115
|
-
)
|
|
113
|
+
logger.info("debug_video_path_created", debug_video_path=temp_debug_video_path)
|
|
116
114
|
|
|
117
115
|
# Process video with detailed timing
|
|
118
116
|
logger.info("video_processing_started")
|
{kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/services/storage_service.py
RENAMED
|
@@ -24,9 +24,7 @@ class StorageService:
|
|
|
24
24
|
"""
|
|
25
25
|
return self.client.upload_file(local_path, remote_key)
|
|
26
26
|
|
|
27
|
-
async def upload_analysis_results(
|
|
28
|
-
self, results: dict[str, Any], remote_key: str
|
|
29
|
-
) -> str:
|
|
27
|
+
async def upload_analysis_results(self, results: dict[str, Any], remote_key: str) -> str:
|
|
30
28
|
"""Upload analysis results as JSON to R2 storage.
|
|
31
29
|
|
|
32
30
|
Args:
|
|
@@ -41,9 +39,7 @@ class StorageService:
|
|
|
41
39
|
results_json = json.dumps(results, indent=2).encode("utf-8")
|
|
42
40
|
return self.client.put_object(remote_key, results_json)
|
|
43
41
|
|
|
44
|
-
async def generate_unique_key(
|
|
45
|
-
self, filename: str, user_id: str | None = None
|
|
46
|
-
) -> str:
|
|
42
|
+
async def generate_unique_key(self, filename: str, user_id: str | None = None) -> str:
|
|
47
43
|
"""Generate unique storage key for uploaded file.
|
|
48
44
|
|
|
49
45
|
Args:
|
{kinemotion-0.60.0 → kinemotion-0.60.1}/backend/src/kinemotion_backend/services/validation.py
RENAMED
|
@@ -21,8 +21,7 @@ def validate_video_file(file: UploadFile) -> None:
|
|
|
21
21
|
file_ext = Path(file.filename).suffix.lower()
|
|
22
22
|
if file_ext not in valid_extensions:
|
|
23
23
|
raise ValueError(
|
|
24
|
-
f"Invalid video format: {file_ext}. "
|
|
25
|
-
f"Supported formats: {', '.join(valid_extensions)}"
|
|
24
|
+
f"Invalid video format: {file_ext}. Supported formats: {', '.join(valid_extensions)}"
|
|
26
25
|
)
|
|
27
26
|
|
|
28
27
|
# Check file size if available (UploadFile.size is often None in test client)
|
|
@@ -97,8 +97,7 @@ def mock_kinemotion_analysis(
|
|
|
97
97
|
"kinemotion_backend.services.storage_service.StorageService.upload_video"
|
|
98
98
|
)
|
|
99
99
|
upload_results_patch = (
|
|
100
|
-
"kinemotion_backend.services.storage_service."
|
|
101
|
-
"StorageService.upload_analysis_results"
|
|
100
|
+
"kinemotion_backend.services.storage_service.StorageService.upload_analysis_results"
|
|
102
101
|
)
|
|
103
102
|
with (
|
|
104
103
|
patch(cmj_patch) as mock_cmj,
|
|
@@ -162,15 +162,11 @@ def test_multiple_errors_sequential(
|
|
|
162
162
|
files_valid = {"file": ("test.mp4", BytesIO(sample_video_bytes), "video/mp4")}
|
|
163
163
|
|
|
164
164
|
# First request with invalid file
|
|
165
|
-
response1 = client.post(
|
|
166
|
-
"/api/analyze", files=files_invalid, data={"jump_type": "cmj"}
|
|
167
|
-
)
|
|
165
|
+
response1 = client.post("/api/analyze", files=files_invalid, data={"jump_type": "cmj"})
|
|
168
166
|
assert response1.status_code == 422
|
|
169
167
|
|
|
170
168
|
# Second request with valid file
|
|
171
|
-
response2 = client.post(
|
|
172
|
-
"/api/analyze", files=files_valid, data={"jump_type": "cmj"}
|
|
173
|
-
)
|
|
169
|
+
response2 = client.post("/api/analyze", files=files_valid, data={"jump_type": "cmj"})
|
|
174
170
|
assert response2.status_code == 200
|
|
175
171
|
|
|
176
172
|
|
|
@@ -220,9 +216,7 @@ def test_keyboard_interrupt_returns_500(
|
|
|
220
216
|
cmj_patch = "kinemotion_backend.services.video_processor.process_cmj_video"
|
|
221
217
|
with patch(cmj_patch) as mock_cmj:
|
|
222
218
|
mock_cmj.side_effect = KeyboardInterrupt()
|
|
223
|
-
response = client.post(
|
|
224
|
-
"/api/analyze", files=files, data={"jump_type": "cmj"}
|
|
225
|
-
)
|
|
219
|
+
response = client.post("/api/analyze", files=files, data={"jump_type": "cmj"})
|
|
226
220
|
|
|
227
221
|
assert response.status_code == 500
|
|
228
222
|
except KeyboardInterrupt:
|
|
@@ -154,9 +154,7 @@ def test_r2_upload_file_success() -> None:
|
|
|
154
154
|
with patch("kinemotion_backend.models.storage.boto3.client") as mock_boto3:
|
|
155
155
|
mock_s3 = MagicMock()
|
|
156
156
|
mock_boto3.return_value = mock_s3
|
|
157
|
-
mock_s3.generate_presigned_url.return_value =
|
|
158
|
-
"https://r2.example.com/presigned-url"
|
|
159
|
-
)
|
|
157
|
+
mock_s3.generate_presigned_url.return_value = "https://r2.example.com/presigned-url"
|
|
160
158
|
|
|
161
159
|
client = R2StorageClient()
|
|
162
160
|
url = client.upload_file("/tmp/test.mp4", "videos/test.mp4")
|
|
@@ -252,9 +250,7 @@ def test_get_object_url_with_custom_expiration() -> None:
|
|
|
252
250
|
with patch("kinemotion_backend.models.storage.boto3.client") as mock_boto3:
|
|
253
251
|
mock_s3 = MagicMock()
|
|
254
252
|
mock_boto3.return_value = mock_s3
|
|
255
|
-
mock_s3.generate_presigned_url.return_value =
|
|
256
|
-
"https://r2.example.com/presigned"
|
|
257
|
-
)
|
|
253
|
+
mock_s3.generate_presigned_url.return_value = "https://r2.example.com/presigned"
|
|
258
254
|
|
|
259
255
|
client = R2StorageClient()
|
|
260
256
|
url = client.get_object_url("videos/test.mp4")
|
|
@@ -416,9 +412,7 @@ def test_r2_put_object_success() -> None:
|
|
|
416
412
|
with patch("kinemotion_backend.models.storage.boto3.client") as mock_boto3:
|
|
417
413
|
mock_s3 = MagicMock()
|
|
418
414
|
mock_boto3.return_value = mock_s3
|
|
419
|
-
mock_s3.generate_presigned_url.return_value =
|
|
420
|
-
"https://r2.example.com/presigned-url"
|
|
421
|
-
)
|
|
415
|
+
mock_s3.generate_presigned_url.return_value = "https://r2.example.com/presigned-url"
|
|
422
416
|
|
|
423
417
|
client = R2StorageClient()
|
|
424
418
|
url = client.put_object("results/test.json", b'{"status": "ok"}')
|
|
@@ -216,9 +216,7 @@ def find_cmj_takeoff_from_velocity_peak(
|
|
|
216
216
|
Takeoff frame with fractional precision.
|
|
217
217
|
"""
|
|
218
218
|
concentric_start = int(lowest_point_frame)
|
|
219
|
-
search_duration = int(
|
|
220
|
-
fps * 0.3
|
|
221
|
-
) # Search next 0.3 seconds (concentric to takeoff is brief)
|
|
219
|
+
search_duration = int(fps * 0.3) # Search next 0.3 seconds (concentric to takeoff is brief)
|
|
222
220
|
search_end = min(len(velocities), concentric_start + search_duration)
|
|
223
221
|
|
|
224
222
|
if search_end <= concentric_start:
|
|
@@ -227,9 +225,7 @@ def find_cmj_takeoff_from_velocity_peak(
|
|
|
227
225
|
# Find peak upward velocity (most NEGATIVE velocity)
|
|
228
226
|
# In normalized coords: negative velocity = y decreasing = jumping up
|
|
229
227
|
concentric_velocities = velocities[concentric_start:search_end]
|
|
230
|
-
takeoff_idx = int(
|
|
231
|
-
np.argmin(concentric_velocities)
|
|
232
|
-
) # Most negative = fastest upward = takeoff
|
|
228
|
+
takeoff_idx = int(np.argmin(concentric_velocities)) # Most negative = fastest upward = takeoff
|
|
233
229
|
takeoff_frame = concentric_start + takeoff_idx
|
|
234
230
|
|
|
235
231
|
return float(takeoff_frame)
|
|
@@ -338,9 +334,7 @@ def find_interpolated_takeoff_landing(
|
|
|
338
334
|
return (takeoff_frame, landing_frame)
|
|
339
335
|
|
|
340
336
|
|
|
341
|
-
def find_takeoff_frame(
|
|
342
|
-
velocities: np.ndarray, peak_height_frame: int, fps: float
|
|
343
|
-
) -> float:
|
|
337
|
+
def find_takeoff_frame(velocities: np.ndarray, peak_height_frame: int, fps: float) -> float:
|
|
344
338
|
"""Find takeoff frame as peak upward velocity before peak height.
|
|
345
339
|
|
|
346
340
|
Robust detection: When velocities are nearly identical (flat), detects
|
|
@@ -621,8 +615,6 @@ def detect_cmj_phases(
|
|
|
621
615
|
)
|
|
622
616
|
|
|
623
617
|
with timer.measure("cmj_find_standing_end"):
|
|
624
|
-
standing_end = find_standing_end(
|
|
625
|
-
velocities, lowest_point, positions, accelerations
|
|
626
|
-
)
|
|
618
|
+
standing_end = find_standing_end(velocities, lowest_point, positions, accelerations)
|
|
627
619
|
|
|
628
620
|
return (standing_end, lowest_point, takeoff_frame, landing_frame)
|
|
@@ -91,9 +91,7 @@ def _generate_debug_video(
|
|
|
91
91
|
timer=timer,
|
|
92
92
|
) as renderer:
|
|
93
93
|
for frame, idx in zip(frames, frame_indices, strict=True):
|
|
94
|
-
annotated = renderer.render_frame(
|
|
95
|
-
frame, smoothed_landmarks[idx], idx, metrics
|
|
96
|
-
)
|
|
94
|
+
annotated = renderer.render_frame(frame, smoothed_landmarks[idx], idx, metrics)
|
|
97
95
|
renderer.write_frame(annotated)
|
|
98
96
|
|
|
99
97
|
if verbose:
|
|
@@ -142,9 +140,7 @@ def _print_quality_warnings(quality_result: QualityAssessment, verbose: bool) ->
|
|
|
142
140
|
print()
|
|
143
141
|
|
|
144
142
|
|
|
145
|
-
def _print_validation_results(
|
|
146
|
-
validation_result: ValidationResult, verbose: bool
|
|
147
|
-
) -> None:
|
|
143
|
+
def _print_validation_results(validation_result: ValidationResult, verbose: bool) -> None:
|
|
148
144
|
"""Print validation issues if present."""
|
|
149
145
|
if verbose and validation_result.issues:
|
|
150
146
|
print("\n⚠️ Validation Results:")
|
|
@@ -327,13 +323,9 @@ def process_cmj_video(
|
|
|
327
323
|
)
|
|
328
324
|
|
|
329
325
|
if verbose:
|
|
330
|
-
print_verbose_parameters(
|
|
331
|
-
video, characteristics, quality_preset, params
|
|
332
|
-
)
|
|
326
|
+
print_verbose_parameters(video, characteristics, quality_preset, params)
|
|
333
327
|
|
|
334
|
-
smoothed_landmarks = apply_smoothing(
|
|
335
|
-
landmarks_sequence, params, verbose, timer
|
|
336
|
-
)
|
|
328
|
+
smoothed_landmarks = apply_smoothing(landmarks_sequence, params, verbose, timer)
|
|
337
329
|
|
|
338
330
|
if verbose:
|
|
339
331
|
print("Extracting vertical positions (Hip and Foot)...")
|
|
@@ -341,9 +333,7 @@ def process_cmj_video(
|
|
|
341
333
|
vertical_positions, visibilities = extract_vertical_positions(
|
|
342
334
|
smoothed_landmarks, target="hip"
|
|
343
335
|
)
|
|
344
|
-
foot_positions, _ = extract_vertical_positions(
|
|
345
|
-
smoothed_landmarks, target="foot"
|
|
346
|
-
)
|
|
336
|
+
foot_positions, _ = extract_vertical_positions(smoothed_landmarks, target="foot")
|
|
347
337
|
|
|
348
338
|
if verbose:
|
|
349
339
|
print("Detecting CMJ phases...")
|
|
@@ -49,12 +49,8 @@ def _process_batch_videos(
|
|
|
49
49
|
for video in video_files:
|
|
50
50
|
try:
|
|
51
51
|
click.echo(f"\nProcessing: {video}", err=True)
|
|
52
|
-
out_path, json_path = generate_batch_output_paths(
|
|
53
|
-
|
|
54
|
-
)
|
|
55
|
-
_process_single(
|
|
56
|
-
video, out_path, json_path, quality_preset, verbose, expert_params
|
|
57
|
-
)
|
|
52
|
+
out_path, json_path = generate_batch_output_paths(video, output_dir, json_output_dir)
|
|
53
|
+
_process_single(video, out_path, json_path, quality_preset, verbose, expert_params)
|
|
58
54
|
except Exception as e:
|
|
59
55
|
click.echo(f"Error processing {video}: {e}", err=True)
|
|
60
56
|
continue
|
|
@@ -311,30 +307,18 @@ def _output_results(metrics: CMJMetrics, json_output: str | None) -> None:
|
|
|
311
307
|
click.echo("=" * 60, err=True)
|
|
312
308
|
click.echo(f"Jump height: {metrics.jump_height:.3f} m", err=True)
|
|
313
309
|
click.echo(f"Flight time: {metrics.flight_time * 1000:.1f} ms", err=True)
|
|
310
|
+
click.echo(f"Countermovement depth: {metrics.countermovement_depth:.3f} m", err=True)
|
|
311
|
+
click.echo(f"Eccentric duration: {metrics.eccentric_duration * 1000:.1f} ms", err=True)
|
|
312
|
+
click.echo(f"Concentric duration: {metrics.concentric_duration * 1000:.1f} ms", err=True)
|
|
313
|
+
click.echo(f"Total movement time: {metrics.total_movement_time * 1000:.1f} ms", err=True)
|
|
314
314
|
click.echo(
|
|
315
|
-
f"
|
|
316
|
-
)
|
|
317
|
-
click.echo(
|
|
318
|
-
f"Eccentric duration: {metrics.eccentric_duration * 1000:.1f} ms", err=True
|
|
319
|
-
)
|
|
320
|
-
click.echo(
|
|
321
|
-
f"Concentric duration: {metrics.concentric_duration * 1000:.1f} ms", err=True
|
|
322
|
-
)
|
|
323
|
-
click.echo(
|
|
324
|
-
f"Total movement time: {metrics.total_movement_time * 1000:.1f} ms", err=True
|
|
325
|
-
)
|
|
326
|
-
click.echo(
|
|
327
|
-
f"Peak eccentric velocity: {abs(metrics.peak_eccentric_velocity):.3f} "
|
|
328
|
-
"m/s (downward)",
|
|
315
|
+
f"Peak eccentric velocity: {abs(metrics.peak_eccentric_velocity):.3f} m/s (downward)",
|
|
329
316
|
err=True,
|
|
330
317
|
)
|
|
331
318
|
click.echo(
|
|
332
|
-
f"Peak concentric velocity: {metrics.peak_concentric_velocity:.3f} "
|
|
333
|
-
"m/s (upward)",
|
|
319
|
+
f"Peak concentric velocity: {metrics.peak_concentric_velocity:.3f} m/s (upward)",
|
|
334
320
|
err=True,
|
|
335
321
|
)
|
|
336
322
|
if metrics.transition_time is not None:
|
|
337
|
-
click.echo(
|
|
338
|
-
f"Transition time: {metrics.transition_time * 1000:.1f} ms", err=True
|
|
339
|
-
)
|
|
323
|
+
click.echo(f"Transition time: {metrics.transition_time * 1000:.1f} ms", err=True)
|
|
340
324
|
click.echo("=" * 60, err=True)
|