<!-- FILE: _St/ai_read_패치.md | ROLE: sort 현재 작업·검증대기 -->

## v324 Auto8700 매 정시 build 체크
- [코드반영] 시작 시 1회 update check 유지 + 실행 중 매 정시 `HH:00:00` `hourly_update_check` 추가.
- [코드반영] manager lock 이후 정상 프로세스 daemon thread 1개만 정시 checker 실행; polling 없음.
- [코드반영] 정시 UPDATE 발견 시 기존 SHA256/ZIP/build 검증과 TEMP updater를 그대로 사용하고 `hourly_auto_update` 정상 종료 요청.
- [코드반영] publisher는 정시 서버 build 확인은 하되 `PUBLISHER_SKIP`으로 다운로드 금지. SAME/LOCAL_NEWER도 기존 기준 유지.
- [코드반영] `Auto8700/test_auto8700_update_hourly_v324.py` 추가. updater 전용 15 passed, 전체 pytest 157 passed.
- [완료] v323 Side/Main 수동 JPG 원래 브라우저 다운로드 사용자 실제 Chrome OK.
- [검증대기] 실제 Windows에서 다음 정시 `UP-H-00` 및 `source=hourly` build 확인 로그, 일반 사용자 새 build 자동 적용.

## v323 현재 작업
- [코드반영] 자동다운로드 JPG 완전 분리: 자동 후보/직접저장/cache fallback/파일집계/ETA/UI는 MP4만 처리.
- [코드반영] 수동 JPG 원래 브라우저 다운로드 복원: Side/Main JPG 클릭은 WS8771 direct를 우회하여 MAIN `fetch → Blob → a.download`, `silent=true`로 Side 상세상태 미표시.
- [완료] 사용자 실제 Chrome에서 Side/Main 수동 JPG 원래 브라우저 다운로드 정상 확인. WS8771 direct 자동진행 UI와 분리됨.
- [검증대기] 실제 자동실행 2계정×Top1에서 `JPG 0개` 문구 없이 MP4 2개만 집계·자동종료되는지 확인.
- 전용 테스트: `IG_StYellow/test_ext_jpg_manual_original_v323.js`.


## v322 Side 설정 전역 선언 회귀 복원
- [코드반영] v317 정상 블록의 `teAutoPyStatsTimer`, `teAutoPyStatsLastMainPush`, `m/b/g/_`, `y/v/w/x`를 `side.js` 원위치에 복원.
- [코드반영] v321에서 제거했던 settings target gate를 v317 원형으로 복구.
- [폐기] `test_ext_settings_open_without_target_v321.js`는 원인 오판 회귀라 0Byte 처리.
- [코드반영] `IG_StYellow/test_ext_settings_modal_restore_v322.js`: 복원 전역/handler 검사 + `T()` 실제 실행 + `settingsModal` 생성 확인.
- [코드반영] 회귀: pytest 151 passed, IG Node 55/55, RTC Node 3/3, Analyze UI 1/1.
- [완료] 사용자 실제 Chrome v322에서 톱니바퀴 클릭 → Settings 모달 정상 표시 확인.


## v321 Side 설정 톱니바퀴 정상 동작 복원
- [코드반영] settings click의 Instagram target 선행 차단 제거. 클릭은 기존 `T()` 설정 모달을 항상 호출한다.
- [코드반영] target이 필요한 개별 기능 로직은 변경하지 않았다.
- [코드반영] 전용 회귀 `IG_StYellow/test_ext_settings_open_without_target_v321.js` 추가.
- [코드반영] 최종 정적/단위: pytest 151 passed, IG Node 54/54, RTC Node 3/3, Analyze UI 1/1, JS syntax 66, Python compile 44, JSON 6 OK.
- [검증대기] 실제 Chrome에서 Instagram target 준비 전/후 각각 톱니바퀴 클릭 → 설정창 표시 확인.


## v320 build 자동업데이트
- [코드반영] `_St_ver.html` 정수 build 비교: server>local만 업데이트, same/local-newer 다운로드 금지.
- [코드반영] 배포자 marker `_St/AutoDistribute/AutoDistribute.py` 존재 시 `PUBLISHER_SKIP`; 개발 원본 자동 덮어쓰기 금지.
- [코드반영] 일반 사용자 TEMP download → SHA256/ZIP 검증 → TEMP updater overlay → Auto8700 재실행.
- [코드반영] AutoDistribute v4: build 증가, 로컬 version file ZIP 포함, ZIP SHA256 서버 meta 생성, ZIP 먼저/version meta 마지막 SFTP 업로드.
- [코드반영] 최종 회귀: pytest 151 passed, IG 53/53, RTC 3/3, Analyze 1/1, JS 65, Python 44, JSON 6 OK.
- [검증대기] 실제 일반 사용자 PC에서 server build를 1 올린 뒤 UP-01~UP-08 로그와 v320→새 build 적용 확인.

## v319 수동 편집복사 완료 후 폴더 열기 확인
- [코드반영] WS8771 GUI main thread `ig_copy_to_edit_folder`가 copy2 성공 후 `messagebox.askyesno("편집폴더", "폴더를 열까요?")`를 1회 표시한다.
- [코드반영] 확인=기존 `ig_open_folder`로 즉시 탐색기 열기, 취소=종료. 취소여도 `target_folder` 응답은 유지한다.
- [코드반영] Side `편집폴더 열기` 버튼은 v318 runtime/session 방식 그대로 유지한다.
- [코드반영] Side의 미사용 자동 다중 편집복사 accumulator/prompt dead code 제거. 수동 MP4 1건만 편집 대상이다.
- [코드반영] 전용 회귀 `WS8771/test_ws8771_edit_folder_open_prompt_v319.py` 추가.
- [코드반영] 최종 정적/단위: pytest 132 passed, IG Node 53/53, RTC Node 3/3, Analyze UI 1/1, JS syntax 65, Python compile 39, JSON 6 OK.
- [검증대기] 실제 Windows 수동 MP4 → picker → copy → `폴더를 열까요?` 확인/취소 각각 확인, 취소 후 Side 버튼으로 같은 폴더 열기 확인.

