move_detect/server
유창욱 b358822247 feat(ergo): posture-load exposure scoring (REBA bands) with anonymous reports
Same pose stream, new safety axis: musculoskeletal-load prevention. This is an
honest 2D reduction of REBA - band exposure TIME, not a precise REBA score.

Edge:
- geometry: arm_elevation_deg (shoulder->elbow vs vertical-down, best of both
  arms) and knee_flexion_deg (hip-knee-ankle interior angle, worst of both
  legs). Both return None when no confident side exists - "unmeasurable" must
  never read as "0 deg / straight".
- detectors/ergonomics.py: per-frame dt accumulation into bands (trunk 20-60
  and 60+ deg via the existing torso angle, arm 90+ deg, knee <110 deg), gated
  on confident core keypoints; detection gaps are dt-capped (2s) so a dropout
  never counts as exposure. Hourly per-camera report, skipped when nothing was
  observed (an empty-workshop report is noise).
- Engine: tracks in an incident state (FALLING/FALLEN/NO_MOTION) are excluded
  - a fallen worker's 90-deg trunk is an incident, not an ergonomic exposure.
  The report event (ergo_report/INFO) carries no track_id and no spatial:
  a camera-level anonymous aggregate, per the PIPA-first product stance.
- run_once: NO snapshots on ergo_report (a frame would turn a statistic into
  surveillance imagery); capture is skipped entirely when only ergo fired.

Server/UI: ergo_report accepted (validator + chk_events_type, edited in the
still-undeployed heatmap migration); detail view now renders event metrics
with Korean labels and seconds humanized - the ergo report's whole value IS
its metrics. Korean type label in list + detail.

Verified: pytest 232 pass (10 new) / PHPUnit 135 pass. NOTE: the detail-view
visual check is pending - the Chrome extension disconnected mid-verification;
harness is staged under the session scratchpad (events/1/view).
2026-08-06 21:46:39 +09:00
..
deploy build: name the two delivery folders and stop archiving by default 2026-07-20 12:58:44 +09:00
docs docs(deploy): fix MySQL/runbook/secret guidance; offline camera probe 2026-07-25 19:21:01 +09:00
migrations feat(ergo): posture-load exposure scoring (REBA bands) with anonymous reports 2026-08-06 21:46:39 +09:00
public feat(ergo): posture-load exposure scoring (REBA bands) with anonymous reports 2026-08-06 21:46:39 +09:00
src feat(ergo): posture-load exposure scoring (REBA bands) with anonymous reports 2026-08-06 21:46:39 +09:00
storage/snapshots refactor: rename cloud/ to server/ (cafe24 is web hosting, not cloud) 2026-07-20 11:30:52 +09:00
tests feat(ergo): posture-load exposure scoring (REBA bands) with anonymous reports 2026-08-06 21:46:39 +09:00
.gitignore refactor: rename cloud/ to server/ (cafe24 is web hosting, not cloud) 2026-07-20 11:30:52 +09:00
composer.json refactor: rename cloud/ to server/ (cafe24 is web hosting, not cloud) 2026-07-20 11:30:52 +09:00
composer.lock refactor: rename cloud/ to server/ (cafe24 is web hosting, not cloud) 2026-07-20 11:30:52 +09:00
config.example.php refactor: rename cloud/ to server/ (cafe24 is web hosting, not cloud) 2026-07-20 11:30:52 +09:00
phpunit.xml refactor: rename cloud/ to server/ (cafe24 is web hosting, not cloud) 2026-07-20 11:30:52 +09:00
schema.sql feat(ergo): posture-load exposure scoring (REBA bands) with anonymous reports 2026-08-06 21:46:39 +09:00