Document signed 1.0.3 migration verification

This commit is contained in:
2026-07-12 05:54:21 +09:00
parent a01836a2d7
commit a481c96c39
7 changed files with 27 additions and 23 deletions

View File

@@ -33,17 +33,19 @@
| LF-010 | P1 | 원본 F2/F3 배경 디렉터리 동등성 | 코드 적용 / 외부자산·패키지 검증 대기 | 원본 `MBN_STOCK_N/MainForm.cs:4008-4054`, `btnback_Click`, `ckback_CheckedChanged`; 현재 `MainWindow.Background.cs`, `PlayoutSceneCompositionFactory`, `TrustedPlayoutAssetPath`, `ValidatedPlayoutOptions`; 문서 `docs/TRUSTED_BACKGROUND_ROOT.md` | Cuts gate를 유지한 채 별도 `LegacyBackgroundDirectory`를 추가했고, 생략 시 원본처럼 `SceneDirectory\..\배경`을 계산한다. F2는 유효할 때만 picker 전 `기본.vrv`를 복원하고 F3-on은 항상 기본 파일을 다시 검증한다. root escape·조상/파일 reparse·hardlink·누락·opened-handle final path를 fail closed로 검사하며 Cuts fallback은 없다. 이 장비의 원본 `bin\Debug\배경``기본.vrv`는 실제로 없어 현재 기본 배경은 잠긴다. | Core Debug/Release 1,259/1,259, Playout Debug/Release 387/387과 앱 Debug/Release x64 build를 통과했다. signed 패키지에서 별도 root 상태 메시지와 F2/F3를 확인하고, 자산 제공 뒤 다음 PREPARE mutation/PGM은 승인 회차에서 검증한다. |
| LF-011 | P1 | `종목비교.dat` 기존 저장쌍 이전 | 적용 중 | 원본 `MBN_STOCK_N/Control/UC3.cs:34-55,181-185`, `UC3_Load`, `Data_Load`, `File_Save`; 현재 `src/MBN_STOCK_WEBVIEW.Core/Data/LegacyComparisonPairImport.cs`, `MainWindow.LegacyComparisonImport.cs`, `Web/comparison-import-workflow.js`, `Web/app.js`; 테스트 `LegacyComparisonPairImportServiceTests.cs`, `comparison-import-workflow.test.cjs`, `comparison-import-app-integration.test.cjs` | 원본 파일은 CP949 358바이트, 비어 있지 않은 8행, 각 행 정확히 9필드이며 0~3열만 값이 있다는 감사 fixture를 SHA-256 `1EE76BC4…BFC0D2F2`로 고정했다. Web이 경로를 전달하지 않는 고정 read-only source, reparse/크기/2회 quiescent snapshot 검사, strict CP949/9필드 parser, 현재 Oracle/MariaDB 종목·해외 identity exact read, 고정 시장명과 해외 동명이름 충돌 차단, 전체 중복·500쌍 경계, 명시적 버튼과 one-time marker/rollback을 구현했다. 원본은 수정하지 않고 성공 뒤 WebView private `localStorage` schema만 사용한다. 이 장비의 실제 설정으로 동일 서비스 read-only smoke를 실행해 8행 전부와 SHA-256이 일치하고 모든 identity가 해소됨을 확인했다. 다만 패키지 UI 버튼→localStorage→재시작 marker까지의 1회 실행은 아직 하지 않았으므로 완료로 올리지 않는다. | 실제 패키지에서 명시적 버튼 1회로 8행을 모두 fresh DB 재검증하고 local schema/hash/순서를 확인한다. 같은 profile의 두 번째 실행은 marker로 차단되고, 원본 변경·손상·동명이름·기존쌍 중복은 부분 저장 없이 전체 fail closed여야 한다. |
| LF-012 | P1 | FSell/VI 원본 `Data`의 안전한 이전과 설정 문서 | 적용 중 | 원본 `MBN_STOCK_N/MainForm.cs:338-339`, `FSell.cs:31-88`, `VIList.cs:31-34,137-139`; 현재 `src/MBN_STOCK_WEBVIEW.Core/Data/LegacyManualOperatorDataImport.cs`, `src/MBN_STOCK_WEBVIEW.Infrastructure/Playout/LegacyManualOperatorDataImporter.cs`, `MainWindow.ManualLists.cs`, `Web/manual-lists-workflow.js`, `Web/manual-lists-ui.js` | UserProfile 아래 고정 원본 경로만 read-only로 두 번 읽고 strict CP949, FSell 파일별 5행+종료 레코드, VI 9열·최대 100건·4,000바이트를 검사한다. 명시적 확인 뒤 private store가 완전히 비어 있을 때만 4개 staged 파일을 no-overwrite로 옮기고 production parser readback 후 v1 marker를 마지막에 기록한다. rollback을 확정하지 못하면 OutcomeUnknown quarantine이며 자동 재시도하지 않는다. 실제 source smoke는 FSell 15행·VI 9건·aggregate SHA-256 `fd39a363…a2114`였고, 이 장비의 private 4개 파일은 이미 원본과 각각 byte-identical이어서 `DestinationNotEmpty`로 source read 전 중단했으며 전후 SHA가 같았다. | 새 빈 package profile fixture에서 버튼→4파일→marker→재시작 차단을 확인한다. 현재 운영 profile에서는 기존 동일 파일을 덮어쓰거나 marker를 임의 생성하지 않는다. |
| LF-013 | P1 | generic native `bridge-error` 표시 | 적용 중 | producer `MainWindow.xaml.cs:431-437`, `MainWindow.Playout.cs:121-126,370-375`; 현재 consumer `Web/app.js:6446-6454`, `handleBridgeError`, `handleNativeMessage`; 테스트 `tests/Web/operator-ui-app-integration.test.cjs:431-435` | 재감사 당시 소비자가 없던 오류 표시가 현재 작업 트리에 반영됐다. bounded 메시지와 운영 로그 표시는 확인되지만 최종 회귀·패키지 반영 전이라 완료로 올리지 않는다. | malformed status/quarantine payload fixture로 `bridge-error` 1회, bounded toast/log, playout state 불변을 확인하고 전체 Web 테스트와 패키지 UI를 다시 검증한다. |
| LF-014 | P2 | 영구 운영 로그 | 적용 중 | 원본 `MBN_STOCK_N/MainForm.cs:84-128,132-180,542-543,675,776`, `initAliveChecker`, `LogWrite`, `timerAliveChecker_Tick`; 현재 `src/MBN_STOCK_WEBVIEW.Infrastructure/Diagnostics/NativeOperatorLogWriter.cs`, `NativeOperatorLogTransitions.cs`, `MainWindow.NativeOperatorLog.cs` | `%LOCALAPPDATA%\MBN_STOCK_WEBVIEW\Logs\Log_MMdd.log`Startup/Shutdown, Oracle/MariaDB·Tornado 전이, 실행 gate를 통과한 PREPARE/TAKE IN/NEXT/TAKE OUT의 요청과 terminal 결과만 기록한다. 4MiB/31일, provider별 중복 억제, single-command terminal, reparse/handle 검증을 적용했다. `TimedOut`과 불명확 결과는 `OutcomeUnknown` 한 번으로 끝내며 late result를 기록하지 않는다. 공개 record는 폐쇄 enum만 받아 requestId, 장면, 경로, SQL, DB message와 예외 문자열을 구조적으로 받을 수 없다. | Debug/Release 자동 검증 후 package context에서 시작→DB/DryRun 상태→종료를 실행하고 파일 재시작 잔존, 중복 억제, 금지 문자열 부재를 확인한다. |
| LF-013 | P1 | generic native `bridge-error` 표시 | 완료 | producer `MainWindow.xaml.cs`, `MainWindow.Playout.cs`; consumer `Web/app.js` `handleBridgeError`/`handleNativeMessage`; 테스트 `operator-ui-app-integration.test.cjs` | bounded toast/log로 소비하며 malformed status/quarantine payload에서 playout state를 변경하지 않는다. 전체 Web 371/371과 signed 1.0.3 패키지 반영을 확인했다. | 새 native error producer를 추가할 때마다 같은 bounded consumer 계약을 유지한다. |
| LF-014 | P2 | 영구 운영 로그 | 완료 | 원본 `MBN_STOCK_N/MainForm.cs:84-180`; 현재 `NativeOperatorLogWriter.cs`, `NativeOperatorLogTransitions.cs`, `MainWindow.NativeOperatorLog.cs` | `%LOCALAPPDATA%\MBN_STOCK_WEBVIEW\Logs\Log_MMdd.log`폐쇄 event/state만 기록하며 4MiB/31일, 중복 억제, reparse/handle 검증, single terminal/OutcomeUnknown 규칙을 적용한다. signed 1.0.3 package context에서 Startup→DryRunReady→Oracle/MariaDB Healthy→Shutdown→재시작이 같은 파일에 잔존했고 SQL·경로·인증·requestId 금지 문자열은 0건이었다. | 운영 회차에서도 로그를 명령 재시도 근거로 사용하지 않고 authoritative 출력과 함께 판독한다. |
| LF-015 | P2 | 호출자가 없는 native bridge handler | 완료 | `MainWindow.xaml.cs`, `OnWebMessageReceived`; 테스트 `tests/Web/operator-ui-app-integration.test.cjs` | Web 호출자가 없던 `open-external``reload` message case를 native allowlist에서 제거했다. 외부 navigation/new-window 처리와 WebView process failure의 내부 reload 복구 메서드는 별도 native event 경로로 유지한다. | 정적 계약 테스트에서 두 message case와 Web 발신 literal이 모두 없음을 확인했다. |
| LF-016 | P2 | 실제 preview 이미지·영상 | 외부자산 필요 | `docs/MIGRATION.md:73-74`; 원본 `MBN_STOCK_N/MainForm.cs:1448-1462,1894-1911,2919-2921` | 현재 preview는 안전한 DTO/mutation 텍스트 중심이다. 실제 이미지·영상 연결은 후속 자산이다. 다만 원본 thumbnail 호출과 watcher는 주석 또는 미호출이므로 활성 원본 동등성의 P0/P1 blocker로 보지 않는다. | 승인된 preview 자산이 생기면 asset root와 노출 정보 검사를 거쳐 패키지 화면에서 확인한다. |
| LF-017 | P1 | 모든 업무 탭에서 계속 보이는 종목 검색·31컷 | 적용 중 | 원본 `MBN_STOCK_N/MainForm.Designer.cs:2022-2036,2454-2462`; 현재 `Web/index.html`의 독립 `stock-panel`, `Web/app.js``renderStockWorkflow`; 테스트 `operator-ui-app-integration.test.cjs` | 종목 검색·31컷을 catalog panel 밖의 독립 열로 옮기고 모든 업무 메뉴에서 항상 표시한다. 1920 브라우저에서 11개 메뉴를 이동해 검색어, 표시, 31개 행이 유지되고 문서 가로 overflow가 없음을 확인했다. | signed MSIX에서 실제 DB 검색 결과·선택 종목이 모든 탭 전환 뒤 유지되고 컷 추가가 같은 identity를 쓰는지 확인한 뒤 완료로 올린다. |
| LF-018 | P2 | 원본 트리·컷 목록 일괄 추가 제스처 | 적용 중 | 원본 부모 double-click `MBN_STOCK_N/Control/UC1.cs:141-180`; 소스 컷 Ctrl/Shift 선택 `MBN_STOCK_N/MainForm.cs:3427-3525,3534-3549,3635-3643`; 현재 `Web/legacy-batch-selection-workflow.js`, `Web/app.js`; 테스트 `legacy-batch-selection-*.test.cjs` | 종목 31컷의 plain/Ctrl/Shift/Ctrl+Shift 선택, 단일 double-click, `선택 컷 추가`를 포팅했다. 해외·환율·지수 fixed source의 섹션 `전체 추가`는 모든 자식을 먼저 materialize한 뒤 원본 순서로 한 번에 commit하며, 수동/지원불가가 한 건이라도 있으면 부분 추가 없이 전체 차단한다. 실제 브라우저에서 5개 선택, 해외 43개 순서 추가, 수동 혼합 섹션 0건 추가를 확인했다. | signed MSIX 확인 뒤 업종·비교·테마 등 전용 source group의 부모 전체 추가가 원본에서 실제로 필요한 범위를 계속 분리 포팅한다. source drag/drop 자체는 오조작 검증 뒤 결정한다. |
| LF-019 | P1 | 저장 PList의 `테마_NXT` stale code 복원 | 적용 중 | 원본 `Control/UC4.cs`, `Scene/s5074.cs`, `s5077.cs`, `s5088.cs`; 현재 `LegacyNamedNxtThemeRestoreService`, `MainWindow.NamedNxtThemeRestore.cs`, `Web/named-nxt-theme-restore-workflow.js`; 상세 `docs/NAMED_NXT_THEME_RESTORE.md` | 원본처럼 제목 exact lookup으로 현재 Maria code를 찾고 현재가 전용 5/6/12행, 정렬 fallback, 00~12 PRE/13~23 AFTER, fresh PageN을 닫힌 batch로 복원한다. 실제 활성 48행/24제목은 모두 current identity가 유일하고 저장 code 48개가 전부 stale였지만 현재 preview가 전부 비어 있어 48행 모두 `PreviewEmpty`로 정상 차단됐다. KRX 테마는 후보가 아니다. | Maria `SB_ITEM`/`v_all_stock` live 연계가 복구된 뒤 같은 read-only audit에서 한 행 이상 live item을 확인하고, fresh page preflight와 Debug/Release/MSIX UI를 검증한다. 실제 PGM은 별도 승인 회차가 필요하다. |
| LF-020 | P2 | 원본 초기 업무 화면 `해외` | 적용 중 | 원본 `MainForm.Designer.cs`, 첫 TabPage `해외`; 현재 `Web/index.html`, `Web/app.js` 초기 `activeMarket` | 원본은 첫 업무 탭인 해외로 시작하지만 재감사 당시 새 앱은 dashboard로 시작했다. dashboard는 진단 화면으로 유지하면서 초기 active identity, 제목과 최초 조회를 해외로 맞추는 중이다. | Web 초기화 테스트와 signed MSIX 첫 실행에서 해외만 active이고 최초 DB 요청이 중복되지 않는지 확인한다. |
| LF-021 | P2 | 업무 탭 드래그 순서 변경 | 코드 적용 / 패키지 검증 대기 | 원본 `MainForm.Designer.cs:1063-1066` TabControl drag events, `MainForm.cs:3183-3312` `tab_MouseDown`/`tab_MouseMove`/`tab_DragOver`/`swapTabPages`; 현재 `Web/market-nav-reorder.js`, `Web/app.js``marketNavReorder` controller; 테스트 `market-nav-reorder*.test.cjs` | dashboard는 첫 위치에 고정하고 원본 10개 업무 button만 `data-market` identity로 교환한다. active DOM node와 view/DB/playlist state는 건드리지 않으며 local/session storage에 저장하지 않는다. drag token은 닫힌 형식으로 검증하고, Alt+위/아래는 인접 교환과 첫·마지막 경계를 제공한다. 입력, modal, PREPARE 이후 잠금에서는 실행하지 않는다. | 전용 10/10과 전체 Web 353/353, cut fixture, Debug/Release x64 build가 통과했다. signed MSIX에서 pointer drag, 키보드 포커스, active click 유지와 재시작 시 기본 순서 복원을 확인한다. |
| LF-022 | P2 | GraphE 검색 Enter 다음 찾기 | 적용 중 | 원본 `GraphE.Designer.cs:229`, `GraphE.cs:605`, `downSearch_Click`; 현재 `Web/manual-financial-ui.js`; 테스트 `manual-financial-ui.test.cjs` | 목록 수락 전 Enter는 기존 DB 조회를 유지하고, 이후 Enter는 현재 선택 다음 행부터 대소문자 무시 Contains로 한 건을 찾아 load한다. 원본처럼 마지막에서 처음으로 순환하지 않으며 pending·잠금·숨김 modal은 무동작이다. | GraphE 모드 관련 테스트 39/39 후 signed MSIX에서 한 건·마지막·검색어 변경을 확인한다. |
| LF-023 | P2 | 전문가 추천 편집기 Delete 키 | 적용 중 | 원본 `UC6.Designer.cs:571`, `UC6.cs:230`; 현재 `Web/operator-catalog-ui.js`; 테스트 `operator-catalog-ui.test.cjs` | expert draft의 포커스/선택 행에서만 Delete를 기존 `removeDraftItem`으로 처리한다. ThemeA, modal 밖, input/textarea/contenteditable에는 영향이 없고 잠금·DB write 중에는 삭제하지 않고 event만 dialog 내부에서 격리한다. | Web 전체 회귀와 signed MSIX EList/전문가 편집 modal에서 확인한다. |
| LF-020 | P2 | 원본 초기 업무 화면 `해외` | 완료 | 원본 `MainForm.Designer.cs` 첫 TabPage `해외`; 현재 `Web/index.html`, `Web/app.js`; 테스트 `operator-ui-app-integration.test.cjs` | dashboard는 진단 화면으로 유지하 초기 active identity/제목/요청을 해외로 맞춰다. 실제 브라우저에서 해외만 active, 최초 요청 1회, dashboard 진입·복귀를 확인했고 signed 1.0.3에 같은 Web 31개가 byte 일치했다. | 후속 탭 추가 시에도 초기 identity를 순번이 아닌 `data-market`으로 유지한다. |
| LF-021 | P2 | 업무 탭 드래그 순서 변경 | 완료 | 원본 `MainForm.cs:3183-3312`; 현재 `Web/market-nav-reorder.js`, `Web/app.js`; 테스트 `market-nav-reorder*.test.cjs` | dashboard는 첫 위치에 고정하고 10개 업무 identity만 drag 교환/Alt+위·아래로 이동한다. active view/DB/playlist는 불변이고 입력·modal·PREPARE 잠금에서 fail closed하며 세션 종료 시 기본 순서로 돌아간다. 실제 브라우저에서 `Alt+Down` 후 active 해외 유지와 reload 초기화를 확인했다. | signed 1.0.3 패키지에 Web 31개 일치로 반영했다. |
| LF-022 | P2 | GraphE 위/아래 찾기 | 완료 | 원본 `GraphE.cs:338-379,605-611`; 현재 `Web/manual-financial-ui.js/.css`; 테스트 `manual-financial-ui.test.cjs` | `위로 찾기`/`아래로 찾기` 버튼과 Enter 다음 찾기를 포팅했다. trim·대소문자 무시 Contains, 현재 행 전/후, no-wrap, 모든 pending·잠금·hidden 차단을 유지한다. 원본의 `i > 0` 첫 행 누락은 명백한 off-by-one으로 보고 첫 행도 정상 후보에 포함했다. | GraphE 집중 20/20, 전체 Web 371/371과 signed 1.0.3 Web 일치 통과. |
| LF-023 | P2 | ThemeA/전문가 편집기 Delete 키 | 완료 | 원본 `ThemeA.cs`/`UC6.cs`; 현재 `Web/operator-catalog-ui.js`; 테스트 `operator-catalog-ui.test.cjs` | ThemeA와 expert draft의 포커스/선택 행 하나를 기존 `removeDraftItem`으로 삭제하고 input/textarea/contenteditable, modal 밖, 잠금/DB write 중에는 상태를 변경하지 않는다. 삭제 후 inputIndex를 재배열하며 native 요청은 보내지 않는다. | 관련 UI/workflow/bridge 32/32, 전체 Web 371/371과 signed 1.0.3 Web 일치 통과. |
| LF-024 | P2 | GraphE 종목명 헤더 정렬 | 완료 | 원본 `GraphE.cs:258-280`; 현재 `Web/manual-financial-ui.js/.css`; 테스트 `manual-financial-ui.test.cjs` | `종목명 ↕` 첫 click 내림차순/둘째 click 오름차순을 세션 로컬 display order로 적용했다. 선택 snapshot/native/playlist는 불변이고 위/아래 찾기는 현재 표시 순서를 따른다. 새 화면/목록에서 오름차순으로 초기화한다. | 네 모드·한글/ASCII·빈/단일·pending·정렬된 find 집중 20/20, 전체 Web 371/371 통과. |
| LF-025 | P2 | UC7 거래정지 종목명 헤더 정렬 | 완료 | 원본 `Control/UC7.cs:173-188`; 현재 `Web/trading-halt-workflow.js`, `Web/app.js`, `Web/index.html`; 테스트 `trading-halt-name-sort-app-integration.test.cjs` | `종목명 ↕` 첫 click 내림차순/둘째 click 오름차순을 표시 order에만 적용했다. 동명은 market+stockCode로 결정적으로 정렬하고 선택 identity를 유지하며 새 검색은 server 순서로 초기화한다. DB/native/playlist 변경은 없다. | 집중 18/18, 전체 Web 371/371, 실제 브라우저에서 접근 라벨/가로 overflow 0, signed 1.0.3 Web 일치 통과. |
## 활성 PLAY_LIST 2,213행 재분류

