kinemotion 0.38.1__tar.gz → 0.39.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.
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/settings.local.json +1 -15
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.cursor/mcp.json +5 -2
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/workflows/deploy-backend.yml +1 -1
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.mcp.json +5 -2
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/project.yml +1 -1
- {kinemotion-0.38.1 → kinemotion-0.39.1}/CHANGELOG.md +49 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/CLAUDE.md +0 -72
- {kinemotion-0.38.1 → kinemotion-0.39.1}/GEMINI.md +45 -18
- {kinemotion-0.38.1 → kinemotion-0.39.1}/PKG-INFO +1 -1
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/src/kinemotion_backend/app.py +104 -17
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/tests/test_r2_integration.py +26 -4
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/App.tsx +1 -1
- kinemotion-0.39.1/frontend/src/components/ResultsDisplay.tsx +237 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/hooks/useAnalysis.ts +6 -3
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/hooks/useAuth.ts +44 -0
- kinemotion-0.39.1/frontend/src/index.css +623 -0
- kinemotion-0.39.1/frontend/src/lib/supabase.ts +20 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/types/api.ts +1 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/vite.config.ts +4 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/pyproject.toml +1 -1
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/api.py +34 -9
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/cmj/analysis.py +105 -23
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/cmj/kinematics.py +39 -6
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/debug_overlay_utils.py +91 -15
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/dropjump/analysis.py +6 -24
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/dropjump/kinematics.py +16 -1
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/dropjump/metrics_validator.py +1 -1
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cmj/test_analysis.py +2 -1
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cmj/test_kinematics.py +58 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/dropjump/test_kinematics.py +43 -1
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/dropjump/test_validation_integration.py +5 -2
- {kinemotion-0.38.1 → kinemotion-0.39.1}/uv.lock +1 -1
- kinemotion-0.38.1/.claude/hooks/fix-basic-memory-names.sh +0 -116
- kinemotion-0.38.1/frontend/src/components/ResultsDisplay.tsx +0 -165
- kinemotion-0.38.1/frontend/src/index.css +0 -1119
- kinemotion-0.38.1/frontend/src/lib/supabase.ts +0 -16
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/api/api-reference-quick-commands.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/api/supabase-authentication-setup-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/authentication/auth-provider-comparison-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/authentication/auth-providers-comparison-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/authentication/supabase-authentication-quick-start.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/authentication/supabase-authentication-setup-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/authentication/supabase-authentication-technical-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/authentication/supabase-google-oauth-setup-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/authentication/supabase-production-setup-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/authentication/supabase-quick-start-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/biomechanics/camera-angle-empirical-validation-results-45-superior-for-media-pipe.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/biomechanics/camera-perspective-analysis-45deg-vs-lateral.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/biomechanics/cmj-landing-detection-window-validation.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/biomechanics/cmj-physiological-bounds-for-validation.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/biomechanics/cmj-validation-implementation-complete.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/biomechanics/drop-jump-vs-cmj-key-differences.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/biomechanics/technical-implementation-45deg-perspective-correction.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/codebase/codebase-architecture-overview.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/codebase/validation-architecture-visual-hierarchy-after-refactoring.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/codebase/validation-code-duplication-evidence.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/codebase/validation-module-architecture-analysis.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/codebase/validation-refactoring-complete-architecture-improvement.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/automated-deployment-setup-git-hub-actions-with-workload-identity-federation.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/backend-repository-split-migration-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/backend-repository-split-step-by-step-execution-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/cloud-run-security-least-privilege-service-account-setup.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/cors-and-memory-issues-production-debugging-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/current-kinemotion-architecture-correct-deployment-setup.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/frontend-repository-split-migration-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/frontend-repository-split-step-by-step-execution-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/production-deployment-guide-vercel-google-cloud-run.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/quick-deployment-commands-vercel-and-cloud-run.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/deployment/vercel-monorepo-deployment-best-practice.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/athlete-pose3d-and-cross-platform-determinism-investigation-complete.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/athlete-pose3d-final-strategy-accuracy-and-robustness.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/athlete-pose3d-media-pipe-enhancement-plan.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/athlete-pose3d-phase-1-implementation-complete.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/backend-authentication-and-logging-status.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/backend-code-coverage-analysis.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/backend-code-duplication-analysis.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/backend-kinemotion-decoupling-strategy.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/backend-sonar-cloud-integration-status.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/basic-memory-naming-hook-analysis.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/ci-caching-issue-investigation-deep-squat-test-failure.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/ci-vs-local-test-failure-investigation.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/claude-code-hook-configuration.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/cmj-phase-detection-testing-gap-analysis.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/cross-platform-determinism-analysis-final-results.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/development-standards-quality-gates.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/drop-jump-detection-complete-fix-all-metrics-within-target.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/drop-jump-detection-failure-analysis-per-video-breakdown.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/drop-jump-fix-drop-start-successful-landing-and-takeoff-remain.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/frontend-dependencies-analysis-nov-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/google-oauth-setup-script-final-review-production-ready.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/google-oauth-setup-script-review-issues-and-recommendations.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/hook-complete-audit-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/hook-configuration-audit.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/hook-quick-reference.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/keyboard-interrupt-test-suite-failure-analysis.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/non-deterministic-analysis-root-cause-and-solution.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/p0-p1-p2-test-suite-fixes-final-report.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/pose-detection-baseline-evaluation-results.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/pose-detection-optimization-complete-success-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/pose-detection-parameter-optimization-framework.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/structured-logging-implementation-complete.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/structured-logging-implementation.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/supabase-dashboard-navigation-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/test-coverage-asymmetry-analysis-cmj-vs-drop-jump.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/test-coverage-equivalence-achievement-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/test-suite-comprehensive-review-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/test-suite-comprehensive-review-structure-and-gaps.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/test-suite-p0-p1-p2-fixes-complete-report.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/test-suite-p0-p1-p2-fixes-progress-report.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/unused-and-experimental-features-strategy.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/unused-code-detection-prompt-template.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/unused-code-identification-and-decorator-application-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/unused-code-verification-final-pass-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/using-multiple-mcp-reasoning-servers-simultaneously.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/velocity-threshold-empirical-validation-study.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/development/vercel-authentication-options-for-user-id-tracking.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/documentation-audit-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/issue-12-mvp-scaffolding-complete.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/issue-12-unblocked-tasks-breakdown.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/issue-12-use-real-metrics-now.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/kinemotion-project-setup-complete.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/kinemotion-supabase-production-configuration.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/mcp-sequential-thinking-alternatives-analysis.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/project-state-summary-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/specialized-subagents-routing-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/supabase-setup-instructions-for-kinemotion.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/project-management/version-mismatch-analysis-kinemotion-0370-vs-0300.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/strategy/deployment-decision-analysis-for-kinemotion.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/strategy/mvp-feedback-collection-plan.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/strategy/mvp-first-strategic-direction.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/strategy/mvp-validation-checkpoints.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/strategy/pose2sim-migration-evaluation-and-strategy.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/strategy/strategic-priority-tasks-current-roadmap.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.basic-memory/strategy/third-party-auth-providers-with-free-tiers-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/agents/biomechanics-specialist.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/agents/computer-vision-engineer.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/agents/devops-cicd-engineer.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/agents/frontend-developer.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/agents/ml-data-scientist.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/agents/project-manager.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/agents/python-backend-developer.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/agents/qa-test-engineer.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.claude/agents/technical-writer.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.dockerignore +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.gitattributes +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/dependabot.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/pull_request_template.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/workflows/docs.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/workflows/release.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/workflows/security.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.github/workflows/test.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.gitignore +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.pre-commit-config.yaml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.readthedocs.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/.gitignore +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/backend-cors-fastapi-middleware-order.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/camera-perspective-validation-study.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/code_style_and_conventions.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/current-project-architecture.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/deployment-checklist-and-known-issues.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/deployment-setup-complete.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/github-project-setup-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/mvp-first-strategy.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/mvp-roadmap-and-priorities.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/project_overview.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/specialist-agents-routing.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.serena/memories/suggested_commands.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.tool-versions +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/.vercelignore +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/CODE_OF_CONDUCT.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/CONTRIBUTING.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/Dockerfile +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/LICENSE +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/SECURITY.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/.dockerignore +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/.env.example +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/Dockerfile +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/docs/fly-deployment.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/docs/implementation-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/docs/setup.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/docs/tests.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/pyproject.toml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/src/kinemotion_backend/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/src/kinemotion_backend/auth.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/src/kinemotion_backend/logging_config.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/src/kinemotion_backend/middleware.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/tests/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/tests/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/tests/conftest.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/tests/test_api_endpoints.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/tests/test_error_handling.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/tests/test_health.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/backend/tests/test_validation.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/api/cmj.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/api/core.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/api/dropjump.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/api/overview.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/development/agents-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/development/errors-findings.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/development/test-suite-review-december-2025.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/development/testing-standards.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/development/testing.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/development/type-hints.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/development/validation-plan.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/development/validation-roadmap.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/development/wallball-norep-detection.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/guides/bulk-processing.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/guides/camera-setup.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/guides/cloud-run-deployment.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/guides/cmj-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/guides/cmj-recording-protocol-es.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/guides/cmj-recording-protocol.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/guides/deployment-checklist.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/guides/local-testing.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/guides/setup-issue-12.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/index.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/quick-start.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/reference/cloud-run-quick-reference.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/reference/json-output-format.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/reference/json-structure-comparison.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/reference/parameters.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/reference/pose-systems.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/paper-downloader/HOW-TO-FIND-DOIS.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/paper-downloader/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/paper-downloader/dois.txt +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/paper-downloader/download.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/paper-downloader/pyproject.toml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/paper-downloader/uv.lock +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/sports-biomechanics-pose-estimation.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/MANUAL-DOWNLOAD-GUIDE.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/convert_pdfs.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/athlete-monitoring/2001_Foster_Session-RPE-Training-Monitoring.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/athlete-monitoring/2015_Buchheit_GPS-Accelerometers-Stride-Stiffness.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Flatt_HRV-Recovery-Swimmers.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Saw_Training-Camps-Monitoring.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Ward_Putting-i-in-Team.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2011_Petersen_Nordic-Hamstring-Prevention.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2011_Wilk_Shoulder-GIRD-Baseball-Pitchers.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2012_Hewit_Multidirectional-Leg-Asymmetry.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2015_Ford_Hip-Neuromuscular-Exercise-Valgus.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2015_Mosler_Hip-Groin-Pain-Factors.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2015_Sconce_Nordic-Hamstring-Validity.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2016_Mendez-Villanueva_Hamstring-MRI-Regional.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2016_Read_Youth-Soccer-Injury-Risk.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2017_Mason-Mackay_Ankle-Dorsiflexion-Landing.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2017_Mendiguchia_Hamstring-Treatment-Algorithm.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2018_Balsalobre-Fernandez_Ankle-Dorsiflexion-App.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2018_Bramah_Pathological-Gait-Running-Injuries.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/injury-prevention/2020_Fidai_Fatigue-Knee-Valgus-Youth.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/jump-performance/2011_Harper_10-to-5-Jump-Test.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/jump-performance/2012_Samozino_Optimal-Force-Velocity-Profile.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/jump-performance/2014_Samozino_FV-Imbalance.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/jump-performance/2016_Jimenez-Reyes_Force-Velocity-Training.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/jump-performance/2016_Morin-Samozino_Power-Force-Velocity-Profiles.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/jump-performance/2018_Garcia-Ramos_Two-Point-Method-Optimization.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/jump-performance/2022_Wells_Golf-Clubhead-CMJ.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/running-biomechanics/2005_Morin_Running-Stiffness-Measurement.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/running-biomechanics/2015_Balsalobre-Fernandez_Strength-Training-Running-Economy.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/running-biomechanics/2016_Balsalobre-Fernandez_iPhone-Running-Mechanics.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/running-biomechanics/2016_Moore_Economical-Running-Technique.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/running-biomechanics/2020_Filter_Curve-Sprint-Test-Soccer.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/running-biomechanics/2020_Harper_Horizontal-Deceleration-Radar.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/running-biomechanics/2021_vanOeveren_Running-Biomechanics-Synthesis.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/running-biomechanics/2024_Bramah_Sprint-Mechanics-Assessment-Score.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/smartphone-technology/2015_Balsalobre-Fernandez_iPhone-Vertical-Jump.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/smartphone-technology/2022_Bishop_MyJumpLab-Validation.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/velocity-based-training/2011_Jidovtseff_Load-Velocity-1RM-Prediction.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/velocity-based-training/2016_Conceicao_Movement-Velocity-Lower-Limb.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/velocity-based-training/2016_Pareja-Blanco_Velocity-Loss-Training.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/velocity-based-training/2017_Balsalobre-Fernandez_Barbell-Velocity-1RM.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/velocity-based-training/2020_Balsalobre-Fernandez_Barbell-Trajectory-Snatch.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/markdown/velocity-based-training/2023_Balsalobre-Fernandez_AI-Barbell-Velocity.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/online-references-for-papers.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2001_Foster_Session-RPE-Training-Monitoring.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2015_Buchheit_GPS-Accelerometers-Stride-Stiffness.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Flatt_HRV-Recovery-Swimmers.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Saw_Training-Camps-Monitoring.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Ward_Putting-i-in-Team.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2011_Petersen_Nordic-Hamstring-Prevention.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2011_Wilk_Shoulder-GIRD-Baseball-Pitchers.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2012_Hewit_Multidirectional-Leg-Asymmetry.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2015_Ford_Hip-Neuromuscular-Exercise-Valgus.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2015_Mosler_Hip-Groin-Pain-Factors.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2015_Sconce_Nordic-Hamstring-Validity.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2016_Mendez-Villanueva_Hamstring-MRI-Regional.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2016_Read_Youth-Soccer-Injury-Risk.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2017_Mason-Mackay_Ankle-Dorsiflexion-Landing.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2017_Mendiguchia_Hamstring-Treatment-Algorithm.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2018_Balsalobre-Fernandez_Ankle-Dorsiflexion-App.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2018_Bramah_Pathological-Gait-Running-Injuries.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/injury-prevention/2020_Fidai_Fatigue-Knee-Valgus-Youth.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/jump-performance/2011_Harper_10-to-5-Jump-Test.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/jump-performance/2012_Samozino_Optimal-Force-Velocity-Profile.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/jump-performance/2014_Samozino_FV-Imbalance.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/jump-performance/2016_Jimenez-Reyes_Force-Velocity-Training.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/jump-performance/2016_Morin-Samozino_Power-Force-Velocity-Profiles.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/jump-performance/2018_Garcia-Ramos_Two-Point-Method-Optimization.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/jump-performance/2022_Wells_Golf-Clubhead-CMJ.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/running-biomechanics/2005_Morin_Running-Stiffness-Measurement.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/running-biomechanics/2015_Balsalobre-Fernandez_Strength-Training-Running-Economy.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/running-biomechanics/2016_Balsalobre-Fernandez_iPhone-Running-Mechanics.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/running-biomechanics/2016_Moore_Economical-Running-Technique.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/running-biomechanics/2020_Filter_Curve-Sprint-Test-Soccer.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/running-biomechanics/2020_Harper_Horizontal-Deceleration-Radar.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/running-biomechanics/2021_vanOeveren_Running-Biomechanics-Synthesis.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/running-biomechanics/2024_Bramah_Sprint-Mechanics-Assessment-Score.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/smartphone-technology/2015_Balsalobre-Fernandez_iPhone-Vertical-Jump.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/smartphone-technology/2022_Bishop_MyJumpLab-Validation.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/velocity-based-training/2011_Jidovtseff_Load-Velocity-1RM-Prediction.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/velocity-based-training/2016_Conceicao_Movement-Velocity-Lower-Limb.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/velocity-based-training/2016_Pareja-Blanco_Velocity-Loss-Training.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/velocity-based-training/2017_Balsalobre-Fernandez_Barbell-Velocity-1RM.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/velocity-based-training/2020_Balsalobre-Fernandez_Barbell-Trajectory-Snatch.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/research/thirdparty/pdfs/velocity-based-training/2023_Balsalobre-Fernandez_AI-Barbell-Velocity.pdf +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/1-STRATEGIC_SUMMARY.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/2-STRATEGIC_ANALYSIS.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/MVP_FEEDBACK_COLLECTION.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/MVP_VALIDATION_CHECKPOINTS.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/STYLE_GUIDE.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/01-executive-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/02-technical-assessment.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/03-refactoring-roadmap.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/BIOMECHANICS/01-executive-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/BIOMECHANICS/02-technical-assessment.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/BIOMECHANICS/03-reference-guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/BIOMECHANICS/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/COMPUTER_VISION/01-executive-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/COMPUTER_VISION/02-real-time-architecture.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/COMPUTER_VISION/03-implementation-checklist.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/COMPUTER_VISION/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/CONSOLIDATED/01-agent-consensus.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/CONSOLIDATED/02-critical-findings.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/CONSOLIDATED/03-roadmap-adjustments.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/CONSOLIDATED/04-decision-points.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/CONSOLIDATED/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/CONSOLIDATED/risk-register.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/CONSOLIDATED/timeline-roadmap.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/DEVOPS_CI_CD/01-executive-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/DEVOPS_CI_CD/02-infrastructure-assessment.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/DEVOPS_CI_CD/03-implementation-roadmap.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/DEVOPS_CI_CD/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/01-executive-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/02-technical-assessment.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/03-parameter-specifications.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/QA_TESTING/01-executive-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/QA_TESTING/02-roadmap-assessment.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/QA_TESTING/03-testing-checklists.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/QA_TESTING/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/TECHNICAL_WRITING/01-executive-summary.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/TECHNICAL_WRITING/02-documentation-strategy.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/TECHNICAL_WRITING/03-action-plan.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/agent-assessments/TECHNICAL_WRITING/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/strategy/pose2sim-migration-evaluation.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/technical/framerate.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/technical/implementation-details.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/technical/imu-metadata.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/technical/real-time-analysis.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/technical/triple-extension.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/translations/es/camera-setup.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/validation/determinism-test.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/validation/known-height-validation.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/docs/validation-status.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/examples/bulk/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/examples/bulk/bulk_processing.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/examples/bulk/simple_example.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/examples/programmatic_usage.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/.editorconfig +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/.env.example +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/.gitattributes +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/.gitignore +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/.yarn/releases/yarn-4.12.0.cjs +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/.yarnrc.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/index.html +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/package.json +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/components/Auth.tsx +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/components/ErrorBoundary.tsx +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/components/ErrorDisplay.tsx +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/components/LoadingSpinner.tsx +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/components/RecentUploads.tsx +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/components/ResultsSkeleton.tsx +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/components/UploadForm.tsx +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/hooks/useBackendVersion.ts +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/hooks/useRecentUploads.ts +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/main.tsx +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/src/vite-env.d.ts +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/vercel.json +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/frontend/yarn.lock +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/justfile +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/local_dev.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/mkdocs.yml +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/.gitignore +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/demos/.gitignore +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/demos/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/demos/api_demo.ipynb +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/demos/batch_processing_demo.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/demos/sample_data/.gitkeep +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/presentation_guide.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/revealjs/.gitignore +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/revealjs/Makefile +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/revealjs/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/revealjs/slides.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/presentation/speaker_script.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/requirements-docs.txt +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/samples/cmjs/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/SCRIPTS_QUICKREF.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/analyze_determinism_variance.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/basic-memory-utils.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/debug_contact_states.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/debug_detection.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/find_unused_features.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/generate_test_data.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/optimize_detection_params.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/plot_cmj_velocities.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/plot_validation_results.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/plot_velocities.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/prepare_ground_truth.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/project/README.md +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/project/add-issue.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/project/batch-set-fields.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/project/helpers.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/project/list.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/project/set-field.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/project/set-status.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/project/summary.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/project.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/setup-github-deploy.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/setup-google-oauth.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/setup-supabase-local.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/setup-supabase-production.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/test_acceleration_standing.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/test_determinism.sh +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/test_drop_start_debug.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/scripts/validate_known_heights.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/sonar-project.properties +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/cli.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/cmj/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/cmj/cli.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/cmj/debug_overlay.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/cmj/joint_angles.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/cmj/metrics_validator.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/cmj/validation_bounds.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/auto_tuning.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/cli_utils.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/determinism.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/experimental.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/filtering.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/formatting.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/metadata.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/pose.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/quality.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/smoothing.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/validation.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/core/video_io.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/dropjump/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/dropjump/cli.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/dropjump/debug_overlay.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/dropjump/validation_bounds.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/src/kinemotion/py.typed +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cli/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cli/test_cmj.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cli/test_dropjump.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cli/test_imports.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cmj/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cmj/test_api.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cmj/test_joint_angles.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/cmj/test_physiological_bounds.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/conftest.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/test_auto_tuning.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/test_filtering.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/test_formatting.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/test_metadata.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/test_pose.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/test_quality.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/test_smoothing.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/test_validation.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/core/test_video_io.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/dropjump/__init__.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/dropjump/test_adaptive_threshold.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/dropjump/test_analysis.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/dropjump/test_api.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/dropjump/test_contact_detection.py +0 -0
- {kinemotion-0.38.1 → kinemotion-0.39.1}/tests/dropjump/test_physiological_bounds.py +0 -0
|
@@ -68,19 +68,5 @@
|
|
|
68
68
|
"WebFetch(domain:www.sonarsource.com)"
|
|
69
69
|
]
|
|
70
70
|
},
|
|
71
|
-
"enableAllProjectMcpServers": true
|
|
72
|
-
"hooks": {
|
|
73
|
-
"UserPromptSubmit": [
|
|
74
|
-
{
|
|
75
|
-
"hooks": [
|
|
76
|
-
{
|
|
77
|
-
"type": "command",
|
|
78
|
-
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/fix-basic-memory-names.sh",
|
|
79
|
-
"timeout": 30000,
|
|
80
|
-
"statusMessage": "Normalizing basic-memory filenames to kebab-case..."
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
}
|
|
71
|
+
"enableAllProjectMcpServers": true
|
|
86
72
|
}
|
|
@@ -134,7 +134,7 @@ jobs:
|
|
|
134
134
|
--allow-unauthenticated
|
|
135
135
|
--service-account=kinemotion-backend-runtime@${{ env.GCP_PROJECT_ID }}.iam.gserviceaccount.com
|
|
136
136
|
--set-env-vars=CORS_ORIGINS=https://kinemotion.vercel.app,JSON_LOGS=true,LOG_LEVEL=INFO
|
|
137
|
-
--set-secrets=SUPABASE_URL=SUPABASE_URL:latest,SUPABASE_ANON_KEY=SUPABASE_ANON_KEY:latest
|
|
137
|
+
--set-secrets=SUPABASE_URL=SUPABASE_URL:latest,SUPABASE_ANON_KEY=SUPABASE_ANON_KEY:latest,R2_ENDPOINT=R2_ENDPOINT:latest,R2_ACCESS_KEY=R2_ACCESS_KEY:latest,R2_SECRET_KEY=R2_SECRET_KEY:latest,R2_BUCKET_NAME=R2_BUCKET_NAME:latest
|
|
138
138
|
|
|
139
139
|
- name: Verify deployment health
|
|
140
140
|
run: |
|
|
@@ -7,6 +7,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
<!-- version list -->
|
|
9
9
|
|
|
10
|
+
## v0.39.1 (2025-12-10)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- Prioritize browser-compatible video codecs
|
|
15
|
+
([`76ea08f`](https://github.com/feniix/kinemotion/commit/76ea08fd6edb3d0e0269b2e05db90a98e99777c1))
|
|
16
|
+
|
|
17
|
+
- Use ffmpeg re-encoding only as a fallback
|
|
18
|
+
([`d55923f`](https://github.com/feniix/kinemotion/commit/d55923f9c09d0d8507519c140b58485eaabb4f86))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## v0.39.0 (2025-12-10)
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
- Proxy the health endpoint to the backend
|
|
26
|
+
([`f1d45d2`](https://github.com/feniix/kinemotion/commit/f1d45d2b194e39f96d43c0462960e80e236a8df9))
|
|
27
|
+
|
|
28
|
+
- Use presigned URLs for R2 storage access
|
|
29
|
+
([`ffd642e`](https://github.com/feniix/kinemotion/commit/ffd642e4c597447f8eee9d4275f48695a7862cf6))
|
|
30
|
+
|
|
31
|
+
- **dropjump**: Use argmin for landing detection in finding acceleration spike
|
|
32
|
+
([`1dd1e1a`](https://github.com/feniix/kinemotion/commit/1dd1e1abff7a3c4aae6675f8aa5f2ddf46de76f6))
|
|
33
|
+
|
|
34
|
+
- **kinematics**: Correct scale and phase detection logic for CMJ/DJ
|
|
35
|
+
([`283b560`](https://github.com/feniix/kinemotion/commit/283b560e69c5785a0d18c5b411e89fedc2a8a7bd))
|
|
36
|
+
|
|
37
|
+
### Chores
|
|
38
|
+
|
|
39
|
+
- Remove basic-memory naming hook and cleanup documentation
|
|
40
|
+
([`b2f41ce`](https://github.com/feniix/kinemotion/commit/b2f41ce5d81a23090d2f60bd1a79451bd363bd77))
|
|
41
|
+
|
|
42
|
+
### Features
|
|
43
|
+
|
|
44
|
+
- Improve frontend
|
|
45
|
+
([`241f2f5`](https://github.com/feniix/kinemotion/commit/241f2f58055c241f9919af70156f5ec586ed249f))
|
|
46
|
+
|
|
47
|
+
- Improve frontend
|
|
48
|
+
([`d6e69f3`](https://github.com/feniix/kinemotion/commit/d6e69f335cf6cee4da8affbab876b858aa04af12))
|
|
49
|
+
|
|
50
|
+
- Integrate Cloudflare R2 storage and debug video overlay
|
|
51
|
+
([`b7b05bd`](https://github.com/feniix/kinemotion/commit/b7b05bd500a26d742d78d1670079fb201af49140))
|
|
52
|
+
|
|
53
|
+
### Testing
|
|
54
|
+
|
|
55
|
+
- Update R2 integration tests
|
|
56
|
+
([`955aa86`](https://github.com/feniix/kinemotion/commit/955aa8610040548635c0f34a931e402825740995))
|
|
57
|
+
|
|
58
|
+
|
|
10
59
|
## v0.38.1 (2025-12-09)
|
|
11
60
|
|
|
12
61
|
### Bug Fixes
|
|
@@ -393,78 +393,6 @@ This project integrates multiple MCP (Model Context Protocol) servers for enhanc
|
|
|
393
393
|
- **Search knowledge**: `search_notes("CMJ triple extension")` to find relevant information
|
|
394
394
|
- **Build conversations**: Call `build_context()` before complex tasks to enhance context
|
|
395
395
|
|
|
396
|
-
#### **Basic Memory Naming Standards**
|
|
397
|
-
|
|
398
|
-
**File Naming Convention: Lowercase Kebab-Case**
|
|
399
|
-
|
|
400
|
-
All Markdown files in `.basic-memory/` must follow lowercase kebab-case naming:
|
|
401
|
-
|
|
402
|
-
```
|
|
403
|
-
✓ GOOD:
|
|
404
|
-
- cmj-physiological-bounds-for-validation.md
|
|
405
|
-
- api-reference-quick-commands.md
|
|
406
|
-
- codebase-architecture-overview.md
|
|
407
|
-
- cmj-phase-detection-testing-gap-analysis.md
|
|
408
|
-
|
|
409
|
-
✗ BAD:
|
|
410
|
-
- CMJ Physiological Bounds for Validation.md (Title Case with spaces)
|
|
411
|
-
- cMJ_validation.md (inconsistent case)
|
|
412
|
-
- API-REFERENCE.md (all caps)
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
**Frontmatter Format**
|
|
416
|
-
|
|
417
|
-
Every note must have proper frontmatter with matching permalink:
|
|
418
|
-
|
|
419
|
-
```markdown
|
|
420
|
-
---
|
|
421
|
-
title: <Human-readable title (can use Title Case)>
|
|
422
|
-
type: note
|
|
423
|
-
permalink: <lowercase-kebab-case-matching-filename>
|
|
424
|
-
tags:
|
|
425
|
-
- tag1
|
|
426
|
-
- tag2
|
|
427
|
-
---
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
**Example:**
|
|
431
|
-
|
|
432
|
-
File: `.basic-memory/biomechanics/cmj-physiological-bounds-for-validation.md`
|
|
433
|
-
|
|
434
|
-
```markdown
|
|
435
|
-
---
|
|
436
|
-
title: CMJ Physiological Bounds for Validation
|
|
437
|
-
type: note
|
|
438
|
-
permalink: biomechanics/cmj-physiological-bounds-for-validation
|
|
439
|
-
tags:
|
|
440
|
-
- cmj
|
|
441
|
-
- validation
|
|
442
|
-
- biomechanics
|
|
443
|
-
---
|
|
444
|
-
|
|
445
|
-
# CMJ Physiological Bounds for Validation
|
|
446
|
-
|
|
447
|
-
Content here...
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
**Folder Organization**
|
|
451
|
-
|
|
452
|
-
- `api/` - API reference and quick commands
|
|
453
|
-
- `biomechanics/` - Jump metrics, RSI, triple extension formulas
|
|
454
|
-
- `codebase/` - Architecture overview, module relationships
|
|
455
|
-
- `development/` - Quality gates, testing standards
|
|
456
|
-
- `project-management/` - Subagent routing, task prioritization
|
|
457
|
-
- `strategy/` - Roadmap and strategic priorities
|
|
458
|
-
|
|
459
|
-
**Why This Matters**
|
|
460
|
-
|
|
461
|
-
- **Consistency**: All files follow the same pattern for easier navigation
|
|
462
|
-
- **URL-friendly**: Kebab-case works in memory:// URLs and permalinks
|
|
463
|
-
- **Searchability**: Predictable naming makes notes easier to find
|
|
464
|
-
- **Tools compatibility**: Works correctly with basic-memory CLI and MCP functions
|
|
465
|
-
|
|
466
|
-
See [.basic-memory/README.md](.basic-memory/README.md) for detailed template and guidelines.
|
|
467
|
-
|
|
468
396
|
#### **exa** - Web Search & Code Context
|
|
469
397
|
- **Purpose**: Real-time web search and code example retrieval
|
|
470
398
|
- **Use Cases**:
|
|
@@ -52,32 +52,53 @@ docs/ # Documentation (PARAMETERS.md is key)
|
|
|
52
52
|
|
|
53
53
|
### Analysis Pipeline
|
|
54
54
|
|
|
55
|
+
#### Drop Jump Analysis
|
|
56
|
+
|
|
55
57
|
1. **Pose Tracking** (`core/pose.py`): Extracts 13 body landmarks per frame using MediaPipe.
|
|
56
|
-
1. **
|
|
57
|
-
1. **
|
|
58
|
-
1. **
|
|
59
|
-
1. **
|
|
60
|
-
1. **
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
1. **Smoothing** (`core/smoothing.py`): Savitzky-Golay filter for noise reduction.
|
|
59
|
+
1. **Contact Detection** (`dropjump/analysis.py`): Velocity-based ground contact detection.
|
|
60
|
+
1. **Sub-Frame Interpolation**: Linear interpolation for precise timing.
|
|
61
|
+
1. **Trajectory Curvature**: Acceleration-based refinement.
|
|
62
|
+
1. **Metrics**: RSI, contact time, jump height.
|
|
63
|
+
|
|
64
|
+
#### CMJ Analysis (`cmj/analysis.py`)
|
|
65
|
+
|
|
66
|
+
1. **Strategy**: Uses a **backward search** algorithm starting from the jump peak.
|
|
67
|
+
1. **Signed Velocity**: Calculates signed velocity (negative=up, positive=down) to distinguish concentric/eccentric phases.
|
|
68
|
+
1. **Phase Detection Sequence**:
|
|
69
|
+
- **Peak Height**: Global minimum y-position.
|
|
70
|
+
- **Takeoff**: Peak *negative* velocity (max upward speed) found by searching backward from peak.
|
|
71
|
+
- **Lowest Point**: Maximum y-position found by searching backward from takeoff.
|
|
72
|
+
- **Landing**: Maximum *positive* acceleration (impact) found by searching forward from peak.
|
|
73
|
+
- **Standing End**: Detected via acceleration thresholds searching backward from lowest point.
|
|
64
74
|
|
|
65
75
|
## Critical Implementation Details
|
|
66
76
|
|
|
67
|
-
### 1. Aspect Ratio
|
|
77
|
+
### 1. Aspect Ratio, Rotation & SAR Handling (`core/video_io.py`)
|
|
78
|
+
|
|
79
|
+
- **CRITICAL**: The tool must preserve the source video's exact aspect ratio and orientation.
|
|
80
|
+
- **FFmpeg/FFprobe**: The `VideoProcessor` class relies on `ffprobe` to extract:
|
|
81
|
+
- **Rotation**: Metadata often ignored by OpenCV (common in mobile videos).
|
|
82
|
+
- **SAR (Sample Aspect Ratio)**: Non-square pixel data.
|
|
83
|
+
- **Fallback**: If `ffprobe` is missing, a warning is issued, and defaults are used.
|
|
84
|
+
- **DO**: Always use `frame.shape[:2]` from an actual read frame for dimensions, not `cv2.CAP_PROP_*`.
|
|
85
|
+
|
|
86
|
+
### 2. Internal Physics Validation (`scripts/validate_known_heights.py`)
|
|
68
87
|
|
|
69
|
-
- **
|
|
70
|
-
- **
|
|
71
|
-
- **
|
|
72
|
-
-
|
|
88
|
+
- **Context**: While clinical validation is pending, the tool undergoes rigorous **internal physics validation**.
|
|
89
|
+
- **Methodology**: Objects are dropped from known heights (0.5m, 1.0m, 1.5m). Measured flight times are compared against theoretical physics predictions ($t = \\sqrt{2h/g}$).
|
|
90
|
+
- **Passing Criteria**:
|
|
91
|
+
- **MAE**: \< 20ms
|
|
92
|
+
- **RMSE**: \< 30ms
|
|
93
|
+
- **Correlation**: > 0.99
|
|
73
94
|
|
|
74
|
-
###
|
|
95
|
+
### 3. Sub-Frame Interpolation & Robust Derivatives (`dropjump/analysis.py`, `core/smoothing.py`)
|
|
75
96
|
|
|
76
97
|
- **CRITICAL**: Timing precision is achieved by interpolating between frames.
|
|
77
|
-
- **Velocity Calculation**: Velocity is computed as the **first derivative of the smoothed position trajectory
|
|
98
|
+
- **Velocity/Acceleration Calculation**: Velocity is computed as the **first derivative** and acceleration as the **second derivative** of the smoothed position trajectory using a Savitzky-Golay filter (`savgol_filter(..., deriv=1)` and `deriv=2`). This approach is highly robust and accurate, minimizing noise amplification compared to simple finite-difference methods.
|
|
78
99
|
- **Interpolation**: When velocity crosses the contact threshold between two frames, linear interpolation is used to find the fractional frame index of the crossing. This improves timing accuracy from ~33ms to ~10ms at 30fps.
|
|
79
100
|
|
|
80
|
-
###
|
|
101
|
+
### 4. Trajectory Curvature Analysis (`dropjump/analysis.py`)
|
|
81
102
|
|
|
82
103
|
- **CRITICAL**: Event timing is further refined using acceleration patterns.
|
|
83
104
|
- **Acceleration Calculation**: Acceleration is the **second derivative of the smoothed position** (`savgol_filter(..., deriv=2)`).
|
|
@@ -86,12 +107,18 @@ docs/ # Documentation (PARAMETERS.md is key)
|
|
|
86
107
|
- **Takeoff**: A sharp change in acceleration.
|
|
87
108
|
- **Blending**: The final transition time is a weighted blend: 70% from the curvature-based estimate and 30% from the velocity-based estimate. This is enabled by default via `--use-curvature`.
|
|
88
109
|
|
|
89
|
-
###
|
|
110
|
+
### 5. Adaptive Velocity Threshold (`dropjump/analysis.py`)
|
|
111
|
+
|
|
112
|
+
- **INSIGHT**: The `calculate_adaptive_threshold` function is implemented but currently *not integrated* into the main analysis pipeline.
|
|
113
|
+
- **PURPOSE**: This feature dynamically adjusts the `velocity_threshold` based on baseline noise characteristics of the video. This can significantly improve robustness across varying camera distances, lighting conditions, and video quality by making contact detection less sensitive to noise and more resilient to false positives/negatives.
|
|
114
|
+
- **STATUS**: Awaiting CLI integration. Its inclusion would enhance the tool's adaptability without manual parameter tuning.
|
|
115
|
+
|
|
116
|
+
### 6. JSON Serialization of NumPy Types (`dropjump/kinematics.py`)
|
|
90
117
|
|
|
91
118
|
- **CRITICAL**: Standard `json.dump` cannot serialize NumPy integer types (e.g., `np.int64`).
|
|
92
119
|
- **DO**: Explicitly cast all NumPy numbers to standard Python types (`int()`, `float()`) within the `to_dict()` methods of data classes before serialization.
|
|
93
120
|
|
|
94
|
-
###
|
|
121
|
+
### 7. OpenCV Frame Dimensions
|
|
95
122
|
|
|
96
123
|
- **CRITICAL**: Be aware of dimension ordering differences.
|
|
97
124
|
- **NumPy `frame.shape`**: `(height, width, channels)`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kinemotion
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.39.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
|
|
@@ -52,6 +52,7 @@ class AnalysisResponse:
|
|
|
52
52
|
message: str,
|
|
53
53
|
metrics: dict[str, Any] | None = None,
|
|
54
54
|
results_url: str | None = None,
|
|
55
|
+
debug_video_url: str | None = None,
|
|
55
56
|
error: str | None = None,
|
|
56
57
|
processing_time_s: float = 0.0,
|
|
57
58
|
):
|
|
@@ -59,6 +60,7 @@ class AnalysisResponse:
|
|
|
59
60
|
self.message = message
|
|
60
61
|
self.metrics = metrics
|
|
61
62
|
self.results_url = results_url
|
|
63
|
+
self.debug_video_url = debug_video_url
|
|
62
64
|
self.error = error
|
|
63
65
|
self.processing_time_s = processing_time_s
|
|
64
66
|
|
|
@@ -76,6 +78,9 @@ class AnalysisResponse:
|
|
|
76
78
|
if self.results_url is not None:
|
|
77
79
|
result["results_url"] = self.results_url
|
|
78
80
|
|
|
81
|
+
if self.debug_video_url is not None:
|
|
82
|
+
result["debug_video_url"] = self.debug_video_url
|
|
83
|
+
|
|
79
84
|
if self.error is not None:
|
|
80
85
|
result["error"] = self.error
|
|
81
86
|
|
|
@@ -110,6 +115,29 @@ class R2StorageClient:
|
|
|
110
115
|
region_name="auto",
|
|
111
116
|
)
|
|
112
117
|
|
|
118
|
+
def generate_presigned_url(self, key: str, expiration: int = 3600) -> str:
|
|
119
|
+
"""Generate presigned URL for object.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
key: Object key
|
|
123
|
+
expiration: Expiration in seconds (default 1 hour)
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Presigned URL string
|
|
127
|
+
|
|
128
|
+
Raises:
|
|
129
|
+
OSError: If generation fails
|
|
130
|
+
"""
|
|
131
|
+
try:
|
|
132
|
+
url = self.client.generate_presigned_url(
|
|
133
|
+
"get_object",
|
|
134
|
+
Params={"Bucket": self.bucket_name, "Key": key},
|
|
135
|
+
ExpiresIn=expiration,
|
|
136
|
+
)
|
|
137
|
+
return cast(str, url)
|
|
138
|
+
except Exception as e:
|
|
139
|
+
raise OSError(f"Failed to generate presigned URL: {str(e)}") from e
|
|
140
|
+
|
|
113
141
|
def upload_file(self, local_path: str, remote_key: str) -> str:
|
|
114
142
|
"""Upload file to R2 storage.
|
|
115
143
|
|
|
@@ -118,14 +146,14 @@ class R2StorageClient:
|
|
|
118
146
|
remote_key: S3 object key in R2 bucket
|
|
119
147
|
|
|
120
148
|
Returns:
|
|
121
|
-
|
|
149
|
+
Presigned URL of uploaded file
|
|
122
150
|
|
|
123
151
|
Raises:
|
|
124
|
-
|
|
152
|
+
OSError: If upload fails
|
|
125
153
|
"""
|
|
126
154
|
try:
|
|
127
155
|
self.client.upload_file(local_path, self.bucket_name, remote_key)
|
|
128
|
-
return
|
|
156
|
+
return self.generate_presigned_url(remote_key)
|
|
129
157
|
except Exception as e:
|
|
130
158
|
raise OSError(f"Failed to upload to R2: {str(e)}") from e
|
|
131
159
|
|
|
@@ -137,7 +165,7 @@ class R2StorageClient:
|
|
|
137
165
|
local_path: Local path to save downloaded file
|
|
138
166
|
|
|
139
167
|
Raises:
|
|
140
|
-
|
|
168
|
+
OSError: If download fails
|
|
141
169
|
"""
|
|
142
170
|
try:
|
|
143
171
|
self.client.download_file(self.bucket_name, remote_key, local_path)
|
|
@@ -151,7 +179,7 @@ class R2StorageClient:
|
|
|
151
179
|
remote_key: S3 object key in R2 bucket
|
|
152
180
|
|
|
153
181
|
Raises:
|
|
154
|
-
|
|
182
|
+
OSError: If deletion fails
|
|
155
183
|
"""
|
|
156
184
|
try:
|
|
157
185
|
self.client.delete_object(Bucket=self.bucket_name, Key=remote_key)
|
|
@@ -166,14 +194,14 @@ class R2StorageClient:
|
|
|
166
194
|
body: Binary content to store
|
|
167
195
|
|
|
168
196
|
Returns:
|
|
169
|
-
|
|
197
|
+
Presigned URL of uploaded object
|
|
170
198
|
|
|
171
199
|
Raises:
|
|
172
|
-
|
|
200
|
+
OSError: If upload fails
|
|
173
201
|
"""
|
|
174
202
|
try:
|
|
175
203
|
self.client.put_object(Bucket=self.bucket_name, Key=key, Body=body)
|
|
176
|
-
return
|
|
204
|
+
return self.generate_presigned_url(key)
|
|
177
205
|
except Exception as e:
|
|
178
206
|
raise OSError(f"Failed to put object to R2: {str(e)}") from e
|
|
179
207
|
|
|
@@ -366,6 +394,7 @@ async def _process_video_async(
|
|
|
366
394
|
video_path: str,
|
|
367
395
|
jump_type: JumpType,
|
|
368
396
|
quality: str = "balanced",
|
|
397
|
+
output_video: str | None = None,
|
|
369
398
|
) -> dict[str, Any]:
|
|
370
399
|
"""Process video and return metrics.
|
|
371
400
|
|
|
@@ -373,6 +402,7 @@ async def _process_video_async(
|
|
|
373
402
|
video_path: Path to video file
|
|
374
403
|
jump_type: Type of jump analysis
|
|
375
404
|
quality: Analysis quality preset
|
|
405
|
+
output_video: Optional path for debug video output
|
|
376
406
|
|
|
377
407
|
Returns:
|
|
378
408
|
Dictionary with metrics
|
|
@@ -381,9 +411,13 @@ async def _process_video_async(
|
|
|
381
411
|
ValueError: If video processing fails
|
|
382
412
|
"""
|
|
383
413
|
if jump_type == "drop_jump":
|
|
384
|
-
metrics = process_dropjump_video(
|
|
414
|
+
metrics = process_dropjump_video(
|
|
415
|
+
video_path, quality=quality, output_video=output_video
|
|
416
|
+
)
|
|
385
417
|
else: # cmj
|
|
386
|
-
metrics = process_cmj_video(
|
|
418
|
+
metrics = process_cmj_video(
|
|
419
|
+
video_path, quality=quality, output_video=output_video
|
|
420
|
+
)
|
|
387
421
|
|
|
388
422
|
return cast(dict[str, Any], metrics.to_dict())
|
|
389
423
|
|
|
@@ -446,8 +480,10 @@ async def analyze_video(
|
|
|
446
480
|
|
|
447
481
|
start_time = time.time()
|
|
448
482
|
temp_video_path = None
|
|
483
|
+
temp_debug_video_path = None
|
|
449
484
|
r2_video_key = None
|
|
450
485
|
r2_results_key = None
|
|
486
|
+
r2_debug_video_key = None
|
|
451
487
|
|
|
452
488
|
try:
|
|
453
489
|
# Validate referer (prevent direct API access)
|
|
@@ -460,7 +496,8 @@ async def analyze_video(
|
|
|
460
496
|
filename=file.filename,
|
|
461
497
|
file_size=file.size,
|
|
462
498
|
)
|
|
463
|
-
|
|
499
|
+
# Normalize to lowercase
|
|
500
|
+
jump_type = cast(JumpType, _validate_jump_type(jump_type))
|
|
464
501
|
await file.seek(0)
|
|
465
502
|
_validate_video_file(file)
|
|
466
503
|
|
|
@@ -472,10 +509,13 @@ async def analyze_video(
|
|
|
472
509
|
content = await file.read()
|
|
473
510
|
temp_file.write(content)
|
|
474
511
|
|
|
512
|
+
# Create temporary path for debug video output
|
|
513
|
+
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as temp_debug:
|
|
514
|
+
temp_debug_video_path = temp_debug.name
|
|
515
|
+
|
|
475
516
|
# Upload to R2 if client available
|
|
476
517
|
if r2_client:
|
|
477
|
-
|
|
478
|
-
r2_video_key = f"videos/{jump_type}/{timestamp}_{file.filename}"
|
|
518
|
+
r2_video_key = f"videos/{jump_type}/{file.filename}"
|
|
479
519
|
try:
|
|
480
520
|
r2_client.upload_file(temp_video_path, r2_video_key)
|
|
481
521
|
logger.info("video_uploaded_to_r2", key=r2_video_key)
|
|
@@ -487,18 +527,30 @@ async def analyze_video(
|
|
|
487
527
|
) from e
|
|
488
528
|
|
|
489
529
|
# Process video with real kinemotion analysis
|
|
490
|
-
metrics = await _process_video_async(
|
|
530
|
+
metrics = await _process_video_async(
|
|
531
|
+
temp_video_path,
|
|
532
|
+
jump_type,
|
|
533
|
+
quality,
|
|
534
|
+
output_video=temp_debug_video_path,
|
|
535
|
+
) # type: ignore[arg-type]
|
|
536
|
+
|
|
491
537
|
logger.info(
|
|
492
538
|
"video_analysis_completed",
|
|
493
539
|
jump_type=jump_type,
|
|
494
540
|
metrics_count=len(metrics),
|
|
495
541
|
)
|
|
496
542
|
|
|
497
|
-
# Upload results to R2 if client available
|
|
543
|
+
# Upload results and debug video to R2 if client available
|
|
498
544
|
results_url = None
|
|
545
|
+
debug_video_url = None
|
|
546
|
+
|
|
499
547
|
if r2_client:
|
|
500
|
-
|
|
501
|
-
|
|
548
|
+
# Use filename stem for derived files to keep them associated
|
|
549
|
+
# e.g. video.mp4 -> video_results.json, video_debug.mp4
|
|
550
|
+
file_stem = Path(file.filename or "video").stem
|
|
551
|
+
|
|
552
|
+
# Upload Metrics JSON
|
|
553
|
+
r2_results_key = f"results/{jump_type}/{file_stem}_results.json"
|
|
502
554
|
try:
|
|
503
555
|
results_json = json.dumps(metrics, indent=2)
|
|
504
556
|
results_url = r2_client.put_object(
|
|
@@ -513,6 +565,28 @@ async def analyze_video(
|
|
|
513
565
|
"r2_results_upload_failed", error=str(e), key=r2_results_key
|
|
514
566
|
)
|
|
515
567
|
|
|
568
|
+
# Upload Debug Video if it was created
|
|
569
|
+
if (
|
|
570
|
+
temp_debug_video_path
|
|
571
|
+
and os.path.exists(temp_debug_video_path)
|
|
572
|
+
and os.path.getsize(temp_debug_video_path) > 0
|
|
573
|
+
):
|
|
574
|
+
r2_debug_video_key = f"debug_videos/{jump_type}/{file_stem}_debug.mp4"
|
|
575
|
+
try:
|
|
576
|
+
debug_video_url = r2_client.upload_file(
|
|
577
|
+
temp_debug_video_path, r2_debug_video_key
|
|
578
|
+
)
|
|
579
|
+
logger.info(
|
|
580
|
+
"debug_video_uploaded_to_r2",
|
|
581
|
+
key=r2_debug_video_key,
|
|
582
|
+
url=debug_video_url,
|
|
583
|
+
)
|
|
584
|
+
except OSError as e:
|
|
585
|
+
logger.warning(
|
|
586
|
+
"r2_debug_video_upload_failed",
|
|
587
|
+
error=str(e),
|
|
588
|
+
key=r2_debug_video_key,
|
|
589
|
+
)
|
|
516
590
|
processing_time = time.time() - start_time
|
|
517
591
|
|
|
518
592
|
# Build successful response
|
|
@@ -522,6 +596,7 @@ async def analyze_video(
|
|
|
522
596
|
message=f"Successfully analyzed {jump_type_display} video",
|
|
523
597
|
metrics=metrics,
|
|
524
598
|
results_url=results_url,
|
|
599
|
+
debug_video_url=debug_video_url,
|
|
525
600
|
processing_time_s=processing_time,
|
|
526
601
|
)
|
|
527
602
|
|
|
@@ -581,6 +656,18 @@ async def analyze_video(
|
|
|
581
656
|
"temp_file_cleanup_failed", path=temp_video_path, error=str(e)
|
|
582
657
|
)
|
|
583
658
|
|
|
659
|
+
# Clean up temporary debug video file
|
|
660
|
+
if temp_debug_video_path and Path(temp_debug_video_path).exists():
|
|
661
|
+
try:
|
|
662
|
+
Path(temp_debug_video_path).unlink()
|
|
663
|
+
logger.debug("temp_debug_file_cleaned", path=temp_debug_video_path)
|
|
664
|
+
except OSError as e:
|
|
665
|
+
logger.warning(
|
|
666
|
+
"temp_debug_file_cleanup_failed",
|
|
667
|
+
path=temp_debug_video_path,
|
|
668
|
+
error=str(e),
|
|
669
|
+
)
|
|
670
|
+
|
|
584
671
|
# Clean up R2 video if results failed (optional - adjust based on policy)
|
|
585
672
|
# if r2_client and r2_video_key and not results_url:
|
|
586
673
|
# try:
|
|
@@ -88,13 +88,22 @@ def test_r2_upload_file_success() -> None:
|
|
|
88
88
|
with patch("kinemotion_backend.app.boto3.client") as mock_boto3:
|
|
89
89
|
mock_s3 = MagicMock()
|
|
90
90
|
mock_boto3.return_value = mock_s3
|
|
91
|
+
mock_s3.generate_presigned_url.return_value = (
|
|
92
|
+
"https://r2.example.com/presigned-url"
|
|
93
|
+
)
|
|
91
94
|
|
|
92
95
|
client = R2StorageClient()
|
|
93
|
-
client.upload_file("/tmp/test.mp4", "videos/test.mp4")
|
|
96
|
+
url = client.upload_file("/tmp/test.mp4", "videos/test.mp4")
|
|
94
97
|
|
|
95
98
|
mock_s3.upload_file.assert_called_once_with(
|
|
96
99
|
"/tmp/test.mp4", "kinemotion", "videos/test.mp4"
|
|
97
100
|
)
|
|
101
|
+
mock_s3.generate_presigned_url.assert_called_once_with(
|
|
102
|
+
"get_object",
|
|
103
|
+
Params={"Bucket": "kinemotion", "Key": "videos/test.mp4"},
|
|
104
|
+
ExpiresIn=3600,
|
|
105
|
+
)
|
|
106
|
+
assert url == "https://r2.example.com/presigned-url"
|
|
98
107
|
|
|
99
108
|
|
|
100
109
|
def test_r2_upload_file_returns_url() -> None:
|
|
@@ -107,11 +116,16 @@ def test_r2_upload_file_returns_url() -> None:
|
|
|
107
116
|
"R2_SECRET_KEY": "test_secret",
|
|
108
117
|
},
|
|
109
118
|
):
|
|
110
|
-
with patch("kinemotion_backend.app.boto3.client"):
|
|
119
|
+
with patch("kinemotion_backend.app.boto3.client") as mock_boto3:
|
|
120
|
+
mock_s3 = MagicMock()
|
|
121
|
+
mock_boto3.return_value = mock_s3
|
|
122
|
+
presigned_url = "https://r2.example.com/presigned-url"
|
|
123
|
+
mock_s3.generate_presigned_url.return_value = presigned_url
|
|
124
|
+
|
|
111
125
|
client = R2StorageClient()
|
|
112
126
|
url = client.upload_file("/tmp/test.mp4", "videos/test.mp4")
|
|
113
127
|
|
|
114
|
-
assert url ==
|
|
128
|
+
assert url == presigned_url
|
|
115
129
|
|
|
116
130
|
|
|
117
131
|
def test_r2_upload_file_error_handling() -> None:
|
|
@@ -240,12 +254,20 @@ def test_r2_put_object_success() -> None:
|
|
|
240
254
|
with patch("kinemotion_backend.app.boto3.client") as mock_boto3:
|
|
241
255
|
mock_s3 = MagicMock()
|
|
242
256
|
mock_boto3.return_value = mock_s3
|
|
257
|
+
mock_s3.generate_presigned_url.return_value = (
|
|
258
|
+
"https://r2.example.com/presigned-url"
|
|
259
|
+
)
|
|
243
260
|
|
|
244
261
|
client = R2StorageClient()
|
|
245
262
|
url = client.put_object("results/test.json", b'{"status": "ok"}')
|
|
246
263
|
|
|
247
264
|
mock_s3.put_object.assert_called_once()
|
|
248
|
-
|
|
265
|
+
mock_s3.generate_presigned_url.assert_called_once_with(
|
|
266
|
+
"get_object",
|
|
267
|
+
Params={"Bucket": "kinemotion", "Key": "results/test.json"},
|
|
268
|
+
ExpiresIn=3600,
|
|
269
|
+
)
|
|
270
|
+
assert url == "https://r2.example.com/presigned-url"
|
|
249
271
|
|
|
250
272
|
|
|
251
273
|
def test_r2_put_object_error_handling() -> None:
|
|
@@ -80,7 +80,7 @@ function App() {
|
|
|
80
80
|
{loading && <LoadingSpinner uploadProgress={uploadProgress} />}
|
|
81
81
|
{loading && uploadProgress >= 100 && <ResultsSkeleton />}
|
|
82
82
|
{error && <ErrorDisplay error={error} onRetry={handleRetry} />}
|
|
83
|
-
{metrics && !loading && <ResultsDisplay metrics={metrics} />}
|
|
83
|
+
{metrics && !loading && <ResultsDisplay metrics={metrics} videoFile={file} />}
|
|
84
84
|
</main>
|
|
85
85
|
|
|
86
86
|
<footer className="footer">
|