# 시나리오 Web 시험 준비

계약: `SCENARIO-FANOUT-01`, `FALL-WIRE-01`. PR6/PR7/PR8 원문은 선개발 당시 기록으로 보존한다.
현재 통합 계약은 이 문서를 우선하며 실제 반영 결과는 profile Owner의 최신 run을 따른다.

## 지원 범위

| Web 활성 시나리오 | 모델 | Tracking |
| --- | --- | --- |
| INTRUSION | Medium | On |
| LOITERING | Medium | On |
| INTRUSION + LOITERING | Medium 하나 공유 | On, Frame당 한 번 |
| FALL 단독 또는 FALL + INTRUSION/LOITERING | Pose 하나 공유, Medium 중복 실행 없음 | On, Frame당 한 번 |
| FIRE | RFDETRFireSmoke | Off |
| FIGHT 단독 또는 FIGHT + INTRUSION/LOITERING/FALL | Pose 하나 공유 | On, Frame당 한 번 |
| CROWD 단독 | Awiros_person_and_head_detection | Off |

사람 시나리오는 기존 result worker에서 순차 판단한다. ROI, 체류/재무장 상태와 EventID는
독립이며 기존 `scenarioResults` 배열, `scenarioConfig` 맵, `eventIds` 배열로 함께 전달한다.
실시간 색상은 어느 한 시나리오라도 경고 상태이면 red다. Artifact는 기존 Event별 파일/원장을
사용하며 snapshot에 포함된 각 시나리오 ROI와 판단 이름을 표시한다.

Web Start의 기존 전체 시나리오 body를 사용한다. ROI 누락/null/[]은 전체화면이며 첫 ROI만 쓴다.
FIRE 전환은 모델과 표시 category를 함께 바꾸고 Tracking을 끈다. 기존 FIRE에서 사람 시나리오로
복귀하면 person/Tracking On으로 돌아가며 FALL 필요 여부에 따라 Medium 또는 Pose를 선택한다.
동일 요청은 기존 no-op·저장/CAS 경로를 유지한다.
활성 FIRE와 사람/Pose 의존성을 함께 요청하면 `NEEDS_MULTI_PROVIDER_RUNTIME_CONFIRMATION`으로
거부하며 저장하거나 다른 시나리오를 임의로 끄지 않는다. CROWD와 다른 시나리오의 조합도 저장 전
명시적으로 거부한다. FIGHT/CROWD는 더 이상 skip하지 않는다.

## FIGHT 임시 시연

9월 시연용 Pose interaction heuristic이며 실제 폭행 인식이나 공격자/피해자 판정이 아니다.
person0.25/joint0.15 기본값, 가까운 tracked pair와 손목 이동/상대 방향 접근 burst를 사용한다.
Web confidence는 person_score에 연결되고 null은0.25다. 첫 ROI에서 두 사람의 bbox 하단중앙이
모두 안에 있어야 판단한다. 누락/null/빈 ROI는 전체화면이다.
순간 거리 이탈이나 invalid PTS로 episode latch를 지우지 않는다. 관측 가능한 quiet2초 후 재무장하며
missing 시간은 close/quiet에 더하지 않는다. 동일 pair의 현재 두 bbox를 빨강 OR 표시에 연결한다.
Event는 pair당1회이고 정렬된 첫 track을 단일 objectRef/bbox 대표로 쓴다. 새 public schema는 없다.
Tracking ID 단절과 실제 검출률 보정은 이번 범위가 아니며, 향후 행동 인식 방식으로 교체한다.

## CROWD 모니터링

