코드 변경 전 회귀 머지 게이트 확보 — 프로덕션 코드 0줄 변경.
적대적 리뷰 지적("엔진 e2e 테스트 0개", "메타-only는 alpha/압축 회귀에 눈멈") 반영.
- EngineCharacterizationTests: ConvertOneAsync/ConvertManyAsync/ExecuteChainAsync/CombineAsync
실파일 e2e 10 시나리오 — png→jpg(1홉)/svg→jpg(멀티홉)/PDF→페이지별/중간 다중산출물 거부
(line200-205)/이미지N장→TIFF·PDF 결합/멀티홉·단일홉 Skip 존중/동일포맷 Skip/png 재압축
- 단순 파일존재 체크 금지 → 구조메타(치수·HasAlpha·포맷·프레임수·압축) + 내용지문(평균색 우세) 박제
- RoutingMatrixCharacterizationTests: FindBestPath/ReachableOutputs 불변 라우팅(13 경로 홉수 +
self-edge + AvoidLossy 래스터 회피 + UI 추천출력 세트) 박제
- docs/ssot/REFACTOR_SMOKE_CHECKLIST.md: 진입점 수동 스모크(DI·MVVM 전환 직후 강제)
발견된 잠재 부채: combine→TIFF가 Tiff.Compression "lzw" define에도 NoCompression으로 저장(미적용).
동작 보존 원칙에 따라 현재 동작을 박제하고 P3 combine 추출 시 정책 통일로 다룸.
38 → 65개 테스트 전부 그린, 빌드 0경고/0오류.
- src/Directory.Packages.props 신규 — 모든 PackageReference 버전의 단일 출처(SSOT)
- ManagePackageVersionsCentrally=true, 3개 csproj에서 Version 속성 제거
- Magick.NET-Q16-AnyCPU Core 14.13.0 → 14.13.1로 통일(Tests와 정합)
테스트와 프로덕션이 동일 네이티브 바이너리로 동작 → 골든마스터 신뢰 기반 확보
빌드 0경고/0오류, 38개 테스트 전부 그린.
증상: 8K(7680x4320) HEVC 11분 6.76GB mp4 변환이 멈춤.
근본 원인 2가지:
1. mp4→mp4(같은 형식)이 그래프 self-edge 부재로 Skip 처리되고,
QuickProgressWindow가 '전부 건너뜀' 종료 상태를 처리 안 해 멈춘 듯 보임.
2. 강제하던 h264_nvenc가 4096px 초과(8K)를 인코딩 못 해 즉시 실패 →
CPU libx264 8K 폴백이 사실상 무한정 소요(진짜 멈춤).
수정:
- FfmpegProvider: 해상도별 코덱 — videoWidth>4096(8K 등)은 hevc_nvenc(GPU)
→libx265(CPU)로, 이하는 h264_nvenc→libx264. 코덱 강제는 mp4/mkv/mov에만
적용하고 webm/avi/gif는 컨테이너 기본 코덱(vp9 등) 유지.
- FfmpegProvider: 비디오/오디오 동일포맷 self-edge 추가(mp4→mp4 등 재압축).
gif는 제외 — 이미지로도 다뤄져 ffmpeg 미설치 시 Skip→하드실패 회귀 방지.
- QuickProgressWindow.Finish: 성공·실패 없이 전부 건너뜀인 종료 상태를 명확히 안내.
검증: 실제 8K HEVC 클립으로 mp4→mp4 변환 → hevc_nvenc로 정상 인코딩,
28.3MB→2.1MB(93% 압축). 전체 38개 단위테스트 통과(적대적 리뷰 2건 반영).
Package 1.0.3.0.
사용자 원래 요구였던 Codex non-interactive OAuth를 실제 동작까지 검증해 통합. ChatGPT 구독으로 API 키 없이 AI 변환.
- CodexChatClient: codex exec --skip-git-repo-check --ephemeral -o <file> - (stdin 프롬프트). 실제 한글→영어 번역 검증 완료
- ExternalProcessRunner: stdin 지원 + UTF-8 인코딩(한글 깨짐 해결)
- ExternalToolDetector.IsCodexAvailable() + public 승격
- LlmProvider: codex 백엔드 + auto 폴백(키 없으면 Codex)
- SettingsWindow: OpenAI/Anthropic 키(2단계 Verify) + Codex(OAuth) + 외부도구 상태/다운로드 CTA + 모델 선택
- App.Settings를 LlmProvider와 공유(키 저장 즉시 반영)
- MainWindow 네비바 ⚙ 설정 진입점
- 디자인: Cursor/Zed/Raycast 설정 UX + Radix 상태 토큰 영감
ProviderRegistry.OutputsForInput을 그래프 transitive closure로 전환. UI 코드 변경 0으로 멀티홉 변환(json→xlsx, svg→jpg 등)이 사이드바·카스케이드 메뉴에 자동 노출된다. 동일 포맷 self-edge는 제외.
- DirectOutputsForInput(1홉)도 별도 보존
- 카스케이드 메뉴는 PopularOutputs 교집합이라 폭발 없이 풍부해짐
- 테스트 1개 추가 (멀티홉 노출 검증) — 총 38개 통과
- SSOT P6 in_progress
FFMpegCore로 영상/오디오 변환·트랜스코딩·오디오 추출. ffmpeg/ffprobe가 없으면 NotReady로 비활성, PATH 또는 앱 폴더에 두면 자동 활성화(LGPL 분리 호출, 본체 미번들).
- 영상 mp4/mkv/webm/mov/avi/gif, 오디오 mp3/aac/m4a/opus/ogg/flac/wav N×M + 영상→오디오 추출
- ExternalToolDetector.TryFindFfmpeg (앱 폴더 + PATH 탐지)
- 진행률 best-effort (ffprobe duration 기반), 취소 전파
- 테스트 3개 + SSOT status 갱신 — 총 37개 통과
AI를 '키 없으면 비활성되는 부가 엣지'로 통합. 기존 변환에 무영향, 일반 변환과 충돌 없는 txt↔txt/md↔md self-edge만 노출.
- IChatClient + OpenAiChatClient/AnthropicChatClient (HttpClient 직접, SDK 의존 0)
- LlmProvider: summarize/translate/proofread/custom, ISettingsStore 키 + 환경변수(OPENAI_API_KEY/ANTHROPIC_API_KEY) 폴백
- CheckAvailabilityAsync 게이트: 키 없으면 NotReady → 그래프에서 실행 비활성
- ConvertOptions.Ai (백엔드/모델/작업/대상언어)
- 테스트 5개 (키 게이트·프롬프트 구성·그래프 엣지) — 총 34개 통과
AI 키·외부 도구 경로를 안전 저장하고 외부 CLI를 일원화 실행하는 토대. 둘 다 순수 .NET, 실동작 테스트 검증.
- DpapiSettingsStore: DPAPI(CurrentUser) 암호화로 %LOCALAPPDATA%에 저장, 평문 노출 없음 검증
- ExternalProcessRunner: stdout/stderr 수집 + 타임아웃 + 프로세스 트리 Kill (LibreOffice/FFmpeg/Ghostscript 공용)
- 테스트 6개 추가 (암호화 round-trip, echo/비정상종료/타임아웃) — 총 29개 통과
ProviderRegistry를 ConversionGraph로 승격하고 ConversionEngine이 자체 Dijkstra로 멀티홉 경로를 자동 합성하도록 전환. 손실을 LossClass 가중치로 SSOT화.
- ConversionGraph: (node,hop) 라벨링 Dijkstra로 홉 제약 최단경로 (일반 Dijkstra의 hops 오염 false negative 회피)
- ConversionEngine.ExecuteChainAsync: 멀티홉 체이닝, 중간 다중출력 거부, 마지막 홉 Status 존중
- PdfToolProvider: pdf->pdf 구조 압축 (PDFsharp, Save 원자화)
- PairsFromMatrix 자기쌍 제외 (png->png 재인코딩 회귀 방지), PDF->이미지 Rasterize 표시
- xUnit 테스트 프로젝트 신설 + 그래프/회귀 14개 통과
- 적대적 병렬 리뷰(27 agents)로 확정된 13건 중 정확성 핵심 수정
SSOT: P1 done