feat: consolidate legacy parity migration baseline

This commit is contained in:
2026-07-20 22:06:12 +09:00
parent 5eb4054120
commit 4a54977341
66 changed files with 5391 additions and 460 deletions

View File

@@ -4,6 +4,9 @@
> [개발 환경 상시 권한](DEVELOPMENT_ENVIRONMENT_AUTHORIZATION.md)에 따라 회차별 대화형
> 승인을 다시 받지 않는다. 운영/방송 대상과 `OutcomeUnknown` 중단 규칙은 그대로다.
> 현재 완료·차단 판정은 [`MIGRATION_STATUS.md`](MIGRATION_STATUS.md)가 우선한다. 아래의
> 2026-07-11 Round 기록과 1.0.5 해시는 당시 패키지의 역사적 증거다.
## 안전 기준
기본 모드는 `DryRun`입니다. `DryRun`은 COM 객체를 만들거나 Tornado 출력에 명령을 보내지 않고 WebView 메시지, 큐, 상태 및 오류 표시 흐름만 검증합니다. 현재 방송 PROGRAM(PGM)에 연결된 Tornado 프로세스는 항상 **안전하지 않은 대상**으로 취급합니다. 프로세스 이름이나 실행 여부만으로 테스트 대상이라고 판단하지 않습니다.
@@ -346,7 +349,7 @@ CLI용 Test JSON은 위처럼 앱 기본 경로인 `playout.local.json`과 다
3. 잘못된 설정 또는 엔진 부재가 앱 종료가 아니라 연결 상태와 안전한 오류 메시지로 표시됩니다.
4. x64 MSIX를 설치해도 같은 dry-run 흐름이 동작합니다.
최종 서명 Release x64 MSIX를 설치한 package context에서 실제 Oracle/MariaDB를 읽는 `DryRun` 검증을 완료했습니다. Web catalog 35개(34개 runtime route 보유), DB 상태 2/2 정상, alias `5001`/`N5001`, fade 6, mutation preview와 asset 경로 비노출을 확인했습니다. 34개 runtime route가 모두 외부 asset까지 준비됐다는 뜻은 아니다. 이어 `5001 PREPARE → fresh TAKE IN → callback drain 뒤 full 2초 cooldown의 자동 refresh → 5074 playlist NEXT → 같은 entry/scene의 Page NEXT`를 수행했고, 5074 `page 1/20 → page 2/20` 전환과 Page NEXT 뒤 refresh 정지를 확인했습니다. 5·6·12개 단위, 최대 20페이지, partial/마지막 page의 clear·hide, `isLastPage`, `END OF PLAYLIST`와 NEXT 비활성 경계는 원본에서 도출해 고정한 자동 테스트로 검증했습니다. TAKE OUT 뒤에는 scene/refresh가 정리되고 playlist 편집 잠금이 해제되었습니다. 전 과정의 안전 배지는 `DRY RUN · PROGRAM 차단`이었고 COM/KTAP/Tornado2 연결은 발생하지 않았습니다.
2026-07-18 현재 unsigned 개발 MSIX에서 실제 Oracle/MariaDB를 사용하는 전체 UI/DB 검증을 완료했습니다. 이어 지정 개발 Tornado2/PGM에서 `5001 → 5074 Page NEXT → TAKE OUT`을 재검증하고 자산 비의존 30개 route를 순차 검증했습니다. 실제 PGM 완료 범위는 32/34 route이며, 미검증은 원본 Cuts에도 영상이 없는 `s5006``s6001`뿐입니다. `5077`은 fresh DB 120건을 6행씩 1/20부터 20/20까지 이동했고 마지막 페이지에서 `5088` 12행 1/20으로 전환했습니다. 이전 scene unload와 최종 TAKE OUT/UNLOAD/IDLE, `FAILURE=0`, `ERROR=0`, retry 0, `OutcomeUnknown=false`를 확인했습니다.
WebView 상태 wire는 `Disconnected`, `Connecting`, `Connected`, `Reconnecting`, `Faulted`, `OutcomeUnknown` 등 native connection state를 별도로 전달합니다. Web catalog는 35개 builder와 도달 가능한 45개 alias, row별 `enabled`를 보존하고 PREPARE 성공 뒤 playlist snapshot을 freeze합니다. pending command, `OutcomeUnknown`과 timeout quarantine 중에도 snapshot 편집 잠금을 유지합니다. native status의 current entry/builder/page size/current rows/last-page와 bounded preview가 authoritative 값이며 asset path는 preview에서 숨깁니다. refresh active/next/last-success/fault도 전달하고 refresh fault는 TAKE OUT 외 mutation 명령을 막습니다. 성공한 TAKE OUT 뒤에는 전용 refresh error marker만 reset하며 다른 unknown latch를 지우지 않습니다. `OutcomeUnknown`과 timeout은 `retryable: false`이며 오류 창을 닫아도 native 잠금은 유지됩니다. 브라우저 응답 제한 시간은 검증된 native operation timeout에 5초 전달 여유를 더해 사용하며, 상관 응답이 오지 않으면 strict `ParseTimeoutQuarantine` 요청을 native에 보냅니다. MainWindow는 await 전에 process-lifetime latch를 세우고 vendor session을 quarantine하므로 WebView reload로도 해제되지 않습니다. 명령 진행 중 trusted navigation, reload 또는 WebView2 process failure로 JavaScript 상관관계가 사라지는 경우도 같은 native latch를 먼저 세웁니다. 늦은 응답이나 UI 재시도로 같은 명령을 다시 보내지 않으며 native 명령이 끝나면 authoritative status를 다시 게시합니다. NEXT는 원본의 `m_TakeIn` 조건처럼 on-air 장면이 있을 때만 native와 Web 양쪽에서 허용됩니다. Test on-air 배지는 실제 PROGRAM과 구분해 `TEST ON AIR`로 표시합니다.
@@ -354,13 +357,15 @@ On-air 표식이 남은 상태에서는 프로세스 감시, 연결 해제, 앱
### 화면/계약 구현과 운영 동등성 경계
- PList 기존 한국어 `DC_TITLE`/`LIST_TEXT` 2,213행은 실제 read-only DB에서 무손상 대조했다. KRX·해외종목·GraphE fresh proof를 합친 `selectionMapped=1,603`/차단 610 확인했지만 scene data·asset·PREPARE·PGM 성공은 별도다. 실제 manual named save write→reload는 미검증이다.
- ThemeA/EList의 expected identity와 응답 상관 계약은 구현됐지만 KRX/NXT·동명이름·코드 경계의 실제 create/replace/delete read-back은 검증되지 않다.
- PList 기존 한국어 `DC_TITLE`/`LIST_TEXT` 2,213행은 실제 read-only DB에서 무손상 대조했다. 즉시 복원 1,581행과 GraphE fresh read 22행을 합친 `selectionMapped=1,603`/차단 610 확인했다. 차단 610행은 DBA 결정 없이 추정 복원하지 않는다.
- 개발 MSIX에서 PList create/save→fresh readback→delete/absence, ThemeA KRX/NXT와 EList create/edit/save→fresh readback→delete/absence를 실제 입력으로 검증하고 cleanup했다. 운영 DB에 대한 포괄적 쓰기 허가는 이 결과에 포함하지 않다.
- 원본 `종목비교.dat`는 signed package에서 8쌍 one-time import와 재시작 marker를 확인했다. FSell/VI는 격리 fixture의 marker-last와 production opened-handle read를 통과했지만, 현재 운영 profile의 기존 동일 파일을 덮어쓰거나 marker를 새로 만들지 않았다.
- `s5006``Video\큐브배경.vrv``s6001` 해외지수 국가 영상 13개는 현재 승인 Cuts에 없으며, alias-only `Missing=0`은 asset-ready 증거가 아니다.
- GraphE·PList/AList·ThemeA·EList 운영 DB-W와 `5001`/`5074` 밖의 실제 PGM은 미검증이다. 아래 Round H 기록은 승인된 두 scene의 역사적 증거로 보존한다.
- 개발 PGM 32/34 route가 검증됐고, `s5006`/`s6001`은 외부자산 제공 전까지 fail closed한다. 아래 Round H 기록은 현재 결과가 아니라 역사적 증거로 보존한다.
승인 컷의 과거 load/play 경로와 현재 WebView 기반 Scene/PageN 데이터 동등성은 서로 다른 검증 범위입니다. 복합 mutation·페이지 계산·fresh TAKE IN·Page NEXT·timer refresh는 구현 및 자동/실데이터 검증을 마쳤으며 [원본 Tornado 송출 흐름 분석](LEGACY_PLAYOUT_ANALYSIS.md)과 [35개 Scene 매트릭스](SCENE_EQUIVALENCE.md)에 기록합니다. 첫 Live WebView 회차 `MBNWEB-20260711-A`의 DB 실패와 Round G의 refresh starvation은 모두 결과를 추정하거나 반복하지 않고 안전하게 종료했습니다. 수정된 Round H에서는 승인된 5001/5074 범위의 실제 TAKE IN, 자동 refresh, playlist/Page NEXT와 TAKE OUT을 Network Monitoring과 PGM에서 함께 완료했습니다. 이 결과를 나머지 scene의 실제 PGM 검증으로 확대하지 않습니다.
### 역사적 Round 기록
첫 Live WebView 회차 `MBNWEB-20260711-A`의 DB 실패와 Round G의 refresh starvation은 모두 결과를 추정하거나 반복하지 않고 안전하게 종료했습니다. 수정된 Round H에서는 당시 승인된 5001/5074 범위의 실제 TAKE IN, 자동 refresh, playlist/Page NEXT와 TAKE OUT을 Network Monitoring과 PGM에서 함께 완료했습니다. 이 기록은 당시 패키지 증거이며 2026-07-18 현재 판정은 [`MIGRATION_STATUS.md`](MIGRATION_STATUS.md)를 따른다.
일반 앱과 정규 Test 경로의 실제 COM 스모크는 별도 테스트 인스턴스와 테스트 씬이 준비된 때에만 진행합니다. 위 안전 게이트를 독립적으로 재확인하고 `mode``Test`로 바꾼 뒤 테스트 모니터에서 `PREPARE → fresh TAKE IN → Page/playlist NEXT → timer refresh → TAKE OUT` 결과를 관찰합니다. 의도하지 않은 PGM/운영 출력 변화가 보이면 추가 명령을 중단합니다. native 결과가 명확하고 Gate A에 포함된 경우에만 TAKE OUT을 한 번 요청하며, timeout·`OutcomeUnknown`·`WEB_TIMEOUT`·refresh fault라면 앱 종료나 반대 명령으로 자동 롤백하지 않고 session을 quarantine한 채 운영자가 실제 출력 상태를 먼저 확인합니다.