## v318 편집폴더 열기 runtime 연결
- [코드반영] picker 성공 경로를 `chrome.storage.session` runtime-only로 전달/복원한다.
- [코드반영] Side가 닫혀 있던 경우에도 재오픈 시 `편집폴더 열기`가 활성화된다.
- [코드반영] 버튼 클릭은 WS8771 `ig_open_folder`; 새 picker 시작 전 이전 경로는 제거한다.
- [검증대기] 실제 Windows picker 선택 → Side 버튼 활성 → 클릭 폴더열기.

## v317 수동 다운로드 전역 강조 + 수동 1건 편집폴더 복사
- [코드반영] 다운로드 상태 강조 설정은 `ndy_ig_visual_settings` Chrome storage를 단일 원본으로 사용하며 active 설정의 Instagram localStorage read/write를 제거했다.
- [코드반영] WS 수동 다운로드 `start`부터 shortcode/asset_kind를 MAIN으로 전달하여 Side가 닫혀 있어도 클릭 즉시 Glow/테두리/상태 배지를 표시한다.
- [코드반영] 수동 완료 버튼에 `다운` 표시를 유지하고 DOM 재생성 시 state map에서 재적용한다.
- [코드반영] PY/WS 미연결 원래 MAIN downloader도 start/done/error 상태 이벤트를 발생시킨다.
- [코드반영] `편집폴더에 복사`는 자동종료 다중복사를 제거하고 `MANUAL_SINGLE` MP4 WS 저장 완료 직후 Background가 방금 받은 파일 1개만 WS GUI picker로 전달한다. Side가 닫혀 있어도 Chrome storage 체크값으로 동작한다.
- [코드반영] 전용 회귀 `test_ext_manual_download_global_highlight_v317.js`; 기존 v316 edit-copy 테스트를 수동 1건 기준으로 갱신했다.
- [코드반영] 최종 정적/단위: pytest 130 passed, IG Node 52/52, RTC Node 3/3, Analyze UI 1/1, JS syntax 64, Python compile 38, JSON 6 OK.
- [검증대기] 실제 Chrome에서 Side 닫힘 + 수동 MP4 클릭 → 다운로드 중 강조 → 완료 `다운`; 실제 Windows에서 체크 ON 수동 MP4 완료 → picker → 방금 파일 1개 복사 확인.

## v316 편집폴더 GUI picker + 수동 원래 injection downloader 복구
- [코드반영] `ig_copy_to_edit_folder`를 WS thread-direct 처리 목록에서 제거하고 Tk `control_queue`로 전달한다. picker 요청은 최대 660초 대기한다.
- [코드반영] WS8771 GUI main thread에서 `filedialog.askdirectory()`를 호출한다. 경로는 영구 저장하지 않는다.
- [코드반영] 자동종료 후 신규 MP4만 복사하며 동일 파일명은 무덮어쓰기 SKIP. 선택 성공 시 Side `편집폴더 열기` 활성화, 새 자동 세션에서 runtime 경로 초기화.
- [코드반영] PY/WS 미연결 수동 다운로드는 Background Chrome filename fallback을 폐기하고 MAIN 원래 `fetch/Blob/a.download` 경로를 사용한다. Video 기본명은 `shortcode.mp4`.
- [코드반영] WS 상태가 stale하게 연결로 보였더라도 실제 Background 요청이 실패하면 Content가 `igblue_manual_original_download`를 MAIN에 보내 같은 원래 downloader로 전환한다.
- [코드반영] 자동 `auto_direct_download`는 기존처럼 WS 미연결 시 실패하고 MAIN 수동 fallback을 사용하지 않는다.
- [코드반영] 최종 정적/단위: pytest 130 passed, IG Node 51/51, RTC Node 3/3, Analyze UI 1/1, JS syntax 63, Python compile 38, JSON 6 OK.
- [검증대기] 실제 Windows 자동종료 → picker 표시 → 복사 → `편집폴더 열기`, 모든 PY/WS 종료 → Explorer/프로필/Reels 수동 Video `shortcode.mp4` 저장 확인.

## v315 편집폴더 복사 + 수동 MP4 확장자 정상화
- [코드반영] Side 다운로드 옵션에 `편집폴더에 복사` 체크를 추가하고 상태를 `chrome.storage.local`에 저장한다.
- [코드반영] 새 자동 세션마다 복사 대상 목록을 초기화하고 실제 신규 저장된 MP4만 수집한다. 전체 자동종료 후 WS8771 `ig_copy_to_edit_folder`를 호출한다.
- [코드반영] WS8771이 Windows native FolderBrowserDialog를 띄우고 선택 폴더로 MP4를 복사한다. 기존 동일 파일명은 덮어쓰지 않는다.
- [코드반영] `igblueSafePath(original)` 90자 재절단을 제거하고 `igblueSafeFileNameKeepExt()`로 240자 제한 뒤에도 `.mp4`를 보존한다.
- [코드반영] 수동/자동 공통 `igblueResolvedMediaExt()`에서 video는 `.mp4` 강제. 물리 저장명은 Instagram 원본 파일명 유지.
- [코드반영] `test_ext_edit_copy_manual_filename_v315.js`, WS8771 edit-copy 단위 테스트 추가. 정적/단위: pytest 130 passed, IG Node 50/50, RTC Node 3/3, Analyze UI 1/1, JS syntax 62, Python compile 38, JSON 6 OK.
- [검증대기] 실제 Windows 자동종료 → 폴더 선택 → 복사, 기존 편집파일 무덮어쓰기, PY/WS 전체 종료 후 수동 Video 클릭 `.mp4` 저장 확인.


## v310 Tray 아이콘 + RTC 시작 숨김
- [코드반영] EXT `icons/logo.png` 기반 공용 Tray PNG/ICO를 `_St/Shared/assets`에 추가.
- [코드반영] Shared WindowsTrayIcon에 `icon_path` 및 Win32 `LoadImageW` 파일 아이콘 로드 추가.
- [코드반영] Auto8700·WS8771 Tray가 공용 프로젝트 ICO를 사용하도록 연결.
- [코드반영] RTC8790_8791 Tray 연결, 실행 직후 숨김, Tray 실패 시 메인창 복원, `.` 재숨김 버튼, 종료 시 Tray cleanup 추가.
- [코드반영] manifest/Auto/Cache/WS/RTC 표시 버전 v310 동기화.
- [코드반영] 정적/단위: pytest 128 passed, IG Node 45/45, RTC JS 3/3, Analyze UI 1/1.
- [검증대기] 실제 Windows에서 Auto/WS/RTC 공용 아이콘, RTC 시작 시 무창+Tray, 클릭 복원, `.` 재숨김, X cleanup 확인.

