Files
sodalive-ios/docs/20261029_추천_서브_배너/reviews/evidence/native-final/README.md
T

11 KiB
Raw Blame History

최종 소스 Native QA 재실행

현재 production 캐러셀 SHA256 7e25db3076d545ffc61ea3a1c5585e7b8a617964ef406d7570286d75a75e010a로 기존 native matrix 재실행과 평가·정리를 완료했다. 실행한 시나리오는 PASS이며 physical tap/swipe와 Reduce Motion ON은 NOT RUN이다. REV-P1-001의 현재 소스와 캡처 연결을 보완하는 증거이며 독립 reviewer의 종료 판정을 대신하지 않는다.

출처와 변경 범위

  • 실행일: 2026-10-30 KST. 부모 소유 iPhone SE3/iOS 18.3 482F7827-2E3A-4559-BAF4-48B68CC5725B, 375×667pt, 2x를 재사용했다. Xcode 26 SDK, Swift 5, x86_64-apple-ios16.6-simulator compile이다. iOS 16.6 런타임 실행은 아니다.
  • 기존 native/source의 run.py, assess.py, cleanup.py, Doubles.swift, Harness.swift를 그대로 재사용했다. 변경은 evidence root, own temporary root, own bundle뿐이다. provenance-before.json과 provenance-after.json의 harnessCloneChecks가 경로 정규화 후 5개 파일 동일성을 assert했다. 시나리오, 대기 시간, 입력 fixture, geometry 검사는 변경하지 않았다.
  • 실제 production 9개 파일의 원본 경로를 swiftc 입력으로 사용했다. production-source-snapshot은 전체 입력 9개의 byte-identical 보존본이며 컴파일 입력은 이 보존본이 아니다. commands.json에 원본 경로와 실제 native 명령·stdout/stderr·exit가 있다.
  • source-hashes-before.json, source-hashes-after.json, source-hashes-final.json, teardown 이후 provenance까지 9개 입력과 snapshot의 해시가 일치한다. source-stability.json은 unchanged=true, changed=[]이다.
  • 기존 native 최종 해시 1bf03b8b1e05310acce09f12b2f09b35af3587f4a7d486b22945ec502cfb506d와 비교하면 9개 입력 중 캐러셀만 다르고 나머지 8개는 같다. 전달받은 delta는 @GestureState isSwiping, tap guard, highPriorityGesture → simultaneousGesture, swiping 중 자동 전환 생략, 수평 우세 drag 및 onEnded guard이다. 현재 전체 snapshot에서 이 처리를 확인했다. 과거 캐러셀 전체 소스는 기존 evidence에 없으므로 과거 byte 단위 diff를 재구성했다고 주장하지 않는다. 배치·비율 변경은 요청되지 않았고 이번 실행에서 제품 수정은 없었다.

기존 native/ 62개 파일과 PRD·plan·기존 리뷰 3개, 합계 65개 보호 파일의 해시 및 파일 목록이 전후 동일하다. 기존 증거·해시를 덮어쓰지 않았다. 추가한 source/provenance.py는 snapshot·보호 파일·의존성 해시와 소유권을 기록하는 증거 보조 도구이며 UI 하네스 동작은 바꾸지 않는다.

실제 실행 Surface와 명시적 대역

production SubBanner.swift, SubBannerLinkOpener.swift, SubBannerCarousel.swift, 두 recommendation View composition, 실제 spacing/color/hex/font 소스를 원본 경로에서 컴파일했다. 기존 prebuilt Kingfisher object/module을 읽기 전용으로 링크했고 전후 해시 동일성을 확인했다. 실제 KFImage와 downloader를 사용한다. dependency-hashes.json 참조.

기존 FixtureProtocol을 실제 Kingfisher의 ephemeral URLSession에 연결했다. subbanner.qa.invalid만 로컬 생성 PNG로 응답하고 다른 요청은 로컬에서 실패한다. 인터넷·계정·서버는 사용하지 않았다. A=1200×400 teal, B=1200×600 orange이다.

