# 고정 R5 Runtime 통합·격리 검증

- 작성: 2026-10-31 10:31:26 KST. Profile: ltb1021 / test / work-session.
- 상태: 소스 구현·필수 격리 검증 완료. 운영 미적용, 실제 Web/미디어 smoke 대기.
- 기준 branch: `task/runtime-lifecycle-refactor`; HEAD: `ac1191a8d042074ab9a4d1ea3d99835b99983cd7`.
- 결정: [R5-CONFIG/RUNTIME/DISPLAY-01](../decision/20261031T103126+0900-decision-fight-r5-runtime-contract.md).
- 사용자 평가: 준비된 샘플 기준 시연 후보 합격. 라이브 일반화·운영 수용 완료는 아니다.

## 재사용과 변경

기준 R5는 `2026-10-30_contextra-fight-robust-32clips_r01/reports/probe_robust_weak.json`과 [고정12입력 검토](20261030T215846+0900-run-r5-space-review.md)다. `compact_hand=0.12`, `compact_max_speed=1.0`; R4의 `compact_max_motion`과 ApproachLink를 추가하지 않았다.

`app/fight_r5/`에 공간/특징/규칙/episode 계산과 정규화 좌표 adapter를 분리했다. 기존 `fight_runtime.py`, `scenario_parameters.py`, `stream_settings.py`, `secure_control.py`에는 선택·설정·안전 오류 전달 연결만 추가했다. 기존 legacy 계산은 보존했다.

데이터 흐름: 기존 Web Start → optional parameter 검증/실효값 → 기존 저장·CAS·restart 판단 → FightSettings의 AI 소유 engine 선택 → 동일 Frame Pose/Tracking·실제 PTS → R5 → 기존 FightDisplay/FightEvent → 기존 Redis/미디어 경로.

- 운영 engine 기본값은 legacy로 유지. R5 선택은 private `fight.engine`이며 새 Web 블록만으로 활성화하지 않는다.
- 공개 조절은 version1의 `window_seconds/min_samples/contact_min_samples`만 추가했다. 생략·명시적 초기화·오류를 구분한다.
- 구형4개 동작 설정은 R5에서 무시하고 로그로 설명한다. 유효한 score만 사람0.25·관절0.10 하한으로 보정하며 공유 provider/다른 시나리오에는 적용하지 않는다.
- 실효값이 같으면 기존 Start/config identity를 보존한다. 잘못된 새 설정은 저장·실행 변경 전에 거부한다.
- 현재/확인된1초 유지의 실제 기여 객체는 빨강이다. 현재 판정·유지·내부 Event·외부 cooldown admission을 분리한다. 가짜 객체/ID, 이전 bbox 유지, 규칙 변경은 없다.
- 형식·예시·오류·Web 체크리스트: [FIGHT R5 Web 설정 계약](../../../../../integration/FIGHT_R5_WEB_CONFIG.ko.md).

## 검증

필수 engine 검증과 설정/출력 계약 검증을 아이서티의 기존 CPU 전용 image에서 수행했다. test 호스트에서는 engine을 실행하지 않았다.

| 검증 | 결과·경계 |
| --- | --- |
| 32입력 | 표시18,045관측, 선행 준비 포함18,161관측. 저장 R5 집계·추가/손실 위치 일치 |
| 상세12입력 | 현재 hit/raw/observable·episode와 Event 시각을 기존 상세 진단과 Frame별 대조, 불일치0 |
| 나머지20입력 | 저장 R5 집계 및 기준과 같다고 확인된 빨간 Frame 집합 대조. 기준 엔진 재실행 없음 |
| Runtime adapter | normalized Pose → pixel/실제PTS 변환 뒤 현재 조건·Event가 raw cache 계산과32입력 전체 일치. 실제 objectRef/T 또는 null 보존 |
| R5 표적 테스트 | 18개 PASS. schema·구형/새 설정·하한·생략/초기화·atomic 오류·CAS/no-op·상태 경계·빨강 유지·cooldown·기존 Event/미디어 필드 |
| 선택 계약 suite | 204개 중199 PASS,5 FAIL, 별도27 subtest PASS. 아래 기존 실패이며 신규 실패0 |
| 원격→test | 결과73파일 SHA256 일치. 검증 소스16파일 지문과 실제 worktree 소스 일치 |

원시 cache에는 image 경계를 벗어난 bbox167개가 있었다. 기존 native `pose_decode.hpp`의0~1 clamp를 검증용 normalized 입력 변환에만 적용했고, 원시 cache는 수정하지 않았다. raw core와 native 방식 adapter 모두 동일한 R5 판정을 유지했다. 초기 실패와 후속 수정 근거는 run reports에 보존했다.