## v309 Auto8700·WS8771 최소창/Tray
- [코드반영] 최종 정적 결과: pytest 125 passed, IG Node 45/45, Analyze UI 1/1, RTC JS 3/3, JS syntax 56, Python compile 36, JSON 6 OK.
- [코드반영] Auto8700 `_` → 34x34 보라색 `ㅁ` 단일 UI, `ㅁ` → 전체 UI 복원.
- [코드반영] WS8771 기존 상태색 `ㅁ` 최소창 유지.
- [코드반영] Auto8700·WS8771 `.` → Win32 Tray 이동, Tray 클릭 → 화면 복원.
- [코드반영] 공용 `_St/Shared/windows_tray.py` 추가. 외부 패키지 없음, Tray 생성 실패 시 UI 화면 유지.
- [코드반영] 패키지/화면 버전 v309 동기화.
- [검증대기] 실제 Windows notification area 아이콘 생성, 클릭 복원, 종료 시 아이콘 정리 확인.

## v308 현재 작업
- [코드반영] Auto8700 실행 위치에서 현재 `_St/IG_StYellow` 절대경로를 계산한다.
- [코드반영] CDP `Extensions.getExtensions`로 unpacked EXT 설치 여부와 실제 `path`를 확인한다.
- [코드반영] 미설치면 `Extensions.loadUnpacked`, 같은 이름이 다른 경로면 `Extensions.uninstall` 후 현재 경로에서 재설치한다.
- [코드반영] 설치·경로 확인이 끝난 뒤에만 기존 EXT `chrome.runtime.reload()` 최초 1회 → 현재 Instagram Page.reload → manifest/content version 검증을 실행한다.
- [코드반영] 체크 로그 순서: CR-01 Runtime, CR-02 설치·경로, CR-03 EXT reload, CR-04 Instagram 새 코드 적용/CDP:O.
- [코드반영] Auto8700 단위 테스트 38 passed.
- [검증대기] 실제 Windows에서 미설치/동일경로/이동경로 3가지 케이스와 `CR-01~04`를 확인한다.

## v307 현재 작업
- [코드반영] `CDP:O` 판정을 8700 포트 응답에서 Instagram `Runtime.evaluate` 실제 성공 기준으로 변경했다.
- [코드반영] Auto8700 프로세스 최초 CDP 연결 시 `IG Sorter Yellow` EXT target을 manifest name으로 찾고 `chrome.runtime.reload()`을 CDP로 1회 요청한다.
- [코드반영] EXT reload 뒤 현재 Instagram target을 `Page.reload` 1회 하고, 로컬 manifest version_name과 EXT/content version 일치를 확인한 뒤에만 O를 허용한다.
- [코드반영] Content의 CDP proof가 `ok:false`를 강제로 true로 바꾸던 로직을 제거했다.
- [코드반영] 상태 worker가 현재 Runtime+EXT 검증 결과로 `AUTO8700_SCHEDULE_STATE.cdp_ready`를 갱신해 stale O를 막는다.
- [코드반영] manifest 버전을 전역값으로 사용해 Side/Content/복사 진단 버전을 동기화했다.
- [코드반영] Auto8700 파일 변경은 마지막 변경 + 3초, 서비스별 1회성 worker로 재실행한다.
- [코드반영] 자동 중단 표시 보존, 화면 리스트 현재 번호 시작, Shift/Ctrl 수집계정 더블클릭 기능을 유지한다.
- [코드반영] 정적 검증: pytest 118 passed, IG Node 45/45, JS syntax 57, Python compile 35, JSON 6.
- [검증대기] 실제 Windows에서 CR-01→CR-02→CR-03 완료 후에만 CDP:O가 표시되는지 확인한다.
- [검증대기] Auto8700 재실행 1회당 EXT reload도 1회이고 탭 이동·페이지 로딩에는 반복되지 않는지 확인한다.

## v304 현재 작업
- [코드반영] Cache8701 target manager에서 `owner_active`를 감시 중단 조건에서 제거했다.
- [코드반영] `cdp_alive=true`와 Instagram target 존재만으로 감시 가능 여부를 판단하는 보호 함수를 추가했다.
- [코드반영] 자동 섬네일 설정에 `8701에 로깅` 체크를 추가하고 Background→8701 설정 전달에 포함했다.
- [코드반영] 체크 시 실행별 단일 로그 파일 생성, 생성 전 오래된 로그 삭제, 총 20개 이하 유지 로직을 추가했다.
- [코드반영] CI-00~CI-06 기능 체크 로그와 실패 지점 `[예외추적]`을 파일에 기록한다.
- [검증대기] 실제 Windows에서 OWNER active=false 상태의 신규 이미지 저장, SQLite 등록, 8780 표시, 로그 파일 20개 회전 확인.

## v303 현재 작업
- [코드반영] v297 기준에서 CDP 상태 원본을 Side/Background로 분리하고 Main을 표시 전용으로 변경했다.
- [코드반영] 새 문서 startup은 X가 아니라 확인중이며 Background 상태를 즉시 요청한다.
- [코드반영] Cache8701 v300 저장 구조 중 shortcode 실제확장자·SQLite·중복스킵·최소 index·상태 집계만 이식했다.
- [코드반영] v297의 기존 대상 0개 Swipe·날짜 경계 분기에 보호 주석과 회귀 테스트를 추가했다. 흐름 자체는 재작성하지 않았다.
- [코드반영] Explorer 기본 섬네일 링크를 가로채지 않는 회귀 테스트를 추가했다.
- [검증대기] 실제 Chrome 새로고침·URL 이동 후 1초 이내 CDP:O, 실제 Cache 파일·SQLite, 대상 0개 Swipe 후 다음 URL, EXT 전 섬네일 클릭.


## v297 Analyze8780 `_StDown` Instagram 가상 폴더
상태: `[코드반영·실제 Windows 검증대기]`

