docs: record completed Tornado playout parity
This commit is contained in:
@@ -7,13 +7,13 @@
|
||||
| 항목 | 상태 |
|
||||
|---|---|
|
||||
| 기본 모드 | `DryRun`; COM 객체와 `KTAPConnect`를 만들지 않음 |
|
||||
| 자동 테스트 | 최신 전체 재검증에서 Core Debug/Release x64 각각 779/779, Playout 각각 355/355, Infrastructure 각각 65/65, Web safety 12/12 통과; 이후 테스트 추가 시 개수보다 실패 0건을 기준으로 재확인 |
|
||||
| 자동 테스트 | 최종 전체 재검증에서 Core Debug/Release x64 각각 790/790, Playout 각각 374/374, Infrastructure 각각 65/65(합계 각 1,229/1,229), Web safety 12/12 통과; 이후 테스트 추가 시 개수보다 실패 0건을 기준으로 재확인 |
|
||||
| Visual Studio 2026 | Debug/Release x64 빌드 성공 |
|
||||
| trusted Release x64 MSIX | 생성·서명 검증·x64 설치·package context 실행 성공. 실제 DB DryRun에서 5001 timer refresh, 5074 playlist/Page NEXT와 1~20페이지 마지막 경계, TAKE OUT 정리를 확인 |
|
||||
| trusted Release x64 MSIX | 생성·서명 검증·x64 설치·package context 실행 성공. 실제 DB DryRun에서 5001 timer refresh, 5074 playlist NEXT와 page 1→2 Page NEXT, TAKE OUT 정리를 확인; 나머지 PageN/마지막 경계는 자동 테스트로 검증 |
|
||||
| 실제 데이터 전체 scene smoke | 34개 도달 가능 builder 통과: 33개 DB + `s5025` trusted 외부 CP949 파일. `s8086` diagnostic 포함 Oracle/MariaDB query 55건 통과 |
|
||||
| `s5025` trusted 수동 파일 | 외부 CP949 source 통합 검증 통과; 실제 파일/환경은 계속 Git 밖에서 회차별 preflight |
|
||||
| `s5006` `Video\큐브배경.vrv` | 현재 승인 Cuts root에서 누락 |
|
||||
| 이번 마이그레이션 WebView workflow의 실제 Tornado2 검증 | **부분 실행·실패 회차 종료; 새 회차 필요** |
|
||||
| 이번 마이그레이션 WebView workflow의 실제 Tornado2 검증 | **승인된 5001/5074 범위에서 Round H 실제 PGM 완료; 35개 전체의 실제 PGM 검증으로 확대 해석하지 않음** |
|
||||
|
||||
과거 고정 `5001 → 5006` runner의 실제 PGM 기록은 연결과 기본 K3D 명령 표면의 증거다. 현재 WebView playlist, fresh TAKE IN, Page NEXT, timer refresh, callback/unload의 동등성 완료 증거는 아니다.
|
||||
|
||||
@@ -21,6 +21,47 @@
|
||||
|
||||
이 회차 뒤 health query와 시장 탭 DB 조회를 송출 fresh query와 하나의 DB activity gate로 직렬화했다. 송출 명령과 자동 on-air refresh가 시작되면 진행 중인 health/market 조회를 취소하고 gate를 먼저 확보하며, 30초 periodic health는 송출 중 건너뛴다. native database status에는 단조 증가 sequence를 붙이고 Web은 오래된 응답을 폐기한다. DB health의 `IsTransient`와 숫자 provider error code만 진단 도구에 보존하며 SQL, parameter, host, 계정, 암호, connection string과 provider message는 출력하지 않는다.
|
||||
|
||||
### Round G 실패 경계와 Round H 최종 실제 검증
|
||||
|
||||
Round G `MBNWEB-20260711-G`는 5001 TAKE IN과 화면 표시까지 성공했지만, 승인된 자동 refresh 1회 예산을 넘어 refresh가 연속 실행되는 경계에서 중단됐다. Network Monitoring에는 성공한 transaction/prepare 39회와 PLAY/`OnScenePlayed` 38회가 기록됐고 FAILURE/ERROR는 각각 0이었다. `refreshLastSuccessAt`은 전진했지만 `playCompletionPending`이 사실상 계속 유지되어 관찰 대기가 timeout됐으며, 5074 playlist NEXT와 Page NEXT는 보내지 않았다. 출력이 5001로 명확히 active이고 `OutcomeUnknown=false`였으므로 승인된 비상 TAKE OUT을 정확히 한 번 보내 STOPALL과 5001 UNLOAD, PGM black, disconnect를 확인했고 재시도는 0회였다.
|
||||
|
||||
Round G 증거 경계는 다음 SHA-256으로 고정한다.
|
||||
|
||||
| 증거 | SHA-256 |
|
||||
|---|---|
|
||||
| 계획 | `E8A6B05E28130665A73CC882A70CD85F023EBF6C59795EC3A56671BE06B06B9A` |
|
||||
| 회차 결과 | `9B573EBB0F5465164298CA96099E1853DE6E6C00B3D375FB81FC954BED3464A0` |
|
||||
| manifest | `A0AA8E95CB7F0BE52E21438094D1FFCDA53245C9E33CDC5A659D513EEF19D1EC` |
|
||||
|
||||
Round H `MBNWEB-20260711-H`는 이 실패 경계를 수정한 source commit `fa0eae7b61f57f134dfd30ebf1e59e9cc2cccfc5`(`fa0eae7`)와 다음 불변 입력으로 실행했다.
|
||||
|
||||
| 항목 | 값 |
|
||||
|---|---|
|
||||
| 계획 SHA-256 | `55C7755C2F874B4B012239117D4AB717BBCE194E7DCC8DA9B0E40D094FF8CA19` |
|
||||
| 회차 결과 SHA-256 | `AB70E61C86909F16FE407AAEEF0A5E668F8A4614375448E860C7BE47D687FA0D` |
|
||||
| 증적 manifest SHA-256 | `CD4EFD0CF64D9C905D7ABF732296E5A80DD4DE362DC7C88FD0D6967846955494` |
|
||||
| 서명된 Release x64 MSIX SHA-256 | `D51E8CB637860D9F0377AEE6FF691D7D954BA0FF7E30B1AB65443DA153BC5429` |
|
||||
| 명령 예산 | CONNECT 1, PREPARE 1, TAKE IN 1, 5001 자동 refresh 1, 5074 playlist NEXT 1, 5074 Page NEXT 1, TAKE OUT 1, disconnect 1, retry 0 |
|
||||
|
||||
실제 PGM에서는 5001 삼성전자 화면, 5074 page 1과 page 2를 차례로 확인했고 TAKE OUT 뒤 black을 확인했다. Network Monitoring의 최종 증분은 다음과 일치했다.
|
||||
|
||||
| 명령군 | request/success 또는 callback |
|
||||
|---|---|
|
||||
| HELLO | 1/1 |
|
||||
| LOAD 5001 / LOAD 5074 | 각각 1/1 |
|
||||
| PREPARE 5001 / PREPARE 5074 | 각각 3/3, 2/2 |
|
||||
| PLAY / `OnScenePlayed` | 4/4, callback 4 |
|
||||
| STOPALL | 1/1 |
|
||||
| UNLOAD 5001 / UNLOAD 5074 | 각각 1/1 |
|
||||
| FAILURE / ERROR | 0/0 |
|
||||
| BYE | request 1, 별도 success marker 0 |
|
||||
|
||||
BYE success marker가 0인 것은 계획의 허용 범위 0~1 안이며, 앱의 disconnected terminal state와 callback drain, 최종 PGM black을 함께 확인했으므로 정상 종료로 판정했다. 전 과정은 `OutcomeUnknown=false`, retry 0이었고 실패 뒤 추정 명령이나 반대 명령을 보내는 rollback은 필요하지 않았다. 정상 cleanup으로 승인된 TAKE OUT 1회, 두 scene unload, disconnect, 앱과 진단 listener 종료, 회차 전용 Live 설정·승인 환경 제거, PGM/Network Monitoring 창 상태 복원을 확인했다. 이후 기본 모드는 다시 `DryRun`이며 장애 rollback은 `Disabled` 전환 또는 직전 승인 패키지 복귀만 사용하고 vendor 설치·등록·라이선스는 변경하지 않는다.
|
||||
|
||||
Round H 전에 Core 790, Infrastructure 65, Playout 374개 테스트를 Debug/Release x64에서 각각 모두 통과했고, 실제 Oracle/MariaDB read-only query 55건, Visual Studio 2026 Debug/Release x64와 package build, 서명·설치·package context 검사를 통과했다. 같은 signed MSIX의 package-context DryRun도 `5001 PREPARE → TAKE IN → 자동 refresh 정확히 1회 → 5074 page 1 → page 2 → TAKE OUT`과 최종 IDLE, `OutcomeUnknown=false`, KTAP 미호출을 확인했다.
|
||||
|
||||
이 실제 Live PGM 증거는 회차에 허용된 5001과 5074에 한정된다. 35개 scene builder 전체 동등성은 자동 테스트, 55-query 실데이터 smoke와 [`SCENE_EQUIVALENCE.md`](SCENE_EQUIVALENCE.md) 매트릭스로 유지하며, 나머지 scene이 실제 PGM에서 각각 송출됐다는 의미로 기록하지 않는다.
|
||||
|
||||
## 절대 안전 규칙
|
||||
|
||||
1. 앱의 기본값은 항상 `DryRun`으로 유지한다.
|
||||
@@ -162,12 +203,14 @@ PREPARE는 다음 native 순서를 수행해야 한다.
|
||||
|
||||
### 5. Timer refresh
|
||||
|
||||
- 승인 범위에 포함된 경우에만 자동 refresh를 관찰한다. 첫 실행은 해당 cut의 원본 `m_time` 뒤, 이후 성공한 실행은 3초 간격이어야 한다.
|
||||
- 각 tick은 current entry/page의 fresh DB DTO를 사용하며 K3D 호출은 원본처럼 `Play(10)` → `GetPlayingScene(10)` → transaction mutation → `QueryVariables` → `EndTransaction` → `Prepare(10)` → `Play(10)` 순서다.
|
||||
- 승인 범위에 포함된 경우에만 자동 refresh를 관찰한다. 현재 안전 스케줄러는 직전 `OnScenePlayed` callback이 lifecycle queue에서 drain된 뒤에만 one-shot cooldown을 시작한다. 5001의 첫 cooldown은 온전한 2초이고, 성공한 refresh 뒤에는 callback drain 후 온전한 3초 recurring cooldown이다. 따라서 실제 dispatch 간격은 callback/drain 시간과 cooldown의 합이며, 원본의 절대 3초 cadence보다 의도적으로 길다.
|
||||
- 이 callback-aware cooldown은 recurring refresh를 제거한 것이 아니다. missed tick을 누적하거나 따라잡지 않고 합치며, refresh는 최대 하나만 in-flight다. 각 실행은 current entry/page의 fresh DB DTO를 사용해 retained on-air scene에 `BeginTransaction` → mutation → `QueryVariables` → `EndTransaction` → `Prepare(10)` → `Play(10)`을 한 번 수행한다.
|
||||
- timer refresh는 scene-level background와 fade effect를 다시 적용하지 않는다.
|
||||
- 앱의 `refreshActive`, `refreshNextAt`, `refreshLastSuccessAt`, fault code/message와 PGM 데이터를 함께 기록한다.
|
||||
- refresh가 실패하거나 timeout/unknown이면 fault latch가 켜지고 반복이 즉시 끝나야 한다. TAKE OUT 이외의 명령을 시도하지 않는다.
|
||||
- 명확히 성공한 TAKE OUT 뒤 native refresh state가 reset되면 전용 refresh fault marker만 사라져야 한다. `OutcomeUnknown`, `WEB_TIMEOUT` 또는 native quarantine 표시는 함께 reset되면 안 된다.
|
||||
- operator NEXT는 먼저 현재 refresh epoch를 원자적으로 stop한다. 그 시점에 Play callback이 pending이면 DB activity 대기나 scene query 전에 `PLAY_CALLBACK_PENDING`으로 즉시 fail-fast하고 자동 재시도하지 않는다. 명령 gate가 바로 풀리므로 TAKE OUT은 계속 사용할 수 있다. callback이 완료된 cooldown 구간에서는 NEXT를 정상 실행할 수 있다.
|
||||
- refresh epoch의 cancellation과 status는 같은 lock에서 교체·중지·갱신·완료한다. Stop 뒤 늦은 `onDelay`, 이전 세대의 success/fault/finally가 현재 세대나 stopped 상태를 다시 활성화할 수 없다.
|
||||
|
||||
### 6. TAKE OUT과 Disconnect
|
||||
|
||||
@@ -187,7 +230,7 @@ vendor monitor의 실제 명령 표기는 버전에 따라 다를 수 있으므
|
||||
| TAKE IN | fresh DB 결과의 두 번째 load/prepare 뒤 PLAY request/response | `OnScenePlayed`, 실제 object 값과 시각 상태 일치 |
|
||||
| Page NEXT | 같은 alias의 새 scene load/transaction/prepare/play 왕복 | playlist index 유지, page만 +1, 빈 slot clear/hide, refresh timer 정지 |
|
||||
| Playlist NEXT | 다음 cut load/prepare/play 왕복 | 다음 활성 항목과 page 0 표시 |
|
||||
| Timer refresh | PLAY, `GetPlayingScene` update transaction, prepare, PLAY의 중복 없는 왕복 | 첫 `m_time` 뒤 실행, 이후 3초, 같은 entry/page의 fresh 값, refresh 상태 정상 |
|
||||
| Timer refresh | retained on-air scene의 update transaction, prepare, PLAY 1회의 중복 없는 왕복 | callback drain 뒤 첫 full `m_time`, 이후 callback drain 뒤 full 3초 cooldown, 같은 entry/page의 fresh 값, refresh 상태 정상 |
|
||||
| TAKE OUT | STOP/STOPALL 대응 왕복 | `OnCutOut`/`OnStopAll`, 승인된 종료 화면 |
|
||||
| Disconnect | BYE 또는 대응 disconnect 왕복 | callback pending 0, 연결 해제 |
|
||||
|
||||
@@ -255,7 +298,7 @@ Gate A에 포함된 TAKE OUT을 한 번 실행한다. 성공 callback과 PGM 종
|
||||
|
||||
1. Gate A와 Gate B가 같은 회차에 기록돼 있다.
|
||||
2. 허용된 test cut과 selector만 사용했다.
|
||||
3. PREPARE → fresh DB TAKE IN → 승인된 Page NEXT/playlist NEXT → 원본 간격 timer refresh → TAKE OUT 순서가 중복 없이 완료됐다.
|
||||
3. PREPARE → fresh DB TAKE IN → 승인된 callback-aware timer refresh → Page NEXT/playlist NEXT → TAKE OUT 순서가 중복 없이 완료됐다. refresh는 callback drain 뒤 full initial/recurring cooldown과 회차 예산을 지켰다.
|
||||
4. 모든 결과가 명확한 성공이며 `OutcomeUnknown=false`다.
|
||||
5. Network Monitoring request/response와 PGM 화면이 같은 시각 증거로 남아 있다.
|
||||
6. 원본과 object 값, 표시, 색, 위치/크기, crop, path, asset, fade, page와 refresh 상태가 일치한다. Web preview에는 실제 asset path가 없다.
|
||||
|
||||
Reference in New Issue
Block a user