기존 실패5개는 변경 전 HEAD의 해당 synthetic config/artifact test만 다시 실행해 같은 실패를 확인했다. 기준 엔진의 cache 계산이나 모델 재실행이 아니다.
- `test_web_fight_shared_pose_and_crowd_switch`: 필수 CROWD parameters가 없는 오래된 fixture의 provider 기대값.
- `test_artifact_attempt_owner_unchanged_and_only_one_delivery_path`, `test_artifact_blocked_time_never_invokes_relay`, `test_artifact_http_only_does_not_initialize_relay_or_ledger`, `test_existing_post_response_validation`: fake `event_artifact_store`에 `StaleArtifactClaim`이 없어 ImportError.
- 관련 없는 fixture를 이번에 수정하지 않았다. suite 전체 PASS나 실제 Event 전송 검증으로 표현하지 않는다.

측정은 cache 기반 CPU 계산뿐이다. 입력별 규칙 계산 p95 약0.025~33.26ms, 최종 비교 루프 합계34.08초, 프로세스 peak RSS124,532KiB였다. 실시간 decode/Pose/Tracking/Redis/Event를 포함한10FPS 달성 근거는 아니다.

## 보호와 자료

- 시험 image 지문: `sha256:671c7416f503481d2be2092a5aa0c035938a07fc514cfc0b45f94d78e86370bd`.
- CPU2/8GiB·최대2작업·timeout1800초·network none·GPU 노출 없음. root 여유 종료 시 약197GiB.
- 운영 컨테이너 identity/image/시작 상태는 전후 동일. GPU PID 집합은 달랐으며 본 시험 GPU 작업0, 원인 조사는 하지 않았다.
- 시험 컨테이너 잔류0. 운영 제어·채널 Start/Stop·실제 Event 전송0. 실제 Runtime 지연·Event 품질은 미측정.
- 모델/Pose/Tracking·기준/R4/ApproachLink 재실행, 새 dependency/build, 새 영상, 원본/cache 변경 없음. 키·sudo파일 보존.

실행 root: `/data/codex-artifacts/contextra/action-model-eval/2026/2026-10-31_contextra-fight-r5-integration_r01`.
원격 root는 `/storage/contextra/experiments/action-model-eval/2026/` 아래 같은 run 이름이다.
근거: [최종검증](/data/codex-artifacts/contextra/action-model-eval/2026/2026-10-31_contextra-fight-r5-integration_r01/results/final_validation.json), [cache 검증](/data/codex-artifacts/contextra/action-model-eval/2026/2026-10-31_contextra-fight-r5-integration_r01/results/cache_validation.json), [소스 지문](/data/codex-artifacts/contextra/action-model-eval/2026/2026-10-31_contextra-fight-r5-integration_r01/results/source_fingerprints.json), [운영 전후](/data/codex-artifacts/contextra/action-model-eval/2026/2026-10-31_contextra-fight-r5-integration_r01/reports/operational_comparison.json).

## 운영 반영·복귀 준비

현장 읽기 확인에서는 기존 Start가 `parameters`를 지원하지만 현재 repository의 `app.multi_roi`는 설치돼 있지 않았다. 현장 운영 모드를 바꾸지 않았다. 현재 `secure_control.py` 일부만 운영에 복사하면 다른 세대의 모듈이 섞일 수 있으므로 다음 승인 단계에서 일관된 소스/image 묶음과 실제 배포 baseline을 먼저 확정한다. 이번 source archive는 검증 묶음이며 배포 image가 아니다.

1. 배포·대상 채널·중단 가능 시간·복귀 image/config 지문을 승인한다. 실제 source/image/설정 CAS가 달라졌으면 해당 반영만 멈춘다.
2. 기존 image/source/settings와 실효 score/cooldown/ROI를 보존한다. 현재 task 전체를 무조건 설치하거나 운영 기본값을 자동 전환하지 않는다.
3. 승인된 일관된 묶음 반영 후 대상의 private `fight.engine=r5`를 설정한다. 구형 Web은 그대로 사용 가능하며 새 블록은 선택이다. 실제 채널 Start는 별도 사용자 승인/수동 확인을 따른다.
4. 최소 Web 확인: 구형 Start의 실효값, 빨강 현재/1초 유지/미관측 해제, 기존 알람·썸네일·클립 열기. 새 block patch가 가능하면 생략/오류/no-op도 확인한다. 현재 요청에서는 실행하지 않았다.
5. 복귀는 승인된 이전 image/source와 저장 설정 snapshot으로 한다. `engine=legacy`만 바꾸면 현재 공통 score/ROI/cooldown은 남으므로 정확한 복귀에는 이전 설정도 필요하다. 자동 rollback/자동 Start는 하지 않는다.

권장: 위 최소 browser smoke. 보류: 장시간 라이브, 자연 장면 일반화, 쓰러짐 엔진 개발. 공용 FINAL 문서는 이번 R5 연결이 stale 후보지만 사용자 승인 범위 밖이므로 수정하지 않았다.