- 숫자 `post_id/asset_id` 미디어 URL·조회 API 제거.
- 게시물 갱신 때 계정·shortcode·실제 확장자로 표준 파일 자동 검색.
- `/_StDown/instagram/{계정}/{shortcode}.{확장자}` inline 응답과 MP4 Range 지원.
- 실제 절대경로 표시·경로 복사·Explorer 파일 선택.
- DB `media_assets`는 다운로드 기록·삭제 안전 확인에만 내부 유지한다. 8780 목록·상세 조회는 해당 행을 조회하거나 주소 식별자로 사용하지 않는다.
- Instagram 외 플랫폼은 이번 목표에서 제외.

## v296 shortcode 실제확장자·DB·8780 로컬 표시
상태: `[코드반영·실제 Windows 검증대기]`

- 수정 파일: `Cache8701/cache8701_main.py`, `Shared/storage/sort_storage.py`, `Shared/storage/__init__.py`, `Analyze8780/analyze8780_repository.py`, `Analyze8780/analyze8780_main.py`, `Analyze8780/web/index.html`.
- Cache8701은 `{shortcode}_thumbnail.*` 대신 `{shortcode}.{실제확장자}`로 원자 저장한다.
- 동일 파일이면 재기록하지 않지만 Shared DB 등록은 생략하지 않는다.
- Shared source mode와 공통 경로·기존 파일 탐색 함수를 추가했다.
- Analyze8780은 현재 열린 DB 기준으로 기존 로컬 파일을 복구 등록하고 실제 존재하는 media_assets만 화면에 제공한다.
- 8780 저장 배지는 JPG 고정 표시가 아니라 실제 파일 확장자를 표시한다.
- 기존 10분 통계와 observation 중복 처리 코드는 변경하지 않는다.
- 정적 결과: pytest 103, Node test 45, JS syntax 52, compileall·JSON·manifest OK.
- 다음 확인: Windows CI-06의 db/post_id/asset_id/file, 신규 shortcode 파일명, 8780 로컬 URL·확장자 배지.


## v295 Cache8701 독립 CDP session
상태: `[코드반영·실제 Windows 검증대기]`

- Auto8700 8707에 `/api/cdp/connection` 읽기 전용 API를 추가했다.
- Cache8701의 고정 `cdp_port=9222` 의존을 제거하고 Auto8700이 실제 실행한 Chrome 포트를 사용한다.
- browser WebSocket 한 연결에서 Instagram target마다 `Target.attachToTarget(flatten=true)` 독립 session을 만든다.
- target 집합·owner generation 변경 시 기존 Cache8701 session을 정리하고 새 session으로 연결한다.
- Cache8701은 Network 읽기 명령만 사용하며 Auto8700의 탭 제어 역할을 침범하지 않는다.
- 코드 검증: Cache+Auto 37 passed, 전체 pytest 96 passed, IG Node 41 OK, JS syntax 51 OK, compileall OK.
- 다음 확인: Windows에서 CI-00 `cdp_port=8700`, CI-02 session, CI-03 URL, CI-04 body, CI-05 파일, CI-06 DB 및 yjm_pmonit 생성 로그.


## v294 Cache8701
- [코드반영] Side→8701 메타데이터·설정 전달
- [코드반영] CDP 이미지 응답 양방향 URL 매칭과 원본 body 저장
- [코드반영] Auto8700 관리 서비스 등록
- [검증대기] 실제 Chrome CI-01~CI-06 및 `_StDown` 생성


## v291 Auto8700 이미 본 JPG 응답 자동 저장

상태: `[코드반영·실제 Windows 검증대기]`

- CDP `Network.responseReceived`의 HTTP 200 `image/jpeg` 후보만 추적한다.
- `Network.loadingFinished` 뒤 현재 화면의 실제 `img.currentSrc`와 응답 URL이 정확히 일치할 때만 `Network.getResponseBody`를 호출한다.
- JPEG 시작/종료 시그니처와 최소 크기를 검사한 뒤 `_StDown/instagram/{owner}/{shortcode}_auto_seen.jpg`에 원자 저장한다.
- 저장 후 Shared `record_downloaded_file()`로 SQLite media_assets에 등록해 Analyze8780 로컬 JPG 우선 표시와 연결한다.
- 프로필·추천·화면 밖 이미지와 URL 불일치는 조용히 건너뛰며 완료로 기록하지 않는다.
- 실제 Chrome에서 현재 게시물 JPG 저장·DB 등록·8780 표시를 확인하기 전까지 `[검증대기]`다.


## v288 Analyze8780 LIKE·DB 번호·미디어 마무리

상태: `[코드반영·실제 Windows 검증대기]`

- `↻`, `0/200` 제거와 계정 헤더 `social_accounts · 검색/전체`
- `✓` quick_check·테이블·개수 점검
- 입력값 그대로 SQLite LIKE, `tem%` 회귀 수정, input 자동 조회
- DB select 옆 1..N 단일 클릭 버튼
- 저장 폴더 탐색기 열기, MP4/JPG localhost inline·Range
- 게시물 개별 posts·통계·media_assets·실제 파일 삭제, 공유 경로 차단
- 계정 전체 삭제 UI 제외
- 실제 Windows 확인 전 상호작용 항목은 완료로 올리지 않는다.


## v287 Analyze8780 DB·검색·페이징·ApexCharts

상태: `[코드반영·실제 Windows 검증대기]`

- DB 파일 select 선택→활성 SQLite 전환→계정·게시물 재조회
- 왼쪽 계정 페이지 제거, 최대 10,000개 전체 표시
- `abc / abc% / %abc / %abc%` 검색 규칙과 원형 `?` 도움말
- 오른쪽 게시물 보기 `50 / 100 / 200 / 10000`과 페이지 계산
- 정렬 항목 내림차순 고정, 이미지 세로 영역 확대·원본 비율 유지
- 게시물별 최근 통계 50개 ApexCharts 자동 선 차트·shared hover tooltip
- 최종 정적/단위: JavaScript syntax 50, Analyze UI Node 1, IG 38, RTC JS 3, Python compile 33, pytest 80 passed
- 다음 검증: 실제 8780 DB 2개 전환, 400개 게시물 50/100/200/10000 페이지, 검색 네 규칙, CDN 차트/툴팁
- 제외 목표: Auto8700·WS8771 동작 변경, Instagram 수집 방식 변경, 타 모듈 UI 변경