첫 ROI 안의 person/head를 별도 집계한다. 기본 confidence0.45, class-aware NMS0.85,
PTS3초 window/report, 최소2표본이며 정상 빈 결과는0, missing/invalid/stale는 제외한다.
person ROI점은 bbox 하단중앙, head는 중심이다. 현재 각 클래스의 최고 score bbox에만
`person | P≈N`, `head | H≈M`을 표시한다. 둘을 합산한 인원수로 해석하지 않는다.
현재 클래스 bbox가 없으면 숫자도 표시하지 않는다. Tracking/Event/Artifact는 만들지 않는다.
관제의 labelText/color/ROI 표시와 무입력 overlay 만료는 사용자 브라우저 시험에서 확인한다.
새 모델은512, RGB/NCHW/ImageNet 정규화, FP16입력/FP32출력, batch1/4/4, instance8이다.
원본·engine과 입출력은 [모델 계약](../deployment/AWIROS_PERSON_HEAD_CANDIDATE.ko.md)을 따른다.

사용자 시험: FIGHT는 원하는 사람 시나리오와 선택 가능, CROWD는 다른 시나리오를 모두 Off로
설정하고 Start한다. 첫 CROWD 숫자는 유효 PTS가 약3초 진행된 뒤 표시된다.
이번 준비 작업에서는 카메라 Start·실제 Event POST를 수행하지 않았다.

## FALL 연결과 누락

- 기존 Web FALL confidence는 person_score이며 null은0.25다. joint0.15와 내부 시간값은 AI 설정이다.
- FALL은 bbox 하단중앙이 첫 ROI 안인 Pose만 소비한다. 빈/null/누락 ROI는 전체화면이다.
  ROI 밖 객체는 OUTSIDE 표시이며 FALL engine에는 미관측으로 전달한다. 짧은 이탈은 시간을
  더하지 않고, 긴 이탈은 core의 미확정 초기화/confirmed retention을 따른다. 외부 bbox로 Event를 만들지 않는다.
- NMS 후 Pose/Tracking을 공유하되 debug min_joints와 표시 confidence로 FALL 입력을 제거하지 않는다.
  각 시나리오가 자기 threshold를 적용한다. FALL 입력의 ROI/local index는 원래 objectRef로 재매핑한다.
- selected Frame의 bounded 원장으로 추론 이후 누락을 확인한다. 정상 sampling은 gap이 아니다.
  결과 queue 교체/age discard와 선택단계 invalid PTS는 다음 수락 Frame의 gap으로 전달한다.
  단순 decoded frame_seq 점프나 네트워크 누락을 추측하지 않는다.
- FALL 판단 전에 Frame/run 유효성을 확인한다. 수락 뒤 Stop이 와도 capture 인계를 끝내고 join한 후
  engine과 UUID latch를 정리한다. FALL Event capture queue 거부는 조용히 무시하지 않고 결과경로 오류로 기록한다.
- FALL Off는 Pose display 설정을 덮지 않는다. 다른 Pose 요구가 없으면 Medium으로 복귀하며,
  사용자가 명시한 기존 show_joints/edges 등 Pose 요구는 보존한다.
- 실제 낙상 영상 정확도, FALL Runtime 첫Frame/판정/Event/GET은 아직 시험 대기다.

## FALL 임시 DOWN 대기 생략

내부 옵션 `fall.test_skip_down_hold`의 전역 기본값은 `false`다. 시험채널에서만 명시적으로
`true`를 저장하면 정상 UPRIGHT/TRANSITION을 거쳐 DOWN_CANDIDATE에 진입한 현재 Frame에서
즉시 FALL Event를 확정한다. 기존 `down_hold_seconds=0.7` 값 자체는 바꾸지 않는다.
ROI/score/관절 geometry/전이 만료/episode 1회/recovery/run 분리와 Event 인계는 그대로다.
처음부터 누운 사람이나 단순 DOWN 자세만으로 Event를 생성하는 옵션이 아니다.

현장별 승인 기본값은 `CONTEXTRA_FALL_SKIP_DOWN_HOLD_DEFAULT=true|false`로 지정할 수 있다.
미설정 기본은false이며 명시적 채널 설정이 우선한다. 아이서티는 승인에 따라 현장 기본true를
적용했다. test 기본값/기존 시험채널은 변경하지 않았다. [현장 적용/복귀](../deployment/ICERTI_INCREMENTAL.ko.md)를 따른다.