source/Doubles.swift의 하위 추천 섹션은 48pt QA ... bar 또는 EmptyView, VM/DTO는 fixture, refresh wrapper는 ScrollView, toast/purchase/media player는 무효 대역이다. production 두 View의 조건부 삽입과 VStack(s24)는 실행하지만 실제 추천 카드·기존 메인 배너 carousel·API/인증/filter/콘텐츠 isEmpty·구매·refresh 전체를 검증하지 않는다. 오류 격리는 주변 대역 bar 유지에 한정한다.

매트릭스와 실제 관측

captures/actions.json의 finished는 launch 기준 monotonic 210.953초에 기록됐다. 41개 앱 window drawHierarchy PNG와 별도 native-os-final.png, 총 42개 native 원본 모두 750×1334이고 production 소스보다 신선하다. verification.json에 PNG별 hash·크기·freshness와 geometry가 있다. contact-1.png~contact-4.png는 41개 앱 캡처 전체를 포함하는 검토용 축소 배치이며 새로운 UI가 아니다.

시나리오 판정 이번 실행에서 확인한 증거
홈 지정 위치 PASS home-first: QA active creators 뒤, debut 앞
콘텐츠 지정 위치 PASS content-first: QA main banner 뒤, exclusive 앞
전체 폭·원본 비율 PASS 양 화면 A: x0/w375/h125pt, B: x0/w375/h187.5pt. Home y280, Content y136
s24·empty 추가 gap0 PASS 이미지 위아래 24pt. home-empty, content-empty는 일반 섹션 간격 24pt만 유지
실제 5초 자동 전환·2항목 wrap PASS, 정밀도 한정 Home 시작 후 4.523초 A → 5.374초 transition → 6.118초 B. Content 4.791초 A → 5.640초 transition → 6.387초 B. 두 wrap 캡처는 A/01/02
단일 고정 PASS 양 화면 one과 one-after-6s의 PNG SHA 동일, 01/01. 실제 관측 간격 Home 6.048초, Content 6.069초
21개·20개 제한 없음 PASS many-first 01/21 → many-twenty-first 20/21 → many-wrap 21/21 → OS final 02/21. timer/index를 직접 바꾸지 않음
컨테이너 resize PASS 양 화면 부모 frame 375→320pt, 배너 x0/w320/h106.6667pt. 실제 회전/기기 resize는 아님
지연 이미지 비율 격리 PASS 초기 direct 높이0 → 유효 B 높이187.5 → 지연된 A 도착 뒤에도 B/187.5 유지
실패 이미지 국소 처리 PASS failure-placeholder-other-content: 회색125pt/02/02와 주변 QA bar 유지 → failure-wrap-valid A
inactive/active PASS, 주입 환경 실제 scenePhase probe inactive 확인, 6.512초 간격 PNG SHA 동일 B. active 주입 후 4.837초 B, 6.345초 A
unmount/remount·목록 축소 PASS unmounted 캡처는 하네스 제목만 유지. remount-first A → remount-next B → shrink-one A/01/01
light/dark PASS, 범위 한정 두 화면 light 캡처가 dark first와 동일한 검정 배경·읽을 수 있는 indicator 유지. 하네스 window override이며 전체 앱 system theme 검증 아님
링크 fallback driver PASS, 탭 아님 production opener에 false completion 주입, sodaqa://banner/900 뒤 https://subbanner.qa.invalid/destination 각 1회
physical tap/swipe·세로 scroll 공존 NOT RUN 좌표 입력/hit testing 미실행. gesture 소스 존재와 compile을 실제 제스처 성공으로 취급하지 않음
Reduce Motion ON NOT RUN OS 관측값 false, 부모 접근성 설정 변경 없음. reduce-* 파일명은 ON 증거가 아님