## v286 현재 작업
- 상태: `[검증대기]`
- 단일 목표: v282의 자동 WS8771 direct·수동 Chrome/WS 분리 다운로드와 UI를 유지하면서, 자동실행은 항상 새 관리 탭에서 시작하고 이전·오류·마지막 자동 탭을 exact CDP target으로 종료한다.
- 자동 새 실행·저장 진행상태 재개: `0/N`이면 목록 1번 계정, `1/N` 이상이면 지정 계정을 새 자동 탭으로 연다. 목록이 없으면 현재 Instagram URL을 새 자동 탭으로 복제한다.
- Explore 잔존 snapshot은 자동 시작 후보로 사용하지 않는다.
- 계정 전환: 새 탭 ready→Side OWNER commit→이전 `auto_created` 탭 CDP `Target.closeTarget`→target 제거→Chrome tab 제거 확인 순서다.
- 종료 실패: exact target close를 한 번 재시도하고 실패/targetId 누락 때만 `chrome.tabs.remove`로 보조 종료한다. 이전 탭 응답·unload·OLD_TAB_CLOSED 메시지를 기다리지 않는다.
- 보호: 사용자/비관리 탭은 닫지 않고 `OK_USER_TAB_PRESERVED`로 남긴다.
- 자동 중지·오류·최종 자동종료에서도 현재 자동생성 탭 종료 요청을 실행한다.
- 변경 모듈: IG Background·Side·Content/Main 버전 표식·manifest, Auto8700 exact target close API, 테스트·문서.
- 신규 테스트: `IG_StYellow/test_ext_auto_fresh_tab_cdp_close_v286.js`, Auto8700 exact target close 단위 2개, `test_verification_checklist.py` v286 검증목록 검사.
- 정적 결과: 전체 JavaScript syntax 49 OK, IG test 38 OK, RTC JS test 3 OK, Python compile 33 OK, pytest 77 passed, manifest `2.3.8.2860 / 2.3.8.286` OK.
- 실제 완료 기준: Windows CDP:O에서 2개 이상 계정, 첫 실행 전에 목록 밖 Explore 자료 0개, 계정별 새 tab/target, 이전 오류 탭 제거, 마지막 자동 탭 제거, 사용자 탭 보존, 자동 WS direct와 수동 다운로드 각각 실제 파일 OK.
- 제외 목표: Instagram 검색 이동, fingerprint/UA 변경, 자동·수동 다운로드 재통합, 기능 외 UI 변경.

## v282 현재 작업
- 상태: `[검증대기]`
- 단일 목표: MAIN 우상단 진단 중복을 한 줄 상태와 `_ / □`로 통합하고, SIDE 0/N을 한 번에 1/N으로 바꾸는 `1부터` 버튼을 추가한다.
- MAIN 표시: `CDP:O · 탭 N · OWNER tab 000000`; 클릭 시 전체 진단 복사, `_` 축소·복원, `□` 상세 열기.
- 상세 패널은 자동 갱신하지 않고 열 때와 `새로고침` 버튼에서만 최신 상태를 읽는다.
- 기존 `CDP`, 탭 표시, `DOM 진단복사`, `MAIN v 👁`의 화면 중복은 숨긴다.
- SIDE `1부터`: 목록 존재 + index 0 + 자동실행 정지일 때만 활성, 클릭 시 index 1 저장, summary 토글 이벤트 차단.
- 변경 모듈: IG Content UI, MAIN ready/DOM 진단 버전 표식, Side HTML/JS, manifest/version.
- 신규 테스트: `IG_StYellow/test_ext_ui_compact_v282.js`.
- 정적 결과: JavaScript syntax 48 OK, IG test 37 OK, Python compile 33 OK, pytest 74 passed.
- 실제 완료 기준: Chrome에서 한 줄 상태만 표시, 클릭 복사, 패널 텍스트 선택 3초 이상 유지, `_ / □` 동작, Side 0/3에서 `1부터`→1/3, 1 이상·실행 중 비활성 확인.
- 제외 목표: OWNER_LOST fallback, pending handoff 정리, Analyze8780 KST 표시는 이번 작업에 포함하지 않는다.

## v281 이전 작업
- 상태: `[검증대기]`
- 단일 목표: YELLOW 관리 새 탭을 Instagram 로드 전에 CDP로 선삽입해 unload 등록을 차단하고 실제 등록·호출 원인을 로그로 확인한다.
- `CL-01`: Background→Auto8700 bootstrap target 탐색 요청.
- `CL-02`: `Page.addScriptToEvaluateOnNewDocument` 등록 확인.
- `CL-03`: 빈 문서 즉시 설치 후 Instagram 이동 확인.
- `CL-04`: unload 차단 또는 beforeunload/pagehide/visibilitychange 등록·실행 source/stack 수집.
- 변경 모듈: Auto8700, IG Background, IG Content bridge, manifest/version.
- 신규 테스트: `IG_StYellow/test_ext_cdp_lifecycle_preload_v281.js`, Auto8700 lifecycle 단위 테스트 3개.
- 정적 결과: JavaScript syntax 47 OK, IG test 36 OK, Python compile 33 OK, pytest 74 passed, 생성 스크립트 동적 모형 OK.
- 실제 완료 기준: 3계정 이상 자동 실행에서 각 replacement 탭마다 CL-01→CL-03 완료, 문제 unload는 BLOCKED_REGISTER/BLOCKED_PROPERTY 기록, 이전 탭 종료 뒤 다음 계정 자동 계속, 응답 없음 재발 없음.
- 제외 목표: OWNER_LOST fallback 교정, pending handoff 정리, Main 복사 UI, Analyze8780 KST 표시는 이번 작업에 포함하지 않는다.