View File

@@ -72,7 +72,7 @@ WebView는 `https://app.mbn.local` 가상 호스트로 패키지 내부 파일
- 자동 계약 검증: 328 fixed + 44 industry + 31 stock + 9 comparison의 412 action 매트릭스, typed DTO, 저장·복원 fail-closed 경계
- 적용 중: PList의 기존 한국어 `DC_TITLE`/`LIST_TEXT` 복원. 기존 운영 DB 행을 원본과 문자 단위로 대조하기 전에는 완료로 판정하지 않음
- 화면/계약 구현·운영 검증 대기: GraphE·FSell·VI 항목을 포함한 manual named save→reload→fresh identity/version/page plan 복원, ThemeA/EList의 KRX/NXT·동명이름·코드 identity 보존
- 미적용: 원본 `Data\종목비교.dat`, FSell, VI 데이터를 패키지 private 저장소로 전하게 옮기는 one-time import
- 코드 적용·운영 검증 대기: 원본 `Data\종목비교.dat`, FSell, VI를 고정 read-only source에서 strict parser·hash·fresh identity·durable intent로 검증한 뒤 private 저장소로 전하는 one-time importer. 실제 package profile의 명시적 1회 실행은 아직 수행하지 않음
- 외부자산 필요: `s5006``Video\큐브배경.vrv`, `s6001` 해외지수의 국가별 영상 13개. 현재 alias-only cut 검사를 asset-ready 근거로 사용하지 않음
- 운영 동등성 미검증: GraphE, PList/AList, ThemeA, EList의 실제 Oracle DB-W와 FSell/VI 운영 파일 write/read-back
- 실제 PGM 제한: Round H의 `5001`/`5074`만 완료 증거가 있으며 나머지 장면·화면은 별도 승인 회차가 필요함

