docs: record round k gate failure and round l plan

This commit is contained in:
2026-07-13 01:26:25 +09:00
parent 9f5be13a05
commit 4e9ae44789
4 changed files with 204 additions and 7 deletions

View File

@@ -118,3 +118,40 @@ Gate B 문구는 Gate A 성공과 command-free preflight 뒤에만 사용한다.
source, package, installed runtime, Live 설정, cut, selector, 대상 source, package, installed runtime, Live 설정, cut, selector, 대상
PID/start/listener/window, helper 또는 계획이 바뀌거나 승인/runtime/preflight가 15분을 PID/start/listener/window, helper 또는 계획이 바뀌거나 승인/runtime/preflight가 15분을
넘으면 승인을 사용하지 않고 새 회차로 돌아간다. 넘으면 승인을 사용하지 않고 새 회차로 돌아간다.
## 실행 결과 — 종료된 실패 회차
Round K는 재시도 없이 `FAIL_KNOWN_CLEANED`로 종료했다. 실행은
`2026-07-12T15:45:34.7388928Z`부터 `15:45:36.8986737Z`까지 2.1597809초였고,
승인 나이는 시작 시점 기준 35.6419872초로 유효했다. `outcomeUnknown=false`다.
실패 원인은 설치 runtime manifest가 Gate A의 strict ordinal 정렬 규약을 만족하지
않은 것이다.
> `The installed runtime manifest is not unique and ordinally sorted.`
manifest는 289개 항목과 exact/OrdinalIgnoreCase 중복 0개를 유지하지만 PowerShell
`Sort-Object -Property path`의 문화권 정렬 결과였다. `[StringComparer]::Ordinal`
비교하면 역전이 41개이며 첫 역전은 `clrjit.dll` 다음
`Config/appsettings.example.json`이다. 기존 manifest SHA-256은
`9234575267F7D1A8A1045246E5128BD755CE9A3976DA83EE00A1AF4ABEE51552`다.
실패는 execution marker, capability 생성과 앱 시작보다 앞에서 발생했다. 따라서 앱
launch, CONNECT/HELLO, PREPARE, TAKE IN, NEXT, Page NEXT, DB write, TAKE OUT,
DISCONNECT와 retry는 모두 0건이다. `prepareIssued=false`,
`prepareMayHaveBeenIssued=false`이며 명령 결과는 명확하다.
비명령 cleanup은 성공했다. 앱/CDP listener, 설치된 Live 설정, 임시 설정, DPAPI
capability와 관련 환경 변수는 남지 않았다. Tornado PID/start ticks와 30001 listener는
계획과 동일하게 유지됐다.
| 증거 | bytes | SHA-256 |
|---|---:|---|
| Round K 계획 | 14,794 | `8B25D2E9987AECF90526752CD9CF9BAB769D2DA4F689064334BE4039FC2E0BC6` |
| Gate A 승인 | 1,085 | `BC1A1F5D4C2CBE60DCD206F284C5CC5CB664AC9DBF576F94F139987562372ED1` |
| Gate A 결과 | 3,366 | `E17FE1EE451A5D9E2B73CCB3D039B5AA90998CC35E3E973148614D32E76D1482` |
Round K 승인과 명령 예산은 폐기했다. 같은 계획이나 승인을 재사용하지 않으며 strict
ordinal 검사는 완화하지 않는다. 수정본은 별도
[`MBNWEB-20260712-L`](LIVE_VALIDATION_PLAN_MBNWEB-20260712-L.md) 계획과 새 승인으로만
검증한다.

View File

