fix: complete legacy operator parity workflows

This commit is contained in:
2026-07-23 00:54:31 +09:00
parent 939c252d23
commit cf117de144
25 changed files with 2430 additions and 223 deletions

View File

@@ -35,16 +35,16 @@ legacy 행까지 숨기던 경로를 제거하고, 불완전한 개별 행만
|---|---|---|
| 원본 Scene 구현 | 완료 | builder 35/35, 실제 운영 runtime route 34개, 무alias 진단 전용 `s8086` 1개 |
| 원본 DB 연결 상태 감시 | 구현·자동 회귀 완료 | LegacyParityApp 시작 후 10초 간격으로 Oracle/MariaDB 상태를 확인하고 상태 전이 때만 native 로그를 남긴다. 운영자 입력·송출·자동 갱신이 시작되면 진단 조회를 취소하고 DB activity gate를 양보한다. 종료 시 monitor도 취소한다. 실제 DB 서버를 강제로 끊는 장애 주입은 하지 않았다. |
| 개발 MSIX 전체 UI/DB | **직전 패키지 실측 PASS · 최신 코드 물리 재검증 대기** | 등록 개발 패키지에서 실제 Windows 입력으로 UC1~UC7, GraphE, FSell, VIList, ThemeA, EList, PList 모달, 검색·키보드·컷/플레이리스트 drag를 검증했다. `readonly` 73, `graphe` 491, `catalog` 264, `screens` 664, `plist` 91, `dryrun-playout` 83 입력은 모두 PASS이고 blocked·state violation·warning은 전 회차 0이다. 그 뒤 즉시 선택, PROGRAM 미래 행 Space/전체 enabled 변경, ThemeA/UC6 빈 검색 전체 조회, 비교쌍 명시적 import와 설정 UI를 교정했으며 자동 검증은 통과했다. 이 변경을 포함한 새 AppX의 물리 입력·DB cleanup·로컬 상태 회차는 아직 최종 재실행 전이다. |
| 개발 Tornado2/PGM | **32/34 route 최신 실측 · s6001 4-action 실측 대기** | 최신 `LATEST-CORE-01`에서 `5001 → 선택 행 NEXT 5074 → Page NEXT → TAKE OUT` 6/6, 분할한 30-route 회차에서 30/30, 최신 `LATEST-PAGED-04`에서 5077/5088 경계 24/24를 실제 PGM으로 확인했다. 명령 실패·오류·retry·`OutcomeUnknown`은 0이다. `s6001`의 영상 비의존 4 action/18-stage workflow는 구현·static PASS지만 실제 PGM은 아직 실행하지 않았다. |
| 개발 MSIX 전체 UI/DB | **최신 패키지 실측 PASS** | 최신 등록 AppX에서 실제 Windows 입력으로 `read-only` 84, `dry-run-playout` 108, `plist` 106, `program-playlist-db` 65, `graphe` 501, `catalog` 299, `screens` 675, 합계 1,838입력을 검증했다. UC1~UC7, GraphE, FSell, VIList, ThemeA, EList, PList 모달, 검색·키보드·drag, 즉시 선택, PROGRAM 미래 행 enabled 변경과 DB create/save→fresh readback→delete/absence/cleanup이 모두 PASS다. 설정 picker 3종 취소와 비교쌍 1+8 병합/재실행 추가 0 로컬 상태도 PASS이며 warning·blocked·state violation은 0이다. |
| 개발 Tornado2/PGM | **33/34 runtime route code 최신 실측** | `LATEST-CORE-01` 6/6, 자산 비의존 30 route 30/30, `LATEST-PAGED-04` 24/24와 `S6001-04` 18/18을 실제 PGM으로 확인했다. `s6001`은 두바이유·WTI·브렌트유·금 4 action 범위이고 국가 영상 13 action은 제외한다. 모든 승인 회차는 retry 0, `OutcomeUnknown=false`, 최종 TAKE OUT/IDLE이다. `s6001`의 원본도 무시하는 `wonText`/`pattern` 보조 오브젝트 누락 로그는 아래에 별도 기록한다. |
| PageN/장기 실행 경계 | **최신 결합 코드 실측 완료** | `LATEST-PAGED-04`에서 `5077` 6행을 1/20부터 20/20까지 실제 Page NEXT하고, 마지막 페이지에서 playlist NEXT로 `5088` 12행 1/20으로 전환했다. 이전 scene unload와 최종 TAKE OUT/UNLOAD/IDLE도 확인했다. `LATEST-CORE-01`의 5074 page 1→2도 포함한다. |
| runtime 폴더/자산 설정 | 구현·자동 회귀 완료 | 선택한 Cuts root는 active `.t2s` alias 45개와 필수 built-in asset 9개를 모두 요구한다. 외부 제작 asset 14개는 없어도 설정을 수용하되 영향 경로만 제한한다. 빈 파일·reparse·중간 junction·root 이탈은 거부한다. 폴더 picker 취소와 최신 AppX 물리 검증은 최종 재실행 대기다. |
| 자동 회귀 | 완료, 최종 합계 갱신 대기 | 마지막 전체 .NET solution 실행은 3,115/3,115였다. 그 뒤 GraphE storage compatibility, 즉시 선택, PROGRAM 미래 행 enabled, ThemeA/UC6 빈 검색, 설정 validator, 비교 importer와 s6001 staged workflow의 focused/static 검증도 통과했다. 전체 solution 합계는 최종 재실행 뒤 갱신한다. 직전 별도 스크립트는 LegacyParityWeb 127/127, WebPlayout JavaScript 424/424이고 Debug build/rebuild는 warning 0, error 0이다. |
| runtime 폴더/자산 설정 | 구현·물리 검증 완료 | 선택한 Cuts root는 active `.t2s` alias 45개와 필수 built-in asset 9개를 모두 요구한다. 외부 제작 asset 14개는 없어도 설정을 수용하되 영향 경로만 제한한다. 빈 파일·reparse·중간 junction·root 이탈은 거부한다. 최신 AppX에서 디자인·리소스·배경 picker를 실제 클릭하고 취소했으며 설정 파일 불변을 확인했다. |
| 자동 회귀 | 완료 | Release x64 전체 .NET solution 3,182/3,182, LegacyParityWeb 150/150, WebPlayout JavaScript 424/424, 원본 scene 기준선 35/35와 staged PGM 정적 계약이 모두 실패 0으로 통과했다. |
| 고객 배포 MSIX | 현재 범위에서 보류 | 현재 결과는 unsigned 개발 패키지다. 고객용 version, Publisher, 서명 인증서, 업데이트 방식과 새 PC의 DB/Development Live 로컬 설정 배포안은 사용자가 배포 작업을 재개할 때 결정한다. |
## 2026-07-21~22 기존 DB 로드·편집 호환 재검수
실제 Oracle/MariaDB를 read-only로 다시 조회하고 직전 등록 개발 패키지를 DryRun으로 실행해
실제 Oracle/MariaDB를 read-only로 다시 조회하고 최신 등록 개발 패키지를 DryRun으로 실행해
다음을 확인했다. 아래 목록 조회와 편집 화면 확인 중 DB write 및 Tornado2/PGM 명령은 0건이다.
| 화면/경로 | 실제 DB 및 패키지 결과 | 송출 경계 |
@@ -59,30 +59,30 @@ legacy 행까지 숨기던 경로를 제거하고, 불완전한 개별 행만
| GraphE | 4개 테이블 7,776행 모두 raw 조회·편집 가능. Revenue 1,960/1, Growth 1,114/5, Sales 2,329/20, OperatingProfit 2,323/24(strict-ready/deferred), 합계 strict-ready 7,726행·deferred 50행 | 원본 저장 의미와 같은 정수 공백·TAB, 분기명 후행 TAB 및 완전히 동등한 중복행을 수용한다. conflicting 중복과 실제 불완전 payload는 계속 차단한다. 기존 이름 기반 GraphE 재생목록 36행은 36/36 fresh materialization됐다. |
| PList | 정의 23개/2,213행 전체 로드, scene alias 2,213/2,213, whole-list reject 0. fresh selection 1,617, 보류 596 | 행별 fresh payload·asset·PGM 검증은 사용할 때 별도 수행 |
직전 패키지 실제 클릭 결과는 C# snapshot과 DOM 행 수가 모두 일치했고, 검수 전 편성표 58행은
최신 패키지 실제 클릭 결과는 C# snapshot과 DOM 행 수가 모두 일치했고, 검수 전 편성표 58행은
끝까지 58행으로 유지됐다. ThemeA와 GraphE의 기존 원문을 단순 조회하거나 편집 화면에 여는 행위가
곧 송출 가능 승인을 뜻하지는 않는다.
## 2026-07-22 직전 등록 패키지 실제 입력 기준선
## 2026-07-22 최신 등록 패키지 실제 입력 기준선
당시 등록된 Development Mode 패키지의 Web 자산과 핵심 DLL이 당시 빌드 산출물과 같은지 hash로
확인한 뒤 여섯 회차를 실행했다. 패키지 입력 도구에도 빌드 AppX와 등록 AppX가 다르면 시작 전에
fail closed하는 검사를 추가했다. 모든 회차는 앱을 정상 종료했으며, 종료 뒤 Tornado2 연결은 0이었다.
아래 결과는 유효한 직전 물리 입력 기준선이지만, 이후 교정 사항을 포함한 최신 AppX의 최종 물리
재검증 결과로 확대하지 않는다.
최신 Development Mode 패키지의 Web 자산과 핵심 DLL을 빌드 AppX와 hash로 고정한 뒤 일곱
패키지 입력 회차와 한 로컬 상태 회차를 실행했다. 빌드 AppX와 등록 AppX가 다르면 시작 전에
fail closed한다. 모든 패키지 입력 회차는 앱을 정상 종료했 Tornado2 연결 없이 수행했다.
| 회차 | 실제 입력과 검사 | 결과 |
|---|---|---|
| `latest-readonly` | 73입력, outbound 29건, DB write 0, playout intent 0, 최종 playlist 3행 | PASS, blocked/violation/warning 0 |
| `latest-graphe` | 491입력, 5 화면 검사, 12 DB 검사, 승인 write 12건 | PASS, cleanup 확인, blocked/violation/warning 0 |
| `latest-catalog` | 264입력, ThemeA KRX/NXT와 EList 3 화면 검사, 11 DB 검사, 승인 write 7건 | PASS, cleanup 확인, blocked/violation/warning 0 |
| `latest-screens` | 664입력, UC1~UC7·GraphE·FSell·VI 등 15 화면/15 DB 검사, 승인 변경 22건 | PASS, cleanup 확인, blocked/violation/warning 0 |
| `latest-plist` | 91입력, create/save→fresh readback→delete/absence 3 DB 검사, 승인 write 3건 | PASS, cleanup 확인, blocked/violation/warning 0 |
| `latest-dryrun-playout` | 83입력, 3행 중 선택 행 기준 NEXT, drag feedback/state, PROGRAM 중 컷 선택, 안전한 tail double-click append | PASS, DB write 0, Tornado2 연결 0, blocked/violation/warning 0 |
| `read-only` | 84입력, 검색·키보드·컷/playlist drag와 모달·선택 상태 | PASS, blocked/violation/warning 0 |
| `dry-run-playout` | 108입력, 선택 행 기준 NEXT, PROGRAM 미래 행 enabled, F2/F3, F8/Escape, drag/double-click append | PASS, DB write 0, Tornado2 연결 0, blocked/violation/warning 0 |
| `plist` | 106입력, recovery exact delete와 create/save→물리 double-click fresh readback→delete/absence | PASS, cleanup 확인, blocked/violation/warning 0 |
| `program-playlist-db` | 65입력, PROGRAM 상태 named playlist create/save/fresh readback/delete/absence와 최종 IDLE | PASS, cleanup 확인, blocked/violation/warning 0 |
| `graphe` | 501입력, 4 화면 identity/action/double-click과 각 create/save→fresh readback→delete/absence | PASS, cleanup 확인, blocked/violation/warning 0 |
| `catalog` | 299입력, ThemeA KRX/NXT·EList 빈 검색/행 조작과 create/edit/save→fresh readback→delete/absence | PASS, cleanup 확인, blocked/violation/warning 0 |
| `screens` | 675입력, UC1~UC7·GraphE·FSell·VIList 15 화면과 15 DB 검사 | PASS, cleanup 확인, blocked/violation/warning 0 |
| `local-state` | 설정 폴더 picker 3종 실제 클릭/취소, 설정 파일 불변, 비교쌍 1+8=9와 재실행 추가 0 | PASS, playout intent 0, retry 0 |
`latest-dryrun-playout`의 식별 결과는 staged `legacy-stock-00000002`, 선택
최신 `dry-run-playout`의 식별 결과는 staged `legacy-stock-00000002`, 선택
`legacy-stock-00000003`, NEXT `legacy-stock-00000001`, 안전 append
`legacy-stock-00000004`다. PROGRAM 뒤 컷 선택은 0번이고 playlist는 3행에서 4행으로 정확히
`legacy-stock-00000008`이었다. PROGRAM 뒤 컷 선택은 0번이고 playlist는 3행에서 4행으로 정확히
한 행만 늘었다.
## 실제 PGM 검증 경계
@@ -107,8 +107,15 @@ fail closed하는 검사를 추가했다. 모든 회차는 앱을 정상 종료
`5088` 전환, 이전 scene unload와 최종 TAKE OUT/UNLOAD/IDLE을 24/24로 재검증했다. 결함이
있던 최초 실행과 이전 `PAGED-01`은 최신 승인 근거로 사용하지 않는다.
- `s6001` 중 국가 영상이 필요 없는 두바이유·WTI·브렌트유·금 4 action은 global
`images\주유기merge.png`, `images\35752913_l.jpg`를 고정 검증하는 18-stage staged workflow로
구현했고 static audit가 통과했다. 실제 PGM 회차는 아직 실행 전이므로 성공 증거에 포함하지 않는다.
`images\주유기merge.png`, `images\35752913_l.jpg`를 고정 검증하는 `S6001-04`에서
18/18을 완료했다. 물리 double-click 4행 생성, 각 action의 activate→TAKE IN→settled
PROGRAM→TAKE OUT과 최종 IDLE을 확인했다. 합산 LOAD 4, PREPARE 8, PLAY 8, UNLOAD 4가
성공했고 안전 차단·위반·retry·`OutcomeUnknown`은 0이다.
- authoritative `6001.t2s`에는 원본 코드가 호출하는 보조 `wonText`/`pattern` 오브젝트가 없다.
최초 송출과 자동 갱신 8회에서 `VALUE_SET wonText`, `FACE_COLOR wonText`,
`VALUE_SET pattern`이 각각 8회 실패했고 관련 원인 `ERROR` 줄은 120개다. 원본
`s6001.cs`도 같은 호출을 빈 `catch`로 무시한다. 필수 movie/unit/수치/색/PREPARE/PLAY와
실제 네 장면 화면은 정상이라, 이 상속된 template 제한을 명시한 4 action만 성공으로 채택한다.
- `s5006`의 큐브 배경 1개와 `s6001`의 국가 영상 13개는 asset preflight에서 관련 action만
fail closed한다. 이 14개가 현재 남은 외부 제작 자산 경계다.
@@ -119,13 +126,16 @@ fail closed하는 검사를 추가했다. 모든 회차는 앱을 정상 종료
- [`8001 known-state TAKE OUT`](../artifacts/pgm-evidence/MBNWEB-20260722-RECOVERY8001-01)
- [`30 route 20~29 PGM`](../artifacts/pgm-evidence/MBNWEB-20260722-THIRTY20-29-01)
- [`최신 5077/5088 20-page PGM`](../artifacts/pgm-evidence/MBNWEB-20260722-LATEST-PAGED-04)
- [`s6001 영상 비의존 4 action PGM`](../artifacts/pgm-evidence/MBNWEB-20260722-S6001-04)
- [`구/신규 30개 송출 비교`](LEGACY_NEW_PLAYOUT_COMPARISON_20260719.md)
- [`직전 read-only 입력 PASS`](../artifacts/package-input-smoke/legacy-package-input-20260721T221024787Z-latest-readonly.json)
- [`직전 GraphE 입력/DB PASS`](../artifacts/package-input-smoke/legacy-package-input-20260721T221122292Z-latest-graphe.json)
- [`직전 ThemeA/EList 입력/DB PASS`](../artifacts/package-input-smoke/legacy-package-input-20260721T221252795Z-latest-catalog.json)
- [`직전 전체 화면/DB PASS`](../artifacts/package-input-smoke/legacy-package-input-20260721T221352946Z-latest-screens.json)
- [`직전 PList 입력/DB PASS`](../artifacts/package-input-smoke/legacy-package-input-20260721T221553250Z-latest-plist.json)
- [`직전 DryRun 송출 입력 PASS`](../artifacts/package-input-smoke/legacy-package-input-20260721T221635626Z-latest-dryrun-playout.json)
- [`최신 read-only 입력 PASS`](../artifacts/package-input-smoke/legacy-package-input-20260722T113449758Z.json)
- [`최신 DryRun 송출 입력 PASS`](../artifacts/package-input-smoke/legacy-package-input-20260722T115610505Z.json)
- [`최신 PList CRUD/recovery PASS`](../artifacts/package-input-smoke/legacy-package-input-20260722T123711141Z.json)
- [`최신 PROGRAM 재생목록 CRUD PASS`](../artifacts/package-input-smoke/legacy-package-input-20260722T124248490Z.json)
- [`최신 GraphE 입력/DB PASS`](../artifacts/package-input-smoke/legacy-package-input-20260722T124550096Z.json)
- [`최신 ThemeA/EList 입력/DB PASS`](../artifacts/package-input-smoke/legacy-package-input-20260722T124717969Z.json)
- [`최신 전체 화면/DB PASS`](../artifacts/package-input-smoke/legacy-package-input-20260722T124819923Z.json)
- [`설정 picker·비교 import 로컬 상태 PASS`](../artifacts/package-input-smoke/legacy-package-local-state-20260722T021114553Z-final-r3.json)
`artifacts`의 개발 장비 증거에는 로컬 실행 상태가 포함될 수 있으므로 고객 MSIX나 Git 배포물에
넣지 않는다.
@@ -139,8 +149,8 @@ fail closed하는 검사를 추가했다. 모든 회차는 앱을 정상 종료
현재 authoritative 원본 Cuts에도 없다. 자산 없이 진행한다는 사용자 결정에 따라 제공 전에는
관련 action만 안전하게 차단하며, 이는 현재 작업 전체의 차단 사유가 아니다. `s6001`의 영상
비의존 4 action은 별도 실제 PGM 검증 대상으로 계속 진행한다. 나중에 자산을 받으면 trusted
root·빈 파일·reparse·경로 이탈 검사를 통과시킨 뒤 `s5006`과 국가 영상 action을 실제 PGM에서 검증한다.
비의존 4 action은 실제 PGM 검증을 완료했다. 나중에 자산을 받으면 trusted root·빈 파일·reparse·
경로 이탈 검사를 통과시킨 뒤 `s5006`과 국가 영상 action을 실제 PGM에서 검증한다.
### 2. 기존 플레이리스트 데이터 정합성
@@ -156,8 +166,8 @@ materialization하여 `1,617 복원 / 596 보류`로 갱신됐다. 596행은 KRX
원본 `종목비교.dat` 8쌍을 현재 로컬 순서 뒤에 중복 없이 병합하는 명시적 importer도 구현했다.
원본 파일은 고정된 trusted path에서 읽기 전용으로 열고 8쌍을 모두 resolve한 뒤에만 atomic하게
저장하며, 실패 시 현재 파일을 보존한다. 실제 최신 AppX에서 `현재 1쌍 + 원본 8쌍 = 9쌍`과 두 번째
실행의 `추가 0`을 확인하는 로컬 상태 smoke는 아직 실행 전이다.
저장하며, 실패 시 현재 파일을 보존한다. 실제 최신 AppX 로컬 상태 smoke에서 `현재 1쌍 + 원본
8쌍 = 9쌍`, 두 번째 실행의 `추가 0`, 원본 SHA-256 불변을 확인했다.
### 3. 고객 배포
@@ -168,8 +178,8 @@ allowlist, vendor hash, STA 직렬화와 대상 identity 검사는 그대로 유
## 완료 조건
최신 AppX의 전체 물리 입력/DB cleanup/설정·비교 import 로컬 상태 재검증, `s6001` 영상 비의존
4 action의 실제 PGM 검증, 기존 보류 행의 payload/asset/PGM 경계 판정을 마치면 현재 개발 장비의
대체 운영 기준선을 확정다. 외부 제작 자산 14개가 없는 action은 제공 전까지 명시적으로 차단한
상태가 정상 기준이다. 고객 서명 MSIX의 clean 설치·업데이트·새 PC 설정 검증은 사용자가 배포를
재개할 때 별도 완료 조건으로 적용한다.
최신 AppX의 전체 물리 입력/DB cleanup/설정·비교 import `s6001` 영상 비의존 4 action의
실제 PGM 검증까지 완료했으므로, 현재 개발 장비에서 검증 가능한 범위의 대체 운영 기준선은
확정다. 외부 제작 자산 14개가 없는 action과 fresh identity를 증명할 수 없는 596행은 제공·DBA
결정 전까지 명시적으로 차단한 상태가 정상 기준이다. 고객 서명 MSIX의 clean 설치·업데이트·새 PC
설정 검증은 사용자가 배포를 재개할 때 별도 완료 조건으로 적용한다.