View File

@@ -278,11 +278,11 @@
| 항목 | 결과 |
|---|---|
| 자동 테스트 | Core 1,116개, Infrastructure 125개, Playout 374개가 Debug/Release x64에서 각각 통과했고 Web workflow·bridge 235/235도 통과했다. 412 action의 폐쇄형 매트릭스, 계약·경계·복원 실패와 native fail-closed gate를 검증한다. |
| 자동 테스트 | Core 1,259개, Infrastructure 173개, Playout 387개가 Debug/Release x64에서 각각 통과했고 Web workflow·bridge 371/371도 통과했다. 412 action의 폐쇄형 매트릭스, 계약·경계·복원 실패와 native fail-closed gate를 검증한다. |
| 실제 운영 DB write | **미실행.** GraphE, named playlist, ThemeA, EList의 mutation executor는 fake/계약 테스트로 검증했으며 운영 DB에는 쓰지 않았다. FSell/VI는 테스트용 격리 저장소만 사용했다. |
| 실제 Tornado2 PGM | 제한된 승인 회차에서 `5001`, `5074` page 1·2, TAKE OUT을 확인했다. 이는 전체 412 action, GraphE, FSell, VI, ThemeA, EList, 이름 있는 playlist 각각의 UI 동등성 검증이 아니다. |
| PList legacy 복원 | raw restore와 fail-closed materialization 계약은 구현했다. 실제 기존 `DC_TITLE`/`LIST_TEXT`의 한국어 무손상 복원은 적용 중이며 완료 증거가 없다. |
| manual named save | GraphE·FSell·VI descriptor 계약과 복원 테스트는 있다. 실제 Oracle save→reload→fresh manual identity/version→page plan→PGM은 미검증이다. |
| ThemeA/EList identity | expected identity·상관 응답 계약은 구현했다. 실제 운영 DB의 KRX/NXT·동명이름·코드 경계와 정확한 선택 행 replace/delete는 미검증이다. |
| legacy file import | `종목비교.dat` importer는 strict parser/DB identity/local one-time marker까지 구현했으나 실제 패키지 1회 실행은 미검증이다. FSell/VI 원본 파일 importer는 미적용이다. |
| 남은 실환경 검증 | 다섯 전용 화면의 Web 연결과 signed `1.0.2.0` Release MSIX package-context 실행은 화면/계약 검증 범위에서 확인됐다. 실제 입력→운영 DB write→재조회와 각 전용 scene PGM 검증은 별도 승인·테스트 데이터·롤백 계획이 있는 회차에서만 수행한다. 운영 DB write 또는 새 Live TAKE IN을 승인 없이 실행하지 않는다. |
| legacy file import | `종목비교.dat`·FSell·VI importer는 strict parser, source/hash 재검증, durable intent/marker, rollback·OutcomeUnknown 차단까지 구현했다. 실제 패키지 profile의 명시적 1회 실행은 미검증이며 기존 파일을 덮어쓰지 않는다. |
| 남은 실환경 검증 | 다섯 전용 화면의 Web 연결과 signed `1.0.3.0` Release MSIX package-context 실행은 화면/계약 검증 범위에서 확인됐다. 실제 입력→운영 DB write→재조회와 각 전용 scene PGM 검증은 별도 승인·테스트 데이터·롤백 계획이 있는 회차에서만 수행한다. 운영 DB write 또는 새 Live TAKE IN을 승인 없이 실행하지 않는다. |