@@ -0,0 +1,123 @@
# MBNWEB-20260712-L 실제 PGM 검증 계획
최종 계획 작성 시각: 2026-07-13 01:20 KST
계획 JSON: 15,987 bytes
계획 SHA-256:
`23E3A6A5400166A47835E146DCC2D19C181E2100D1485DB428F1B10718D89928`
계획 원본은 Git 제외 로컬 파일
`artifacts\pgm-evidence\MBNWEB-20260712-L\round-plan.json`이다. 계획 고정 시점의
Round L 실제 앱·Tornado2 명령은 0건이며 승인, 앱, CDP listener, 설치된 Live 설정,
DPAPI capability도 없다. 운영 폴더는 정확히 10개 파일이다.
Round L은 Round K의 retry나 남은 예산 사용이 아니다. 새 회차·새 계획·새 one-shot
예산이며 새 승인을 요구한다.
## 이전 회차 결박
| 항목 | 값 |
|---|---|
| Round K status | `FAIL_KNOWN_CLEANED`, `outcomeUnknown=false` |
| Round K 계획 | `8B25D2E9987AECF90526752CD9CF9BAB769D2DA4F689064334BE4039FC2E0BC6` |
| Round K Gate A | `BC1A1F5D4C2CBE60DCD206F284C5CC5CB664AC9DBF576F94F139987562372ED1` |
| Round K 결과 | `E17FE1EE451A5D9E2B73CCB3D039B5AA90998CC35E3E973148614D32E76D1482` |
| K command boundary/app launch/vendor command | `미도달 / 0 / 0` |
K는 설치 runtime manifest의 culture sort와 Gate A의 strict ordinal 계약 불일치로
execution marker 전에 끝났다. K 승인과 결과는 L authorization으로 복사하거나
재사용하지 않는다.
## manifest 교정과 회귀시험
K manifest의 289개 path/length/SHA-256은 모두 정상이며 exact 및
OrdinalIgnoreCase 중복은 0개다. 그러나 PowerShell `Sort-Object path` 순서였고
`[StringComparer]::Ordinal` 기준 역전이 41개였다. 첫 역전은
`clrjit.dll → Config/appsettings.example.json`, 비교값 32다.
L manifest는 Ordinal dictionary로 중복을 먼저 검사하고
`[Array]::Sort(paths, [StringComparer]::Ordinal)`로 항목만 재정렬했다. 기존과 동일한
289개 의미 집합을 유지하며 결과는 다음과 같다.
- 76,119 bytes
- SHA-256 `9631E8188E10F23970F43593B705957A215AE01E2760FE714B08518DB0571A9B`
- strict ordinal 역전 0
- K/L path·length·SHA-256 289/289 동일
- `ko-KR`, `en-US`, `tr-TR`에서 동일한 ordinal 결과
Gate A와 Gate B는 exact schema와 entry property, NFC, rooted/backslash/control/dot
segment/후행 공백·점, Ordinal 중복, OrdinalIgnoreCase 충돌, strict ordinal 순서를
검사한다. Gate A 검사는 capability와 execution marker 전에, Gate B 재검사는
capability 소비와 consumed marker 전에 수행한다.
K→L 식별자 이관 중 발견한 `backgroundKind` 부분 문자열 오염 네 곳도 모두 교정했다.
최종 helper는 identifier-aware 비교로 manifest hardening 외 K와 동일하며 독립 감사
결과는 P0/P1 0건이다.
첫 L 계획 후보는 Node JSON 왕복이 18자리 Tornado start ticks를 반올림한 것을 계획
감사에서 발견해 승인 전에 폐기했다. 최종 생성기는 unsafe JSON integer를 token으로
보호했다가 숫자 literal로 복원하며, 최종 계획의 `processStartUtcTicks`는 원본과 같은
`639193655349284515` `Int64`다. raw precision loss 재현과 두 unsafe 값 복원 시험도
통과했다. K/L 공통 숫자 leaf 112개를 비교했으며 의도된 이전 결과 파일 길이
3,377→3,366 외 차이는 0개다.
| command-free 시험 | bytes | SHA-256 |
|---|---:|---|
| PowerShell 정적·manifest 회귀 | 30,321 | `CB49085EDFD14A4D842723ECDE2FD7EE06EA19CC0067408E804B6A7CA56BB39C` |
| Node 시간·Int64 계약 | 2,891 | `8632D129688646F923D11A8CBAB2139B1D3DF901223A7748956F743786B27D43` |
| 계획 생성기 | 8,429 | `258949E9AE8E5D4DBEEE16F19166715F4B84F35268E2C48FE9BBDF6C61B4C2B2` |
## 동결된 입력과 helper
- MSIX: `1B0BA713619CC3BD7CB3E03D78FD1EB1CEAF49E7D50F5C00DDFB483917BA5437`
- 설치 runtime: `168D1FB8D6487C41C8CEAA828B4D9515A38DB3A970F8EB44FA930ABDD577B8E9`
- Live 설정: `63C6F386D73D8740B7B10994668ED14D95C3D7B68025B0DF034C3F18D660E582`
- cut: 5001.t2s, 895,922 bytes,
`99CE3B689A42D8C42BEB09A86FA10C2D7C1AEF4F50D324D81276C1A1E4C4D8A7`
- selector: `KOSPI / 삼성전자 / 1열판기본 / CURRENT / 005930`, page 1, fade 6
- Tornado: PID 6972/start ticks `639193655349284515`, 0.0.0.0:30001 단일 listener,
PGM/네트워크 모니터링 창 owner 6972
| helper | SHA-256 |
|---|---|
| `round-l-gate-a.ps1` | `584AE3BD50F973C024D365A86E4E2B002DC6A8F4EAF6C97A528A40607F6E6EE6` |
| `round-l-gate-a-cdp.mjs` | `56836F73C7A3B04653B74D9E708F5AAEF06AF890B7C75ADB6752252BD25AD1A5` |
| `round-l-gate-b.ps1` | `DC82195CB35F99558D15E0F5DD5221EB600FE7D3ED32E8EC7A0D51DC54CCC786` |
| `round-l-gate-b.mjs` | `663B1369C24BF9479A055ABC9D60A92F9D653835B4A2F45D5C363C4D2C44BD38` |
| `round-l-window-arm.ps1` | `E8AC68F8A3B6A703753F17181153938E5141C7CFBADE365CA47A076C264B21B1` |
| `round-l-desktop.ps1` | `1E3ABAE50B1337AEA5CCE05CC8125D04F4D6AA0FC2441FD98381B5165032175A` |
| `round-l-monitor.ps1` | `B1CFEBC4A35347ADE5B1B402641EEA19A6975997C05C2726C74D1F4E72694B30` |
## 폐쇄형 prearm과 명령 예산
승인 전 운영 L 폴더는 계획·Live 설정·installed manifest·helper 7개의 정확히 10개
파일이다. `gate-a.json`을 생성한 실행 시점에는 이 11개만 허용한다. 폴더, reparse,
미지 파일, `*.tmp`, partial, static-test, 누락·중복은 capability 생성 전에 거부한다.
이 검사는 계획/승인 해석 전과 capability 초기화 직전에 두 번 수행한다.
Gate A는 CONNECT 1회와 PREPARE 5001/page 1 1회만 허용한다. TAKE IN, NEXT,
Page NEXT, DB write는 0이다. 명확한 known-outcome 중단에서만 정상 종료에 의한
DISCONNECT 최대 1회를 허용한다.
Gate B는 별도 즉시 승인 뒤 TAKE IN 1회, 자동 갱신 최대 1회, TAKE OUT All 1회,
DISCONNECT 1회를 단일 observer로 수행한다. NEXT, DB write, retry는 0이다.
- Gate A 완료 `[R]`: 정확히 39 marker
- Gate B 최종 누적 `[R]`: 정확히 117 marker, 의미상 vendor request 114
- 누적 PREPARE/PLAY/OnScenePlayed: cap 도달 전 `3 / 2 / 2`
- 최종 refresh: `completed=1`, `maximum=1`, `limitReached=true`, `CAPPED · 1/1`
## 승인 문구
Gate A는 다음 한 문장을 그대로 승인받아야 한다.
> 회차 MBNWEB-20260712-L의 계획 SHA-256 23E3A6A5400166A47835E146DCC2D19C181E2100D1485DB428F1B10718D89928을 승인한다. 현재 K3D 라이선스가 유효함을 확인하며, 현재 PGM 대상 Live CONNECT 1회와 PREPARE 5001 page 1 실행, Gate A가 명확한 known-outcome 상태에서 중단될 때 DISCONNECT 1회를 승인한다. TAKE IN, NEXT, DB write는 아직 승인하지 않는다.
Gate B 문구는 Gate A 성공과 command-free preflight 뒤에만 사용한다.
> 회차 MBNWEB-20260712-L의 계획 SHA-256 23E3A6A5400166A47835E146DCC2D19C181E2100D1485DB428F1B10718D89928을 다시 확인했다. 현재 PGM 대상 TAKE IN 5001 page 1 정확히 1회, OnScenePlayed 확인 후 자동 갱신 최대 1회, TAKE OUT All 정확히 1회와 DISCONNECT 1회를 승인한다. NEXT와 DB write 및 결과 불명확 시 재시도는 승인하지 않는다.
source, package, installed runtime, Live 설정, cut, selector, 대상
PID/start/listener/window, helper 또는 계획이 바뀌거나 승인/runtime/preflight가 15분을
넘으면 승인을 사용하지 않고 새 회차로 돌아간다.

