Fumoca v10.1.0 — Frame Extraction Engine Pack
==============================================

Patched from v10 — all QA/QC fixes applied.

Changes in v10.1.0
------------------
BUGS FIXED
  - cap.release() now in finally block — no VideoCapture leak on exceptions
  - Recovery pass uses index set (was object identity comparison — could silently fail)
  - cv2.imwrite return value checked — raises RuntimeError on disk full / bad path
  - feature_min_distance now reads from profile (was hardcoded 26.0)

DESIGN FIXES
  - spacing_score and final_score are new separate FrameMetrics fields
    quality_score is no longer mutated during selection — stays a clean intrinsic score
  - Dedup compares against nearest frame in time from selected set
    (was selected_frames[-1] which is quality-ordered, not time-ordered)
  - Worker path uses Path(__file__).parent (was bare relative string — broke outside engine/)

MAGIC NUMBERS PROMOTED TO PROFILE FIELDS
  - feature_min_distance     (was hardcoded 26.0)
  - blur_normalize_saturation (was hardcoded 2.2)
  - recovery_gap_factor       (was hardcoded 0.75)

NEW FEATURES
  - logging module throughout (log.info/warning on all key steps)
  - --version flag  (fumoca 10.1.0)
  - --log-level flag (DEBUG / INFO / WARNING / ERROR)
  - Portrait-mode rotation fix (_apply_rotation + CAP_PROP_ORIENTATION_META)
    Mobile Android/iOS videos shot in portrait no longer come out sideways
  - Video duration validation — warns if video is too short (<3s) or too long (>120s)
  - fumoca_version field in manifest.json and summary.json
  - avg_final_score_selected added to summary
  - Input file existence check before processing starts

DEAD CODE REMOVED
  - gated_quality_score() deleted (defined but never called — was drifting from live logic)
  - Unused imports: math, os

Main entry point:
  python frame_extraction_engine.py --input /path/to/video.mp4 --output /path/to/out --profile standard

CLI flags:
  --input       Path to input video (required)
  --output      Output directory (required)
  --profile     fast | standard | pro  (default: standard)
  --version     Print version and exit
  --log-level   DEBUG | INFO | WARNING | ERROR  (default: INFO)

Outputs:
  selected_frames/   selected frame images
  manifest.json      full per-frame metrics for all candidates + selected
  summary.json       quick summary with counts, times, avg scores, version