View File

@@ -351,7 +351,7 @@ On-air 표식이 남은 상태에서는 프로세스 감시, 연결 해제, 앱
- PList raw restore와 manual descriptor 계약은 구현됐지만 기존 한국어 `DC_TITLE`/`LIST_TEXT`, GraphE·FSell·VI를 포함한 manual named save→fresh restore는 운영 DB에서 검증되지 않았다.
- ThemeA/EList의 expected identity와 응답 상관 계약은 구현됐지만 KRX/NXT·동명이름·코드 경계의 실제 create/replace/delete read-back은 검증되지 않았다.
- 원본 `종목비교.dat`, FSell, VI 파일을 패키지 private 저장소로 옮기는 one-time import는 구현되지 않았다.
- 원본 `종목비교.dat`, FSell, VI를 고정 read-only source에서 패키지 private 저장소로 옮기는 one-time importer 코드는 구현했다. 실제 package profile의 명시적 1회 실행·재시작 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의 역사적 증거로만 보존한다.

View File

@@ -7,15 +7,17 @@
| 항목 | 상태 |
|---|---|
| 기본 모드 | `DryRun`; COM 객체와 `KTAPConnect`를 만들지 않음 |
| 자동 테스트 | 최종 전체 재검증에서 Core Debug/Release x64 각각 1,116/1,116, Playout 각각 374/374, Infrastructure 각각 125/125(합계 각 1,615/1,615), Web 235/235 통과; 실패·skip·경고 0건 |
| 자동 테스트 | 최종 전체 재검증에서 Core Debug/Release x64 각각 1,259/1,259, Playout 각각 387/387, Infrastructure 각각 173/173(합계 각 1,819/1,819), Web 371/371 통과; 실패·skip 0건 |
| Visual Studio 2026 | MSBuild `18.7.8.30822` Debug x64와 signed Release x64 패키지 빌드 성공 |
| trusted Release x64 MSIX | `1.0.2.0` 생성·서명 검증·x64 설치·package context 실행 성공. SHA-256 `4A4ED867D16B75C1C82CB55DA5111E0502573F486B8B897889069843D9DF5072`; source Web 24개 일치, 금지 자산 0건, 기본 DryRun과 전체 UI·실제 DB 검색·오류 이벤트 0건 확인. Round H의 실제 DB DryRun/Live workflow 증거는 아래에 별도 보존 |
| 실제 DB read→DTO→mutation smoke | 34개 도달 가능 data route 통과: 33개 DB + `s5025` trusted 외부 CP949 파일. `s8086` diagnostic 포함 Oracle/MariaDB query 55건 통과. 종속 asset·운영 DB-W·PGM 검증은 포함하지 않음 |
| trusted Release x64 MSIX | clean commit `a01836a`에서 `1.0.3.0` 생성·`CN=Comtrophy` 서명/SignTool 검증·x64 설치·package context 실행 성공. SHA-256 `B46C225B6859F7EBBFDDA83F4433DC64AFDCD59230B667A28BAEC0AE328534C6`; 288개 항목, source Web 31개 byte 일치, 금지 자산 0건. WebView2 6개, 단일 인스턴스, 종료 확인 취소/정상 종료/재시작, `DryRunReady`, Oracle/MariaDB `Healthy`를 확인 |
| 실제 DB read→DTO→mutation smoke | 34개 도달 가능 data route 통과: 33개 DB + `s5025` trusted 외부 CP949 파일. `s8086` diagnostic과 NXT restore audit를 포함 Oracle/MariaDB query 58건 통과. 종속 asset·운영 DB-W·PGM 검증은 포함하지 않음 |
| `s5025` trusted 수동 파일 | 외부 CP949 source 통합 검증 통과; 실제 파일/환경은 계속 Git 밖에서 회차별 preflight |
| `s5006` `Video\큐브배경.vrv` | 현재 승인 Cuts root에서 누락 |
| `s6001` 해외지수 영상 | 국가별 `Video\20201008_<국가>.vrv` 13개가 현재 승인 Cuts root에서 누락; 외부자산 필요 |
| 이번 마이그레이션 WebView workflow의 실제 Tornado2 검증 | **승인된 5001/5074 범위에서 Round H 실제 PGM 완료; 35개 전체의 실제 PGM 검증으로 확대 해석하지 않음** |
1.0.2 Visual Studio 개발 등록본을 signed 1.0.3으로 교체할 때 `Remove-AppxPackage -PreserveApplicationData`를 사용했다. 재등록 구간에서 바뀐 파일은 Windows package Settings transaction log `settings.dat.LOG1/LOG2`뿐이었고, WebView LocalState와 외부 `%LOCALAPPDATA%\MBN_STOCK_WEBVIEW` 운영 데이터는 삭제·덮어쓰지 않았다. 이 패키지 검증 회차는 기본 설정 부재와 환경 override 0건을 확인한 `DryRun`으로만 실행했으며 Tornado 실제 명령은 보내지 않았다.
과거 고정 `5001 → 5006` runner의 실제 PGM 기록은 연결과 기본 K3D 명령 표면의 증거다. 현재 WebView playlist, fresh TAKE IN, Page NEXT, timer refresh, callback/unload의 동등성 완료 증거는 아니다.
2026-07-11의 승인 회차 `MBNWEB-20260711-A`에서는 현재 MSIX WebView runtime으로 `CONNECT → PREPARE 5001/page 1`까지 성공했다. Network Monitoring에 `HELLO`, `LOAD_SCENE`, `BEGIN_TRANSACTION`, 데이터 mutation, `QUERY_VARIABLES`, `END_TRANSACTION`, `SCENE_PREPARE`의 request/success가 기록됐고 PREPARE 동안 PGM은 검은 화면이었다. TAKE IN은 두 번째 K3D Prepare/Play 전에 수행하는 fresh Oracle 조회에서 `DATABASE_UNAVAILABLE`로 명확히 실패했다. `PLAY`가 없고 PGM도 검은 상태임을 확인해 TAKE IN을 반복하지 않았으며, 승인 범위의 `TAKE OUT All` 한 번으로 `STOPAL → UNLOAD_SCENE 5001` 성공을 확인하고 `BYE` 뒤 앱을 정상 종료했다. 직후 probe는 Oracle unhealthy/MariaDB healthy와 정상 DNS/TCP 도달을 보였고, 회차 종료 뒤 전체 55-query 스모크는 두 DB 모두 다시 통과했다. 이 회차는 실패·복구 증거이며 동등성 완료 증거가 아니다. 새 package/계획 SHA-256과 새 Gate A/B로 처음부터 다시 시작한다.
@@ -68,7 +70,7 @@ Round H 전에 Core 790, Infrastructure 65, Playout 374개 테스트를 Debug/Re
- 화면·native bridge·DTO·mutation·identity 상관 계약이 존재하고 자동 테스트가 통과한 상태를 화면/계약 구현으로 기록한다.
- PList의 기존 한국어 `DC_TITLE`/`LIST_TEXT` 복원과 GraphE·FSell·VI를 포함한 manual named save→fresh restore는 적용 중이며 운영 검증 완료가 아니다.
- ThemeA/EList의 expected identity 계약은 구현됐지만 실제 운영 DB에서 KRX/NXT·동명이름·코드 경계와 정확한 selected-row replace/delete를 확인하지 않았다.
- 원본 `종목비교.dat`, FSell, VI 파일의 one-time private-store import는 적용이다.
- 원본 `종목비교.dat`, FSell, VI 파일의 one-time private-store importer 코드는 적용했고, 실제 package profile의 명시적 1회 실행은 미검증이다.
- GraphE·PList/AList·ThemeA·EList의 실제 운영 DB-W와 승인된 `5001`/`5074` 밖의 PGM은 미검증이다. 이 작업은 승인된 테스트 데이터·rollback과 장면별 별도 회차가 있어야 한다.
## 절대 안전 규칙
@@ -92,7 +94,7 @@ Round H 전에 Core 790, Infrastructure 65, Playout 374개 테스트를 Debug/Re
- 원본 test Cuts root: `C:\Users\MD\source\repos\MBN_STOCK_N\MBN_STOCK_N\bin\Debug\Cuts`
- 실제 `.t2s`, image, texture, video와 기타 scene 자산
- `s5006`의 상대 자산 `Video\큐브배경.vrv``s6001` 해외지수의 국가별 영상 13개; 현재 위 Cuts root에는 없으므로 제공 전 해당 장면의 실제 PREPARE 금지
- 정상 앱의 FSell/VI private 저장소 `%LOCALAPPDATA%\MBN_STOCK_WEBVIEW\OperatorData`. 원본 `Data`를 이 위치로 검증·복사하는 one-time importer는 아직 없으며, runtime factory의 `MBN_STOCK_S5025_MANUAL_DATA_DIRECTORY` fallback을 정상 앱 이전 절차로 사용하지 않음
- 정상 앱의 FSell/VI private 저장소 `%LOCALAPPDATA%\MBN_STOCK_WEBVIEW\OperatorData`. 원본 `Data` strict CP949·hash·durable intent로 검증해 이 위치로 이전하는 one-time importer는 구현했지만, 현재 운영 profile의 기존 파일을 덮어쓰거나 marker를 임의 생성하지 않음
- Oracle/MariaDB host, SID/service, database, user, password와 운영 query selector
- K3D/Tornado vendor DLL, Interop, license와 설치 경로
- `MBN_STOCK_K3D_NATIVE_SHA256`, `MBN_STOCK_K3D_INTEROP_SHA256` 승인 값과 승인 근거