View File

@@ -14,7 +14,7 @@
| `s5025` trusted 수동 파일 | 외부 CP949 source 통합 검증 통과; 실제 파일/환경은 계속 Git 밖에서 회차별 preflight | | `s5025` trusted 수동 파일 | 외부 CP949 source 통합 검증 통과; 실제 파일/환경은 계속 Git 밖에서 회차별 preflight |
| `s5006` `Video\큐브배경.vrv` | 현재 승인 Cuts root에서 누락 | | `s5006` `Video\큐브배경.vrv` | 현재 승인 Cuts root에서 누락 |
| `s6001` 해외지수 영상 | 국가별 `Video\20201008_<국가>.vrv` 13개가 현재 승인 Cuts root에서 누락; 외부자산 필요 | | `s6001` 해외지수 영상 | 국가별 `Video\20201008_<국가>.vrv` 13개가 현재 승인 Cuts root에서 누락; 외부자산 필요 |
| 이번 마이그레이션 WebView workflow의 실제 Tornado2 검증 | **최신 성공은 승인된 5001/5074 범위의 Round H. Round J pre-dispatch 명령 0건으로 종료됐고 수정된 Round K는 Gate A 승인 대기; 35개 전체의 실제 PGM 검증으로 확대 해석하지 않음** | | 이번 마이그레이션 WebView workflow의 실제 Tornado2 검증 | **최신 성공은 승인된 5001/5074 범위의 Round H. Round J/K는 각각 pre-dispatch 명령 0건으로 종료됐고 수정된 Round L은 Gate A 승인 대기; 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 실제 명령은 보내지 않았다. 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 실제 명령은 보내지 않았다.
@@ -90,7 +90,7 @@ range에는 그 추가 PREPARE/PLAY를 반영하지 않은 불일치가 있었
이 실패 뒤 `maximumAutomaticRefreshesPerTakeIn` trusted JSON-only 상한을 추가했다. 기본 `null`은 원본 연속 갱신을 유지하고, 실제 검증 설정의 `1`은 scheduler와 실제 refresh dispatch 경계에서 두 번째 실행을 이중 차단한다. 상태는 `refreshCompletedCount`, `refreshMaximumCount`, `refreshLimitReached`를 제공하며, 마지막 refresh `OnScenePlayed`가 drain되기 전에는 count가 상한에 도달해도 `refreshLimitReached=false`를 유지한다. 검증은 `completed=1`, `maximum=1`, `limitReached=true`, `refreshActive=false`, `playCompletionPending=false`를 모두 확인해야 한다. 변경된 package는 Round I 승인/계획을 재사용할 수 없으며 새 package hash, 새 회차 계획과 새 CONNECT/PREPARE/TAKE IN 승인이 필요하다. 이 실패 뒤 `maximumAutomaticRefreshesPerTakeIn` trusted JSON-only 상한을 추가했다. 기본 `null`은 원본 연속 갱신을 유지하고, 실제 검증 설정의 `1`은 scheduler와 실제 refresh dispatch 경계에서 두 번째 실행을 이중 차단한다. 상태는 `refreshCompletedCount`, `refreshMaximumCount`, `refreshLimitReached`를 제공하며, 마지막 refresh `OnScenePlayed`가 drain되기 전에는 count가 상한에 도달해도 `refreshLimitReached=false`를 유지한다. 검증은 `completed=1`, `maximum=1`, `limitReached=true`, `refreshActive=false`, `playCompletionPending=false`를 모두 확인해야 한다. 변경된 package는 Round I 승인/계획을 재사용할 수 없으며 새 package hash, 새 회차 계획과 새 CONNECT/PREPARE/TAKE IN 승인이 필요하다.
### Round J pre-dispatch 실패와 Round K 시간 검증 ### Round J/K pre-dispatch 실패와 Round L 교정
Round J `MBNWEB-20260712-J`는 계획 SHA-256 Round J `MBNWEB-20260712-J`는 계획 SHA-256
`8B51E43AFC5F0E330A8DEF3B38DF071B071E5814FC96258AA9505935D1B43956`에 대한 `8B51E43AFC5F0E330A8DEF3B38DF071B071E5814FC96258AA9505935D1B43956`에 대한
@@ -111,10 +111,29 @@ Round K `MBNWEB-20260712-K`는 별도 회차이며 계획 SHA-256은
거부와 `60.125초` 보존을 확인한다. Gate A는 승인 파일 생성 뒤 정확히 계획·승인· 거부와 `60.125초` 보존을 확인한다. Gate A는 승인 파일 생성 뒤 정확히 계획·승인·
Live 설정·installed manifest·계획에 SHA로 묶인 helper 7개만 있는지 계획 해석 전과 Live 설정·installed manifest·계획에 SHA로 묶인 helper 7개만 있는지 계획 해석 전과
capability 생성 직전에 검사한다. 폴더, reparse, 미지·임시·partial·static-test 파일, capability 생성 직전에 검사한다. 폴더, reparse, 미지·임시·partial·static-test 파일,
누락과 중복은 모두 fail-closed다. K는 새 Gate A 승인을 받기 전에는 어떤 앱이나 누락과 중복은 모두 fail-closed다.
Tornado 명령도 실행하지 않는다. 현재 승인 전 운영 폴더는 정확히 10개 파일이며,
Gate A 예산은 CONNECT 1회, PREPARE 5001/page 1 1회, 명확한 known-outcome 중단의 K Gate A는 승인 시간 계산을 통과했지만 설치 runtime manifest의 culture sort가 strict
DISCONNECT 최대 1회다. TAKE IN, NEXT, Page NEXT, DB write와 retry는 0이다. ordinal 검사를 만족하지 않아 execution marker 전에 `FAIL_KNOWN_CLEANED`로 끝났다.
manifest 289개 항목과 내용은 정상이지만 ordinal 역전이 41개였고 첫 역전은
`clrjit.dll → Config/appsettings.example.json`이다. 앱 launch/CONNECT/PREPARE와
금지 명령은 모두 0건이며 `OutcomeUnknown=false`다. 결과 SHA-256은
`E17FE1EE451A5D9E2B73CCB3D039B5AA90998CC35E3E973148614D32E76D1482`다. K 승인과
예산은 폐기하며 재사용하지 않는다.
Round L은 289개 path/length/SHA-256을 그대로 두고 `[StringComparer]::Ordinal`로만
재정렬했다. manifest SHA-256은
`9631E8188E10F23970F43593B705957A215AE01E2760FE714B08518DB0571A9B`이며 역전 0,
K/L 의미 집합 289/289 동일, `ko-KR/en-US/tr-TR` 불변성을 확인했다. Gate A/B 모두
exact schema, NFC와 안전 경로, exact/대소문자 충돌, strict ordinal 순서를 검증한다.
Node 계획 생성기의 18자리 start ticks 반올림도 승인 전에 발견해 Int64 보존 회귀를
추가했다. 최종 L 계획 SHA-256은
`23E3A6A5400166A47835E146DCC2D19C181E2100D1485DB428F1B10718D89928`이다. 승인 전
운영 폴더는 정확히 10개 파일이며 앱/Tornado 명령은 0건이다. Gate A 예산은 CONNECT
1회, PREPARE 5001/page 1 1회, 명확한 known-outcome 중단의 DISCONNECT 최대 1회다.
TAKE IN, NEXT, Page NEXT, DB write와 retry는 0이다. 세부 계획은
[`LIVE_VALIDATION_PLAN_MBNWEB-20260712-L.md`](LIVE_VALIDATION_PLAN_MBNWEB-20260712-L.md)에
고정했다.
이 실제 Live PGM 증거는 회차에 허용된 5001과 5074에 한정된다. 35개 scene builder 전체 동등성은 자동 테스트, 55-query 실데이터 smoke와 [`SCENE_EQUIVALENCE.md`](SCENE_EQUIVALENCE.md) 매트릭스로 유지하며, 나머지 scene이 실제 PGM에서 각각 송출됐다는 의미로 기록하지 않는다. 이 실제 Live PGM 증거는 회차에 허용된 5001과 5074에 한정된다. 35개 scene builder 전체 동등성은 자동 테스트, 55-query 실데이터 smoke와 [`SCENE_EQUIVALENCE.md`](SCENE_EQUIVALENCE.md) 매트릭스로 유지하며, 나머지 scene이 실제 PGM에서 각각 송출됐다는 의미로 기록하지 않는다.