파일명은 예정 촬영 시점명이다. 현재 원본을 직접 열어 many-twenty-first=20/21, many-wrap=21/21, native-os-final=02/21 및 many-2-wide.png를 확인했다. 기존 assess.py에는 이전 실행 관측 native-os-final=01/21이 하드코딩되어 있으므로 script 복제 자체는 유지하고 이번 verification.json의 해당 설명만 실제 캡처에 맞게 수동 정정했다. OS final은 복사와 screenshot 사이에도 timer가 계속 동작한 뒤의 상태다. 21→1 순간 프레임은 없고 21 이후 2가 확인된 범위에서 wrap을 판단한다.

모든 contact sheet와 주요 full-size PNG(두 화면 first/second/transition, 21개 후반 2장, OS final)를 직접 열어 배너·주변 bar 배치, clipping/겹침, fixture 순서와 페이지 번호를 확인했다. 전환 프레임은 A 일부와 B가 함께 보이는 이동 중 상태이며 결함이나 정착 프레임으로 오인하지 않았다. timestamp는 screenshot 완료 후 기록이므로 5.000초 정확도·프레임률·매끄러움·인터럽트·중복 timer 부재를 보증하지 않는다.

명령과 평가

아래 순서로 각 명령 exit0을 확인했다. provenance.py는 Python AST와 clone 동일성도 검사한다. native compile stderr는 비어 있었다. LSP 도구는 제공되지 않았으며 native swiftc 진단으로 대체했다. 전체 앱 build, 집중 CLI checks 재실행, 독립 reviewer 호출은 이번 위임 범위에 따라 하지 않았다.

export TMPDIR=/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/sub-banner-native-final.97cQKj
export NODE_COMPILE_CACHE="$TMPDIR"
export BUN_RUNTIME_TRANSPILER_CACHE_PATH="$TMPDIR"
export PYTHONDONTWRITEBYTECODE=1
python3 docs/20261029_추천_서브_배너/reviews/evidence/native-final/source/provenance.py
python3 docs/20261029_추천_서브_배너/reviews/evidence/native-final/source/run.py
python3 docs/20261029_추천_서브_배너/reviews/evidence/native-final/source/assess.py
python3 docs/20261029_추천_서브_배너/reviews/evidence/native-final/source/cleanup.py
python3 docs/20261029_추천_서브_배너/reviews/evidence/native-final/source/provenance.py --after

assess.py의 assertions PASS: 41 PNG와 OS PNG signature/750×1334/freshness, 원본 소스 해시, 양 화면 전체 폭·A/B 비율·s24·empty·320pt, single 고정, inactive 고정, 지연 이미지 높이 격리, 21개 input, opener 순서. 자동 geometry와 양끝 fixture pixel scan을 교차 검증한다. 페이지 번호 관측은 위 직접 검사와 구분했다.

소유권과 정리

ownership.json에 own bundle qa.sodalive.subbanner.native.final.97cQKj, PID 10884, own root, 부모 device 소유권을 launch 직후 기록했다. cache는 own root 아래 module-cache; shell TMPDIR/NODE/BUN cache 환경은 provenance에 기록했다.

cleanup.json: own app terminate/uninstall exit0, app container 조회 exit2, PID 조회 exit1로 부재 확인, own root와 module-cache 제거, 부모 simulator Booted 유지, production 해시 불변, shared cache 삭제 없음. provenance-after.json은 teardown 이후에도 source/snapshot·기존 native 62개 파일·PRD/plan/review 3개·Kingfisher 입력 해시 불변과 root 부재를 다시 확인했다. device shutdown/delete/reset, 공유 cache 삭제, worktree, commit/push, 의존성 변경은 하지 않았다.

남은 한계: physical tap/swipe/세로 scroll 공존, Reduce Motion ON, 실제 UIApplication.open, OS background/foreground, 전체 SodaLive 앱·실서비스, 실기기/iOS16.6/Dynamic Type/VoiceOver는 미검증이다. 현재 증거 범위의 실행 차단 문제는 없으며 REV-P1-001의 공식 해소 판정은 상위 실행자와 기존 reviewer의 후속 범위다.