## IG v280 미완료 이전 작업
- 상태: `[검증대기]`
- 체크 ID: `T-IG-V280-TAB-OWNER-001`
- 단일 목표: 여러 Instagram 탭의 OWNER를 최근 이력으로 관리하고 새 탭 OWNER 확정 뒤 이전 탭을 닫는다.
- Background는 최근 20개 탭 이벤트, generation, run_seq, pending handoff를 저장하고 서비스 워커 재시작 시 수명 상태를 복원한다.
- Side는 새 tab_id를 먼저 세션에 반영한 뒤 `IGBLUE_COMMIT_TAB_HANDOFF`를 호출한다.
- Main `igblue_main_diag_toggle/panel`과 DOM 진단복사에 CDP·탭 수·OWNER·인계 이력을 표시한다.
- v279c WS8771 direct 다운로드는 변경하지 않는다.
- 테스트: `test_ext_tab_control_v280.js`, `test_ext_tab_replacement_v279d.js`, 전체 회귀.
- 정적 결과: JavaScript syntax 46 OK, IG test 35 OK, Python compile 33 OK, pytest 71 passed.
- 실제 Chrome 완료 기준: CDP:X→O 시작과 CDP:O 시작 모두 3계정 완료, 매 전환 OWNER 선확정, 이전 탭 종료, 중단 없음.


## IG v279d 완료 참고
- 상태: `[완료]`
- 체크 ID: `T-IG-V279D-TAB-REPLACE-001`
- 단일 목표: 자동 계정 전환을 기존 탭 URL 재사용에서 새 탭 교체 방식으로 변경한다.
- 새 탭을 비활성으로 생성하고 Content/Main 준비 확인 후 활성화한 다음 이전 자동 탭만 닫는다.
- 새 탭 실패 시 이전 탭을 보존하고 새 탭만 제거한다.
- 이전 탭 종료 guard는 900ms 제한을 두며 실패·timeout이 새 탭 진행을 막지 않는다.
- document_start unload 전역 후킹은 제거하고 이전 탭 종료 직전의 제한 guard만 남긴다.
- 유지: v279c WS8771 direct MP4/JPG 저장, v279ccc 진행률·No·ETA.
- 테스트: `test_ext_tab_replacement_v279d.js`, `test_ext_navigation_unload_guard_v279cc.js`, 전체 IG 회귀.
- 정적 결과: JavaScript syntax 45 OK, IG test 34 OK, Python compile 33 OK, pytest 71 passed.
- 실제 Chrome 확인: 첫 계정 새 tab_id, 이전 tab_id 종료, 다음 계정 반복, 자동종료 후 현재 탭 클릭, MP4/JPG 저장.
- 제외: 카테고리 100개, Analyze8780 성장 분석 UI.
## IG v279ccc 현재 작업
- 상태: `[검증대기]`
- 첫 계정·다음 계정 URL 이동 전 guard 호출/결과/차단/URL update/ready 콘솔 로그를 남긴다.
- guard 실패는 첫 URL 이동 중단이 아니라 `GUARD_FAILED_CONTINUE` 기록 후 이동 계속으로 변경했다.
- `#IGBLUE_NoTop` 생성만 기다리지 않고 MAIN 스크립트 끝의 ready marker를 확인한다.
- 다운로드 No는 실제 rank가 있을 때만 표시하고 `No---` 기본값은 제거했다.
- 자동 진행률은 전체 계정×Top 목표 기준이며 자동종료 전 100%가 되지 않는다.
- 발견 자산은 shortcode+mp4/jpg 단위로 예정/완료를 집계해 `파일 완료/예정`으로 표시한다.
- 종료예상은 최근 성공 세트 20개의 전체 처리시간 이동평균과 설정 대기시간을 사용한다. 표본 전에는 `계산중`이다.
- 테스트: `test_ext_navigation_unload_guard_v279cc.js`, `test_ext_progress_eta_v279ccc.js`, 전체 IG 회귀.
- 정적 결과: JavaScript syntax 44 OK, IG test 33 OK, Python compile 33 OK, pytest 71 passed.
- 실제 Chrome 결과: CDP:O 2계정·3계정, 3계정×Top3, 파일 18/18, 자동종료 `OK`.

## 이전 IG v279cc URL 이동 unload guard·준비 확인
- 상태: `[검증대기]`
- 체크 ID: `T-IG-V279CC-NAV-UNLOAD-READY-001`
- 단일 목표: 자산 2/2 완료 뒤 다음 계정 URL 이동에서 `unload` 등록을 제한하고 새 문서 Content/Main 준비가 확인된 뒤 자동 실행을 재개한다.
- 변경: URL 이동 전 MAIN world에서 `unload` addEventListener와 `window.onunload`만 차단한다.
- 변경: guard 설치 실패 시 URL을 열지 않고 오류·tab_id·guard 결과를 남긴다.
- 변경: Side 고정 4.5초 대기를 제거하고 Background가 목표 URL·탭 complete·Content probe·Main panel을 확인한다.
- 진단: `unload_guard`, `navigation_ready`, 실제 URL, 탭 status, probe 오류, 시도 횟수, 준비 소요시간을 cycle 결과에 남긴다.
- 신규 테스트: `IG_StYellow/test_ext_navigation_unload_guard_v279cc.js`.
- 정적 결과: JavaScript syntax 39 OK, IG test 32 OK, Python compile 33 OK, pytest 71 OK.
- 실제 Chrome 확인: 2/2 완료 → 다음 계정 이동, Permissions policy 경고 억제 여부, 1/3→2/3 자동 재개, 다운로드 회귀.
- 제외: 다운로드 진행률/No/ETA, 기본 카테고리 100개, Analyze8780 시각화.

## IG v279c v262 자동 다운로드 exact 복원
- 상태: `[완료]`
- 체크 ID: `T-IG-V279C-AUTO-V262-RESTORE-001`
- 기준: v262 CDP:O 사용자 실제 확인 — 2개 계정 순회, 전체 게시물 5개, MP4 5개, JPG 5개, `WS8771 direct download`, 실제 저장 경로 표시.
- 변경: 자동 snapshot 자산은 MP4/JPG URL만 허용하고 `metadata`를 자동 완료 자산에서 제거했다.
- 변경: 자동 direct/cache pair와 WS8771 direct asset 전송을 v262 구현으로 복원했다.
- 완료 조건: 실제 파일 저장 또는 실제 중복 파일·JSON·보고서 확인. metadata만 저장된 경우 완료 수 증가 금지.
- 유지: 수동·Filtered metadata 정책, Side 계정 클릭 선택, MAIN hover 비활성, v279b 상태 보존.
- 정적 결과: JS syntax 38 OK, IG test 30 OK, 폐기 진단 1 SKIP, Python compile 33 OK, pytest 70 OK.
- 실제 Chrome v279c 결과: 사용자 연속 실행 MP4/JPG 실제 저장·WS8771 direct 완료 `OK`.
- v279c 항목은 완료 처리하고 v279cc URL 이동 회귀에서 자동 저장이 유지되는지 확인한다.

