move_detect/server/migrations/2026-08-07-improvement-actions.sql
유창욱 6b69f22275 feat(data-asset): labeled-dataset export + improvement-action effect tracking
The operator's daily clicks become durable assets:

Label export (GET /api/export/labels?days=N, JSONL download):
- Every 확인/오탐 click is a human verdict on a detection, and each verdict
  carries a blurred 3-frame evidence timeline. The export turns that into a
  dataset: one JSON line per event with type/severity/camera/zone/metrics/
  spatial, label (confirmed | false_positive | unreviewed), labeled_by, and
  snapshot uuids (images fetched via /snap, which re-checks session + site).
  ergo_report rows are excluded - statistics are not labelable detections.
- Admin-only ('manage_compliance'): bulk export of detection history is a
  compliance decision, not an operator convenience. Site scope applies.
- This is where the deferred P1-C evaluation set will come from for free.

Improvement actions (move_actions + GET/POST /api/actions):
- Record a site fix against a camera ("미끄럼 방지 매트 설치"); the report's
  new card compares detection density over EQUAL windows before/after the
  fix (capped 30d; under 3 days shows "측정 중" - two days of data is noise,
  not a verdict). Improvement shows accent, worsening shows red - the card
  reports honestly in both directions, which is exactly what makes the
  improvement numbers credible.
- Future timestamps and >1y-old entries are rejected (the comparison could
  not be fair). Recording needs edit_zones + CSRF.

Verified: PHPUnit 145 pass (5 new: export perm gate + line shape/labels/
snapshot join, action validation, equal-window effect math, pending state)
+ Chrome real-render (action card with better/worse/pending rows, export
link, no console errors).
2026-08-07 07:44:00 +09:00

13 lines
706 B
SQL

-- Improvement action log (개선 조치 기록): "미끄럼 방지 매트 설치" 같은 현장 조치를
-- 카메라에 기록해 두면, 리포트가 조치 전후의 검출 밀도를 자동 비교한다 —
-- 안전 투자의 효과가 데이터로 증명되는 경로.
CREATE TABLE move_actions (
action_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
camera_id VARCHAR(64) NOT NULL,
note VARCHAR(500) NOT NULL,
taken_at BIGINT UNSIGNED NOT NULL, -- 조치 시행 시각(epoch s)
created_by VARCHAR(190) NOT NULL,
created_at BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (action_id),
KEY ix_actions_taken (taken_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;