View File

@@ -90,7 +90,7 @@ CDP listener가 모두 0임을 확인했다. 임시 playout local config를 삭
process/user/machine 범위 `MBN_STOCK_PLAYOUT_*`도 모두 0이다. 1.0.5 signed process/user/machine 범위 `MBN_STOCK_PLAYOUT_*`도 모두 0이다. 1.0.5 signed
설치본은 `Status=Ok`로 유지한다. 설치본은 `Status=Ok`로 유지한다.
## Round I 실패 증거와 다음 회차 ## Round I 실패 증거와 후속 회차
Round I의 결과는 계속 `FAIL`이다. 로컬 증거는 Round I의 결과는 계속 `FAIL`이다. 로컬 증거는
`artifacts\pgm-evidence\MBNWEB-20260712-I\round-result.json`, SHA-256은 `artifacts\pgm-evidence\MBNWEB-20260712-I\round-result.json`, SHA-256은
@@ -133,3 +133,21 @@ K Gate A는 승인 파일 생성 시 운영 폴더의 정확한 11개 allowlist
정적 시험 파일·미지 파일·폴더·reparse·누락·중복을 capability 생성 전에 거부한다. 정적 시험 파일·미지 파일·폴더·reparse·누락·중복을 capability 생성 전에 거부한다.
실제 operator workflow 입력은 실제 operator workflow 입력은
`KOSPI / 삼성전자 / 1열판기본 / CURRENT / 005930`, page 1, fade 6으로 유지한다. `KOSPI / 삼성전자 / 1열판기본 / CURRENT / 005930`, page 1, fade 6으로 유지한다.
K Gate A 결과는 `FAIL_KNOWN_CLEANED`, `outcomeUnknown=false`다. 설치 runtime
manifest가 PowerShell culture sort 순서여서 strict ordinal 검사에서 execution marker
전에 중단됐다. 앱 launch, CONNECT, PREPARE, TAKE IN, NEXT, DB write, DISCONNECT와
retry는 모두 0건이다. Gate A 승인 SHA-256은
`BC1A1F5D4C2CBE60DCD206F284C5CC5CB664AC9DBF576F94F139987562372ED1`, 결과 SHA-256은
`E17FE1EE451A5D9E2B73CCB3D039B5AA90998CC35E3E973148614D32E76D1482`다. K 승인은
폐기했고 재사용하지 않는다.
교정된 [`LIVE_VALIDATION_PLAN_MBNWEB-20260712-L.md`](LIVE_VALIDATION_PLAN_MBNWEB-20260712-L.md)은
기존 manifest 의미 집합 289/289를 유지한 strict ordinal manifest
`9631E8188E10F23970F43593B705957A215AE01E2760FE714B08518DB0571A9B`를 사용한다.
K 역전 41개를 재현하고 L 역전 0, exact/대소문자 중복 0, 3개 문화권 불변성을
command-free로 검증했다. Gate A/B에 exact schema·NFC·안전 경로·ordinal 재검증을
추가했다. Node 계획 생성기의 18자리 Tornado start ticks 반올림도 승인 전에 폐기하고
Int64 보존 회귀를 추가했다. 최종 L 계획 SHA-256은
`23E3A6A5400166A47835E146DCC2D19C181E2100D1485DB428F1B10718D89928`이다. 계획 고정
시점의 앱/Tornado 명령은 0건이며 새 Gate A 승인 전에는 실행하지 않는다.