docs: record completed Tornado playout parity

This commit is contained in:
2026-07-11 15:33:06 +09:00
parent fa0eae7b61
commit d2e16bf0c2
5 changed files with 111 additions and 40 deletions

View File

@@ -37,9 +37,11 @@ timeout, dispatch 뒤 cancellation 또는 결과가 불명확한 COM 실패는 `
원본에는 같은 scene을 바꾸는 두 경로가 있다. 서로 혼동하면 안 된다.
1. Operator Page NEXT는 `btnNext_Click``Next_Scene(0)` 경로다. 다음 page의 fresh 데이터를 조회하고 새 scene을 `LoadScene` → transaction → `QueryVariables``EndTransaction``Prepare(10)``Play(10)`한다. playlist index는 유지하지만 `GetPlayingScene` in-place 갱신은 아니다.
2. Timer refresh는 `timer1_Tick``Show_PlayList(idx: 1)` 경로다. current entry/page의 fresh DB DTO를 사용하고 K3D 호출 `Play(10)` `GetPlayingScene(10)` → transaction → `QueryVariables``EndTransaction``Prepare(10)` `Play(10)` 순서로 현재 scene을 갱신한다. scene-level background와 transition effect는 다시 적용하지 않는다.
2. Timer refresh는 `timer1_Tick``Show_PlayList(idx: 1)` 경로다. current entry/page의 fresh DB DTO를 사용하고 원본 K3D 호출에는 mutation 전 선행 `Play(10)` `GetPlayingScene(10)` → transaction → `QueryVariables``EndTransaction``Prepare(10)` 뒤 후행 `Play(10)`이 모두 있다. scene-level background와 transition effect는 다시 적용하지 않는다.
operator command를 시작할 때 timer를 먼저 멈춘다. TAKE IN과 playlist NEXT 성공 뒤 해당 cut의 원본 `m_time`으로 첫 refresh를 예약하고, 첫 성공 이후에는 3초 간격으로 반복한다. Page NEXT 뒤에는 원본처럼 timer를 다시 시작하지 않는다. refresh 실패, timeout 또는 `OutcomeUnknown`이면 fault latch를 세우고 자동 반복을 중단하며 TAKE OUT 외 mutation 명령을 막는다.
operator command를 시작할 때 timer를 먼저 멈춘다. TAKE IN과 playlist NEXT 성공 뒤 반복 refresh를 시작하고 Page NEXT 뒤에는 원본처럼 다시 시작하지 않는다. 새 runtime은 이전 tracked PLAY의 callback drain을 먼저 확인한 뒤 해당 cut의 첫 `m_time`, 이후 3초의 전체 cooldown을 시작한다. 원본의 UI timer보다 실제 cadence가 callback drain만큼 길어지는 의도적 안전 적응이며, callback 대기와 delay를 겹쳐 `playCompletionPending`이 사실상 계속 유지되는 상태를 방지한다.
마이그레이션의 same-scene refresh는 retained on-air scene에 fresh DTO를 적용해 `BeginTransaction → mutation → QueryVariables → EndTransaction → Prepare(10) → tracked Play(10)`을 한 번 수행한다. 원본의 선행·후행 PLAY 두 번 중 선행 replay와 불완전한 `GetPlayingScene` proxy를 사용하지 않는 명시적 안전 차이다. 모든 PLAY를 callback accounting과 연결하고 중복 송출을 피하기 위한 결정이며, Round H의 정확한 `PLAY = 4`, `SCENE_PLAYED = 4` 예산으로 검증했다. refresh generation과 공개 상태는 atomic epoch로 묶어 이전 CTS의 늦은 delay, success, fault 또는 completion이 새 generation이나 stopped 상태를 덮어쓰지 못한다.
마지막 부분 page는 남은 row만 채우고 나머지 object를 clear/hide한다. `s5088` NXT 비교와 조회 index는 모두 `i + pageIndex * 12`를 사용한다. page 경계값과 partial-page clearing은 자동 테스트로 검증했다.
@@ -51,7 +53,7 @@ operator command를 시작할 때 timer를 먼저 멈춘다. TAKE IN과 playlist
- MainForm 도달 runtime: 34개 builder, active cut alias 45개
- `s5032`/`s8018`: `5032`, `8018`, `8032` shared alias를 closed selection으로 분기
- `s8086`: 원본 MainForm dispatch가 없어 active alias와 앱 runtime route 없이 diagnostic으로 유지
- 실제 데이터 smoke: 33개 Oracle/MariaDB loader와 `s5025` trusted 외부 CP949 파일 통과
- 실제 데이터 smoke: 33개 Oracle/MariaDB loader와 `s5025` trusted 외부 CP949 파일 전제조건을 포함해 통과. 해당 trusted 파일은 Git/MSIX 밖에서 별도로 제공해야 한다.
- `s8086` diagnostic 조회 통과, 전체 Oracle/MariaDB query 55건 통과
builder별 object/mutation과 검증 상태는 [`SCENE_EQUIVALENCE.md`](SCENE_EQUIVALENCE.md)에 있다. 실제 `.t2s`, DB 계정과 외부 CP949 파일은 Git에 넣지 않는다.
@@ -62,6 +64,8 @@ Web catalog는 35개 builder와 도달 가능한 45개 alias를 제공하고 pla
native status는 현재 entry, builder, page size/index/count, current row 수, last-page, next kind와 bounded typed preview를 authoritative 값으로 보낸다. preview는 object 값과 상태를 보여주되 asset path는 숨긴다. refresh active/next/last-success/fault도 표시한다. 성공한 TAKE OUT으로 native refresh state가 reset되면 전용 refresh error marker만 제거하고 다른 unknown/quarantine latch는 유지한다.
refresh CTS와 상태는 같은 atomic epoch 안에서 교체·중단·조건부 갱신·완료한다. 따라서 중단된 이전 loop가 `refreshActive`를 다시 켜거나 오래된 `NextAt`, success, fault를 새 scene 상태 위에 기록할 수 없다. NEXT는 epoch를 먼저 중단하고 pending PLAY callback이 있으면 DB나 workflow에 들어가기 전에 즉시 fail-closed 반환하므로 TAKE OUT을 긴 callback 대기로 막지 않는다.
Web 응답 제한 시간이 지나면 strict `ParseTimeoutQuarantine` 요청을 native에 보내고 MainWindow가 process-lifetime correlation latch를 먼저 세운 뒤 vendor session을 quarantine한다. 명령 진행 중 trusted navigation, reload 또는 WebView2 process failure도 JavaScript 상관관계를 잃기 전에 같은 latch를 세우므로 WebView reload로 해제되지 않는다. pending request와 맞지 않는 늦은 응답은 state 전이 근거로 쓰지 않으며 같은 명령을 다시 보내지 않는다. `OutcomeUnknown`, native fault와 Web timeout은 UI를 닫는 것으로 해제되지 않는다.
## Callback과 scene 수명
@@ -78,12 +82,15 @@ vendor event handler의 `OnScenePlayed`, `OnCutOut`, `OnStopAll`은 managed call
## 검증 판정 범위
다음 자동·통합 검증은 완료됐다.
다음 자동·통합 검증은 clean `main``fa0eae7b61f57f134dfd30ebf1e59e9cc2cccfc5`에서 완료됐다.
- 35개 builder, loader, resolver, runtime coverage와 PageN 경계
- 실제 Oracle/MariaDB 및 trusted CP949 source → DTO → mutation preflight
- Debug/Release x64 Core, Playout, Infrastructure suite와 Web safety suite
- Visual Studio 2026 Debug/Release x64 빌드
- trusted Release x64 MSIX 생성, 설치와 package context 실행
- Debug/Release x64 Core 790개, Playout 374개, Infrastructure 65개와 Web safety suite
- 실제 Oracle/MariaDB read-only query 55/55
- Visual Studio 2026 MSBuild `18.7.8` Debug/Release x64 및 앱 패키지 빌드
- 서명·설치·내용 감사를 통과한 Release x64 MSIX(SHA-256 `D51E8CB637860D9F0377AEE6FF691D7D954BA0FF7E30B1AB65443DA153BC5429`)와 packaged `DryRun`
하지만 이번 마이그레이션 WebView workflow로 실제 Tornado2 PGM에 PREPARE/TAKE IN/Page NEXT/playlist NEXT/timer refresh/TAKE OUT을 보내고 Network Monitoring과 화면을 함께 확인하는 회차는 아직 승인되지 않았고 실행하지 않았다. 과거 고정 `5001 → 5006` runner 증거는 이 동등성 검증을 대신하지 않는다. 실제 운영 검증은 [`PLAYOUT_OPERATIONS.md`](PLAYOUT_OPERATIONS.md)의 회차 승인과 반복 금지 절차를 따른다.
실제 Tornado2 검증은 계획 SHA-256 `55C7755C2F874B4B012239117D4AB717BBCE194E7DCC8DA9B0E40D094FF8CA19``MBNWEB-20260711-H`에서 승인된 `5001``5074`만 실행했다. PGM에서 5001, 5074 page 1/page 2를 확인하고 TAKE OUT 뒤 검은 화면을 확인했다. Network Monitoring은 `SCENE_PREPARE 5001 = 3`, `SCENE_PREPARE 5074 = 2`, `PLAY = 4`, `SCENE_PLAYED = 4`, `FAILURE = 0`, `ERROR = 0`, retry 0을 기록했고 최종 `OutcomeUnknown`은 false였다.
이 실제 증거는 두 scene에만 적용한다. 나머지를 포함한 35개 builder/45개 alias와 PageN 경계는 자동 매트릭스 검증의 범위이며, 다른 scene을 PGM에 보내려면 자산과 명령 예산을 고정한 새 승인 회차가 필요하다. 실제 운영 검증과 복구는 [`PLAYOUT_OPERATIONS.md`](PLAYOUT_OPERATIONS.md)의 반복 금지 절차를 따른다.