## IG v279bb MAIN 스코프·자동 다운로드 복구
- 상태: `[코드반영]`
- 체크 ID: `T-IG-V279BB-MAIN-SCOPE-001`
- `IGBLUE_MAIN_HOVER_DIAGNOSTIC_ENABLED is not defined` 오류를 제거했다.
- v279bb 당시 v279aaaa 동일 비교는 실제 자동 파일 저장을 보장하지 못했고, 사용자 확인에서 MP4/JPG 0개로 실패했다. v279c에서 v262 exact 경로로 대체했다.
- 정적·단위 결과: JS syntax 37 OK, IG test 29 OK, 진단 1 SKIP, Python compile 33 OK, pytest 71 OK.
- 실제 Chrome 자동 다운로드는 검증대기다.
- `IGBLUE_` → `YELLOW` 전체 변경은 별도 후속 작업이다.

## IG v279b 현재 작업
- 체크 ID: `DOWNLOAD-STATUS-HOLD-01`
- 상태: `[코드반영]`
- 단일 목표: 다운로드 시작 전에는 상태 표시를 변경하지 않고, 실제 시작 순간에만 초기화하며, 완료 후 마지막 실제 파일 정보를 보존한다.
- 제거: 계정 이동·새 자동실행·`auto_account_continue`에서 다운로드 상태를 선제 초기화하는 처리.
- 제거: 다운로드 전 `자동현황 대기 / 다운로드 진행 없음`, `No---`, `asset: 파일`, `파일: 대기중`을 자동 생성하는 처리.
- 유지: 자동 Top, 수동 JPG/MP4, Side 계정 클릭, Auto8700·WS8771, 완료 집계·자동종료.
- 정적 결과: `test_ext_download_status_preserve_v279b.js` 및 전체 IG 회귀 검사 OK.
- 실제 Chrome 결과: `UNKNOWN`.
- 다음 확인: 완료 표시가 있는 상태에서 새 자동실행을 시작해 후보 탐색·계정 이동 동안 표시가 그대로인지, 실제 다음 다운로드 시작 순간에만 새 파일 상태로 바뀌는지 확인한다.

### 제공 로그 검토
- 첫 실행: 11:31:20~11:31:53, 3개 계정×목표 2개 완료 로그 존재.
- 두 번째 실행: 11:33:22~11:33:59, 첫 계정 2개·마지막 계정 2개 완료 로그 존재.
- 두 번째 실행의 2/3 계정은 `AD-02` 이후 로그가 없으며 다음 계정으로 전환됐다. 현재 로그만으로 후보 없음 사유는 확인 불가하므로 별도 완료·실패 판정하지 않는다.
## IG v279aaaa
- [코드반영] Side `IG 계정명` 클릭 전용 추가 대상 선택.
- [코드반영] `계정 확인중`을 `IG 계정 선택`으로 교체.
- [코드반영] 자동 계정 확인 타이머·Main current-account polling·URL 자동 초기화 제거.
- [검증대기] 다른 계정 카드 연속 선택·계정추가·SQLite 저장 실제 확인.

## IG v279aaa
- `[코드반영]` MAIN hover 비활성 진단.
- 실제 Chrome에서 MAIN JPG/MP4 및 페이지 이동 재검증 필요.

<!-- FILE: _St/ai_read_패치.md | ROLE: sort 전체 현재 작업·검증대기 -->
# sort 현재 패치 — v286

## IG v279aa
- 수동 다운로드 복구와 Auto8700 안내 우선순위 교정
- 실제 Chrome 검증대기

상태: `[코드반영·실제 Windows 검증대기]`

## 단일 목표

Auto8700의 `자동실행`과 `CDP모드 실행`이 8700 포트만 남은 불완전 상태를 정상으로 오판하지 않고, 실제 CDP Chrome과 Instagram Runtime을 준비하도록 복구한다.

- `/json/version` 응답만으로 실행 성공 처리하지 않음
- Instagram page target·webSocketDebuggerUrl·Runtime.evaluate 응답 확인
- `/json/new`는 PUT으로 호출하고 실패 시 browser `Target.createTarget` 사용
- 수동 `자동실행`·`CDP모드 실행`은 기존 정상 Instagram 탭을 앞으로 표시
- 8700만 열리고 Runtime이 없으면 `CDP:PORT`·`CDP 복구` 표시
- 전용 `D:\cdp-data-dir` Chrome만 복구 종료 후 재실행
- 일반 Chrome User Data 프로세스는 종료하지 않음
- 설정 창에 CDP 실행 성공 또는 실패 원인 표시

## 실제 확인

- Auto8700 `자동실행` 클릭 → 전용 CDP Chrome 실행 또는 기존 탭 앞으로 표시
- 설정 `CDP모드 실행` 클릭 → 같은 동작과 결과 문구 확인
- 전용 CDP Chrome 강제 종료·8700 잔류·Instagram 탭 없음 상태 각각 복구 확인
- 일반 Chrome 창·프로필은 유지

## 제외

- Instagram 다운로드 로직
- Main 계정 hover/click
- 응답 없음 이후 계정 자동 스킵
- Analyze8780 UI 변경
## v290 Analyze8780
- 차트 결측값 null 단절, 화면 설정, 로컬 JPG 우선, MP4 재생, 파일/폴더 버튼 코드반영
- 코드 검증 OK, 실제 Windows UI 검증대기

## v292 자동 섬네일 다운저장 2단계 설정
- [코드반영] 전체 사용/미사용 설정 추가. 기본=사용.
- [코드반영] 페이지별 설정 추가: Explorer·검색=미사용, 단일 게시물=사용, 계정 프로필=사용, 계정 릴스=사용.
- [코드반영] Side chrome.storage → background 8707 event → Auto8700 devtools_network_watch 설정 연결.
- [코드반영] Auto8700 현재 페이지 유형별 JPG 저장 허용 검사 추가.
- [검증대기] 실제 Chrome에서 Explorer 저장 차단 및 나머지 페이지 저장 확인.