Web에는 새 필드를 추가하지 않는다. 기존 Start projection은 이 내부 옵션을 보존하지만,
FALL confidence는 Web 입력이 우선하므로 시험에서는 `0.30`을 지정한다.
기본 Off와 특정 채널 On을 혼동하지 않는다. bbox 검출 개선이나 실제 낙상 정확도를 보장하지 않으며,
짧은 자세 흔들림에도 Event가 확정될 수 있어 오탐 위험이 증가한다.

시험 종료 후 사용자 수동 Stop/회수 완료를 확인하고 기존 Settings GET의 configured.revision으로
PATCH body `{"expected_revision":"<현재 revision>","fall":{"test_skip_down_hold":false}}`를 적용한다.
새 revision과 저장값을 확인한 뒤 다음 수동 Start부터 원래 0.7초 대기가 적용된다.
실행 중 PATCH는 controlled restart를 일으키므로 이번 시험의 원복은 stopped 상태에서만 한다.
임시 옵션 Owner는 FALL config/engine이며, 현재 시험 종료 피드백 시 RESET을 재검토한다.

## 판단과 외부 경계

- LOITERING: 유효 PTS 체류5초, confidence>=0.5, 관측 누락 grace1초, 관측 이탈1초 재무장.
- FIRE: flame_visible만 사용, bbox center/첫 ROI, confidence>=0.5, 최근2초 표본 수 비율>=0.6,
  최소 연속 관측1초 및 현재 positive일 때 Event1회. 0.5초 초과 공백은 연속성 초기화이며
  실제 연속 negative5초 뒤 재무장한다. Smoke/과거 bbox/가짜 track ID는 외부에 보내지 않는다.
- Frame/RTP 시간, 좌표·padding, 기존 Event key와 최대2회 전송/원장 소유권은 유지한다.
- Analytics/Sidecar image와 Gateway template을 함께 반영한다. CA·TLS·WSS·접근 정책은 유지한다.
- Artifact 운영 기본 On/HTTP On. 시험 종료만으로 Off하지 않으며 과거 Event는 재전송하지 않는다.

## 미연결 복수 모델 core

`provider_composition.py`는 PR7에서 가져온 미연결 선개발 코드다. 실제 result path에서 사용하지 않는다.
기본 순차 fixture만 통과했으며 thread 경합, 열린 slot 상한, 닫힌 Frame 기록 회수 뒤 재수락 방지는
후속 보완/검증 대상이다. 이를 bounded concurrency 또는 실제 multi-provider 수용 완료로 해석하지 않는다.
이번 같은 Provider의 사람 시나리오 실행은 이 composer를 사용하지 않는다.

## 사용자 시험 순서

1. Codex의 준비 완료 뒤 각 시험용 cameraId를 전달한다. 임의 자동 Start는 하지 않는다.
2. PR6/7 시험은 사용자 확인으로 최소 수용했다. 다음은 FALL 단독과 FALL+침입/배회를 브라우저에서 Start한다.
3. 사용자는 그림/시간/ROI를 확인하고 Codex는 요청·활성 설정·오류와 자연 Event를 짧게 대조한다.
4. 유효 사람 체류/불꽃 입력이 없으면 추론 준비와 판정/Event 수용을 구분한다.
5. 실제 시나리오/영상/GET 시험과 16채널·성능·Person+Fire는 준비 단계에서 실행하지 않는다.

## 재개·실패

private 원장의 image ID와 전체 기존 Compose env/overlay 조합을 사용한다. 설정 일부만으로
재생성하지 않는다. Gateway의 graceful QUIT가 WSS 종료를 기다릴 수 있어 실제 Stop 상태를 확인한다.
Stop/반영 intent를 재사용하고 채널 Start·build·로그인을 무조건 반복하지 않는다.
실패 시 이번 대상 서비스만 정상 Stop/reap하며 자동 image/config rollback이나 재Start를 하지 않는다.