View File

@@ -11,10 +11,10 @@
| 원본 inventory와 hash 기준선 | 완료 | 35/35 builder, 원본 기준선 스크립트 35/35 |
| DTO와 mutation builder | 완료 | registry가 정확히 35개 builder를 발견하고 catalog와 1:1 대조 |
| loader와 runtime route | 완료 | MainForm 도달 가능 builder 34개, active alias 45개를 fail-closed route로 등록; `s8086`은 원본과 같이 무alias 진단 전용 |
| 자동 테스트 | 완료 | Core 1,116/1,116, Playout 374/374, Infrastructure 125/125가 Debug/Release x64에서 각각 통과했다. 구성별 1,615개, 전체 3,230개이며 실패·skip·경고는 0건이다. Web 235/235와 원본 baseline 35/35도 통과 |
| 자동 테스트 | 완료 | Core 1,259/1,259, Playout 387/387, Infrastructure 173/173이 Debug/Release x64에서 각각 통과했다. 구성별 1,819개, 전체 3,638개이며 실패·skip 0건이다. Web 371/371와 원본 baseline 35/35도 통과 |
| Visual Studio 2026 빌드 | 완료 | MSBuild `18.7.8.30822`로 Debug x64와 signed Release x64 앱 패키지 빌드 성공 |
| Release x64 MSIX | 완료 | `1.0.2.0` 서명·설치·내용 감사와 package-context 실행 통과. SHA-256 `4A4ED867D16B75C1C82CB55DA5111E0502573F486B8B897889069843D9DF5072`; Web 24개가 source 일치하고 금지 자산 0건이며 기본 `DryRun`에서 전체 UI와 실제 DB 종목 검색을 확인. Round H의 승인된 실제 송출 증거는 아래 별도 행과 운영 문서에 보존 |
| 실제 DB read→DTO→mutation smoke | 완료 | 34개 도달 가능 builder의 data route 통과: 33개 Oracle/MariaDB loader와 `s5025` trusted 외부 CP949 파일. 무alias `s8086` diagnostic도 통과했고 실제 Oracle/MariaDB query 55/55가 성공했다. 종속 asset 또는 PGM 준비 상태는 이 행의 범위가 아니다. |
| Release x64 MSIX | 완료 | clean commit `a01836a` `1.0.3.0` 서명·설치·내용 감사와 package-context 실행 통과. SHA-256 `B46C225B6859F7EBBFDDA83F4433DC64AFDCD59230B667A28BAEC0AE328534C6`; 288개 항목, Web 31개 source 일치, 금지 자산 0건, WebView2 6개, 단일 인스턴스와 정상 종료·재시작 로그를 확인. 기본 상태는 `DryRunReady`, Oracle/MariaDB `Healthy` |
| 실제 DB read→DTO→mutation smoke | 완료 | 34개 도달 가능 builder의 data route 통과: 33개 Oracle/MariaDB loader와 `s5025` trusted 외부 CP949 파일. 무alias `s8086` diagnostic과 NXT restore audit를 포함한 실제 Oracle/MariaDB query 58건이 성공했다. 종속 asset 또는 PGM 준비 상태는 이 행의 범위가 아니다. |
| 종속 asset preflight | **외부자산 필요 / 검사 보강 적용 중** | 승인 Cuts에서 `s5006``Video\큐브배경.vrv``s6001` 해외지수용 국가별 영상 13개가 없다. 현재 작업 트리에는 45 alias와 builder 소유 자산 23개의 누락·빈 파일·root 탈출·reparse 검사가 반영돼 있지만 최종 전체 회귀·패키지 반영 전에는 완료로 올리지 않는다. |
| 이번 마이그레이션의 실제 Tornado2/PGM | **승인 범위 완료** | 계획 SHA-256 `55C7755C2F874B4B012239117D4AB717BBCE194E7DCC8DA9B0E40D094FF8CA19``MBNWEB-20260711-H`에서 `5001 → 자동 refresh 1회 → 5074 page 1 → page 2 → TAKE OUT`을 PGM과 Network Monitoring으로 함께 확인. 최종 검은 화면, retry 0, `OutcomeUnknown = false` |