## v293 Side 톱니바퀴 자동 섬네일 설정
- 상태: `[코드반영·실제 Chrome 검증대기]`
- 톱니바퀴 설정 모달에 `자동 섬네일` 탭과 전체/페이지별 2단계 설정을 실제 렌더링한다.
- 기본값: 전체 ON, Explorer OFF, 단일 게시물/계정 프로필/계정 릴스 ON.
- 전체 OFF 시 하위 체크를 비활성화한다.
- Save 시 모달 값이 기존 DevTools state보다 우선하며 storage·8707 전달값을 갱신한다.
- 본문 중복 체크 UI를 제거하고 위치 안내로 교체한다.
- 실제 Chrome의 표시·저장·복원과 Auto8700 local.json 반영은 `[검증대기]`다.

## v305 코드반영·검증대기
- [코드반영] `Showing A` 필터 결과 목록을 Cache8701에 자동 전송.
- [코드반영] OBSERVED/CACHE_RUNS/CI-00~CI-06를 `tab_id` 기준으로 분리·기록.
- [코드반영] CDP 세션 프로필 계정과 메타데이터 계정 불일치 시 매칭 금지.
- [코드반영] 자동 시작은 화면 리스트 번호만 사용, input 전체 복사 보정.
- [검증대기] moyasi_jm `Showing 10 of 12`에서 대상 10, 처리 10, 신규+중복=10, 실패 0.

## v307 자동 중단 표시 보존
- [코드반영] 사용자 자동 중단 직전 통합 진행 표시를 스냅샷으로 보존한다.
- [코드반영] 기존 표시 마지막 줄에 `⛔ 자동 중단`만 추가하고 사유/이어하기 문구로 덮어쓰지 않는다.
- [검증대기] 실제 Side에서 진행 정보가 유지된 채 마지막 줄에 중단 표시만 추가되는지 확인한다.


## v307 화면 리스트 시작번호 절대 기준
- [코드반영] 사용자 중단 스냅샷은 이전 진행 표시 보존용으로만 사용한다.
- [코드반영] `시작` 클릭 시 화면 `수집계정 목록` 입력값을 다시 읽고 그 번호에서 새 실행한다.
- [코드반영] 저장된 `account_queue_index`, last_rank, 이전 실행 resume 상태가 화면 리스트 번호를 덮어쓰지 않는다.
- 예: 2/3에서 중단 후 사용자가 1/3으로 수정하고 `시작` → 반드시 1/3부터 실행.
- [검증대기] 실제 Chrome에서 2/3 중단 → 1/3 수정 → 시작 후 AS-03=1/3 확인.

## v307 수집계정 modifier 더블클릭
- [코드반영] 수집계정 목록 계정 줄 `Shift+더블클릭=새창`, `Ctrl+더블클릭=새탭`을 추가했다.
- [검증대기] 실제 Chrome에서 클릭한 계정과 열린 Instagram 계정이 일치하는지 확인한다.


## v311 Side 수집계정 섞기·자동섞기·IG_DBG 콘솔 억제
- 상태: `[코드반영] / 실제 Chrome 검증대기`
- 수동 `섞기`: `수집계정 목록` 헤더의 접기 `□` 바로 앞에 추가. 자동실행 중·현재채널만·2개 미만에서는 비활성.
- 순서 알고리즘: Fisher–Yates + 동일 순서 발생 시 1칸 회전으로 2개 이상은 반드시 기존과 다른 순서 보장.
- 저장: `chrome.storage.local` `IGBLUE/account_queue_shuffle_v311`에 최대 50건의 before/after/source/index/ts 이력과 current_order 보관.
- `자동섞기`: `자동실행 사용` 바로 다음 체크. 설정은 `IGBLUE/account_queue_auto_shuffle_v311`에 Chrome 공통 저장.
- 자동 실행 조건: 새 사용자 `시작`, 현재 화면 `1/N`, N>1일 때만 시작 직전 1회 섞고 index=1 유지. 0/N·2/N 이상·계정 continuation은 제외.
- `[IG_DBG]` 반복 콘솔: Side/Content/Background/Main에서 console 출력만 비활성화하고 debug snapshot 저장은 유지.
- 테스트: `IG_StYellow/test_ext_account_shuffle_v311.js` + 전체 회귀.
- 정적 결과: pytest 128 passed, IG Node 46/46, RTC Node 3/3, Analyze UI 1/1, JS syntax 57, Python compile 38, JSON 6 OK.


## v312 Explorer scroll MAIN metadata 파서 보강
- 상태: `[코드반영] / 실제 Chrome 검증대기`
- upstream 2.4.0(ij1)→2.4.1(ij2) 의미 diff에서 Explorer `clips`의 `layout_content.medias` 처리 추가를 확인했다.
- 현재 `instagram_inject.js`의 기존 `fill_items`·`one_by_two_item` 경로는 보존하고 `medias[].media`·`medias[].clips.items[].media`만 추가했다.
- `test_ext_explore_clips_scroll_v312.js`로 기존/신규/sparse 응답 회귀를 보호한다.
- [검증대기] 실제 Chrome Explore에서 첫 화면 후 Swipe/scroll 여러 번 진행해 새 카드 overlay/metadata가 계속 붙는지 확인한다.

## v313 Side 랜덤/예약 UI
- [코드반영] IG v313 Side 요구사항 반영.
- 정적 회귀 `test_ext_side_random_delay_schedule_v313.js` 포함.
- [검증대기] 실제 다운로드 랜덤지연/예약 랜덤분/자동종료 재추첨.

## v314 Side 다운로드 방식 1/2 강제 비표시
- [코드반영] `Down all medias`, `Down filtered medias` 카드에 `d-none`을 추가했다.
- [유지] DOM/핸들러는 삭제하지 않고 향후 복구 가능하게 보존한다.
- [유지] v313 Side 썸네일100·섞기/자동섞기·랜덤초·예약랜덤분 기준.
- [검증대기] 실제 Chrome Side 재열기/상태갱신 후에도 두 카드 비표시 확인.