1
0
Fork 0
Commit graph

48 commits

Author SHA1 Message Date
Yun Chan
ba5738e705 refactor(P5b-1): CommunityToolkit.Mvvm 도입 + OptionsViewModel 추출 (옵션 로직 테스트화)
MVVM 첫 슬라이스 — 테스트 불가능했던 코드비하인드 BuildOptions의 순수 옵션 구성 로직을
헤드리스 단위테스트 가능한 OptionsViewModel.ToConvertOptions로 추출. XAML 바인딩 미변경(런타임 위험 0).

- CommunityToolkit.Mvvm 8.2.2(CPM) + App.csproj. App/ViewModels/OptionsViewModel.cs:
  ObservableObject + [ObservableProperty](Quality/CustomOutputDirectory/ConflictRule/AiTaskIndex/
  TargetLanguage/VideoPreferGpu) → 향후 옵션 패널 직접 바인딩 토대. ToConvertOptions()는 순수.
- MainWindow.BuildOptions: 컨트롤 값을 VM에 반영 후 ToConvertOptions() 위임(동작 동일).
- Tests → App ProjectReference 추가(App 뷰모델 헤드리스 테스트 가능화).
- OptionsViewModelTests 10케이스(품질매핑·AVIF clamp·커스텀폴더 trim·AI작업·대상언어·충돌/GPU).

71 → 81개 테스트 전부 그린, 빌드 0경고/0오류.
2026-06-02 09:51:49 +09:00
Yun Chan
729b9b699d refactor(P6): Independent 배치 병렬화 + Magick ResourceLimits (즉효 최적화)
순차 for-loop(멀티코어를 1코어만 사용)을 코어 수 병렬로 — 50장 배치가 코어 수만큼 가속.
ConvertOptions 불변(P4)이라 공유 읽기 스레드 안전. 시그니처 불변(내부 교체).

- ConversionEngine.ConvertManyAsync: Independent 분기를 Parallel.ForEachAsync(MaxDOP=BatchParallelism)로.
  결과는 인덱스 고정 ConvertResult[]로 순서 보존. 진행률은 완료 건수(Interlocked.Increment)로 보고
  (파일별 분수 진행률은 동시 실행에서 의미가 흐려짐). DOP<=1이면 기존 순차 경로(세부 진행률 보존).
  CombineToSingle은 단일 연산이라 병렬 대상 아님(기존대로).
- ConvertOptions.BatchParallelism(기본 = 논리 코어 수) 추가 — 미디어 위주 배치는 낮춰 튜닝 가능.
- MagickProvider 정적 생성자: ResourceLimits.LimitMemory(60%) — 병렬 시 동시 MagickImage OOM 방지
  (초과분 디스크 스필, 출력 바이트 무영향).
- 신규 테스트: 8장 병렬 배치의 순서 보존(results[i]↔sources[i]) + 전수 변환 검증.

71개 테스트 전부 그린(골든마스터 동일성 유지), 빌드 0경고/0오류.
⚠ 진행률 UX(완료 건수 모델) 변경 — GUI 스모크 권장.
2026-06-02 09:43:20 +09:00
Yun Chan
379a4a738d refactor(P4): ConvertOptions God Object → 불변 record (init-only)
mutable sealed class(13 sub-record 가변)을 불변 record로 전환 — 배치 병렬 변환(P6)에서
공유해도 안전한 스레드 안전 전제 확보 + 값 의미론. 시그니처(ConvertAsync(ConvertOptions))는 비침습 유지.

- ConvertOptions + 13개 옵션 타입(Jpeg/Png/Webp/Avif/Tiff/Bmp/Gif/PdfRender/PdfBuild/HtmlRender/
  Ocr/PdfCompress/Ai) → sealed record, 전 프로퍼티 get;init;. 8개 Provider의 READ는 무영향.
- 변이 5곳을 with 식/객체 초기화로 교정(WRITE만 깨지므로 국소적):
  MainWindow.BuildOptions(한 식으로 불변 구성), App.RunQuickAsync(with), OcrProvider(PdfRender 초기화),
  특성화 테스트 2곳, ImageOptimProviderTests.
- 카테고리 분해(RoutingOptions/OutputOptions)는 reader 파급이 커서 후속으로 보류(비침습 우선).

70개 테스트 전부 그린(골든마스터 동일성 = 동작 불변), 빌드 0경고/0오류.
2026-06-02 09:40:07 +09:00
Yun Chan
12bda2dcbf refactor(P5a): App DI 컴포지션 루트 + MainWindow 생성자 주입 (서비스로케이터 제거)
MVVM(P5b)의 선행조건 — 엔진/설정을 생성자 주입으로 가시화하고 서비스로케이터 결합을 제거.

- App.xaml.cs: new DpapiSettingsStore()+CreateDefault() 직접 생성 → ServiceCollection.AddEverything2Everything()
  (P2 DI 재사용) 컴포지션 루트. Settings/Engine은 컨테이너 단일 싱글턴에서 해소(공유 보존).
  Generic Host 대신 ServiceProvider 사용 — Environment.Exit 진입점과 라이프사이클 충돌 회피(적대적 리뷰 반영).
- MainWindow: ((App)Application.Current).Engine/.Settings 서비스로케이터 8곳 → 생성자 주입 _engine/_settings.
  App.ShowMainWindow/ShowConvertDialog가 주입. 헤드리스 테스트 가능성 토대.

70개 테스트 전부 그린, 빌드 0경고/0오류.
2026-06-02 09:37:35 +09:00
Yun Chan
6ce4c429fe refactor(P6): 死코드 제거 + publish 전 테스트 게이트 (안전 부분)
GUI 위험 없는 P6 부분만 선반영(병렬화·ResourceLimits·ILogger·진행률 변경은 GUI 스모크 필요로 보류).

- HistoryStore.cs의 死코드 HistoryStore 클래스 제거(인메모리 ObservableCollection, 미인스턴스화).
  App은 정적 HistoryStorage + jsonl 영속화만 사용. HistoryEntry record는 보존(HistoryStorage/MainWindow 의존)
  → 파일명을 HistoryEntry.cs로 정합화(rename).
- packaging/BuildMsix.ps1: publish 직전 [0/5] dotnet test 게이트 추가 — 실패 시 패키징 중단.
  적대적 리뷰의 '최후 방어선'(회귀가 MSIX/서명까지 새는 것 차단). BuildAndSign 경유도 자동 커버.

70개 테스트 전부 그린, 빌드 0경고/0오류.
2026-06-01 23:45:16 +09:00
Yun Chan
dad1c0bca3 refactor(P3): combine을 IMultiInputConverter로 추출 — 엔진 ImageMagick 누수 봉합
ConversionEngine이 더 이상 ImageMagick에 의존하지 않는다(추상화 누수 확정 봉합).
결합(N→1)을 변환 그래프의 1입력 엣지로 표현 못 하던 한계를 1급 인터페이스로 분리(Branch by Abstraction).

- Core/Providers/IMultiInputConverter.cs 신규 — CanCombineTo + CombineAsync(N→1).
- MagickProvider가 IMultiInputConverter 구현 — 엔진의 CombineAsync/LoadImageForCombine/
  ApplyCombineEncoding 코드를 동작 그대로 이주(CombinableOutputs도 이관).
- ConversionEngine: using ImageMagick 제거(코드 참조 0건, grep 검증 — 주석만 잔존),
  CombineAsync는 _registry.All.OfType<IMultiInputConverter>()로 결합기를 찾아 위임하는 얇은 코드로 축소.
  출력 디렉터리 결정만 엔진이 수행, 파일명·인코딩·쓰기는 결합기가 담당.
- UI 무변경: 정적 CanCombine/CanCombineInput(순수 메타데이터, ImageMagick 무관)은 엔진에 그대로 유지.
- 신규 테스트: MagickProvider가 IMultiInputConverter로 발견되는 seam 잠금.

P1 combine 골든마스터(프레임수·NoCompression·치수·평균색 + PDF 헤더)가 추출 후에도 그린 = 동작 동일성 입증.
70개 테스트 전부 그린, 빌드 0경고/0오류.
2026-06-01 23:39:02 +09:00
Yun Chan
8419bf30ff refactor(P2): DI 컴포지션 루트 + Scrutor 어셈블리 스캔 자동등록
컴파일타임 하드코딩(Bootstrap 14개 new + 수동 생성자 와이어링)을 제거 — 새 Provider는 클래스만
추가하면 자동 등록되고 그래프가 변환 엣지를 자동 흡수(확장성 토대). Strangler Fig 파사드로 호출부 무변경.

- Core/ServiceCollectionExtensions.AddEverything2Everything: Scrutor FromAssembliesOf →
  AssignableTo<IConverterProvider> → AsSelfWithInterfaces(단일 싱글턴 공유) → Singleton.
  Heic(Magick)/Docx·Ocr·Hwpx(Pdf)/Llm(Settings) 생성자 의존 자동 해소. ProviderRegistry/Engine 등록.
- Bootstrap.CreateDefault: 내부를 DI(BuildServiceProvider→GetRequiredService)로 교체하되
  시그니처·동작 불변 — App/CLI/테스트 호출부 전부 무파손.
- 패키지: Microsoft.Extensions.DependencyInjection 9.0.0, Scrutor 4.2.2 (CPM 경유).
- DependencyInjectionTests: 14개 전수 해소 + 생성자 의존 자동 와이어링 + AsSelf 동일 인스턴스
  + 공유 Settings + 파사드 하위호환 검증(적대적 리뷰의 'AsSelf 누락 silent 실패' 방어).

App.xaml.cs Generic Host 전환·서비스로케이터 제거는 GUI 스모크가 필요해 P5(MVVM 생성자 주입)로 통합.
69개 테스트 전부 그린(65+4), 빌드 0경고/0오류, 골든마스터 녹색 유지(동작 불변).
2026-06-01 23:30:06 +09:00
Yun Chan
6b524662a4 refactor(P1): 엔진 실행경로 특성화(골든마스터) 안전망 구축
코드 변경 전 회귀 머지 게이트 확보 — 프로덕션 코드 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오류.
2026-06-01 23:20:53 +09:00
Yun Chan
f36ee299f4 refactor(P0): CPM 도입 + Magick.NET 14.13.1 통일
- 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개 테스트 전부 그린.
2026-06-01 23:02:16 +09:00
Yun Chan
47600d2eb5 fix: mp4 변환 멈춤 해결 — 8K HEVC 코덱 + 동일포맷 재인코딩 + 종료상태
증상: 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.
2026-06-01 22:25:12 +09:00
Yun Chan
acb3fdbfd1 feat: imagegen2 아이콘·글리프·일러스트 생성 후 GUI 전면 적용 (투명 배경)
codex noninteractive + imagegen2로 앱 비주얼 에셋 일괄 생성, 코드 생성 차단
(gen-one.sh: FORBID 블록 + 코드파일 감지 + 재시도). 모든 산출물은
플러드필 배경 제거로 진짜 알파 투명 PNG화.

생성 에셋 (assets-gen/):
- app-master: 앱 아이콘 마스터 (사이클 화살표, 솔리드 타일 유지)
- 카테고리 글리프 8종: image/video/audio/document/data/vector/archive/ai
- 일러스트 2종: illus-empty(드롭존), illus-done(완료)
- logo-mark: 브랜드 마크

GUI 적용:
- 사이드바 헤더 브랜드 → logo-mark
- 드롭존 빈 상태 → illus-empty
- QuickProgressWindow 완료 → illus-done
- AI 작업 패널 → glyph-ai 스파클
- 큐/과거결과 행 라벨 아이콘 → 카테고리 글리프 (CategoryGlyphs 매핑)
- 미리보기 placeholder → 형식별 카테고리 글리프 (경고 대신)

앱 아이콘:
- app.ico (멀티 크기 16~256) + 윈도우 Icon
- MSIX 타일 4종(Square44/150·Wide310·Store) app-master 기반 갱신
- Package 버전 1.0.2.0
2026-06-01 22:00:53 +09:00
Yun Chan
ef10c139cd fix: 빠른 변환 진행 표시(제목 동적+%) + 영상→이미지 프레임 추출 + GPU 가속
사용자 리포트: mp4 변환 시 %안나오고 멈춤, JPEG 고정 문구, GPU 가속 부재.

- QuickProgressWindow: 제목/타이틀바를 출력 형식으로 동적화('JPEG 고정' 해결), % 텍스트 + indeterminate 표시
- FfmpegProvider: 영상→이미지(jpg/png/webp/bmp) 대표 프레임 추출 직접 엣지 (mp4→jpg가 무거운 mp4→gif→jpg 멀티홉 거치던 문제 해결)
- GPU 가속: ConvertOptions.VideoPreferGpu(기본 on) — NVENC 시도 후 실패 시 CPU 자동 폴백, 설정창 토글로 제어
- 테스트 38개 통과
2026-06-01 21:28:55 +09:00
Yun Chan
573d04521d feat(shell): 입력 형식별 추천 출력 — 영상→영상/오디오, 데이터→데이터
셸 카스케이드 서브메뉴가 입력 형식과 무관하게 이미지 출력만 보이던 문제. EnumSubCommands에 전 카테고리 출력(이미지·영상·오디오·데이터·마크업)을 나열하고, 각 SubVerbCommand.GetState가 첫 파일 확장자를 보고 추천되지 않는 출력을 ECS_HIDDEN으로 숨김.

- CatOf/Recommend/FirstItemExt 헬퍼 추가
- 영상→mp4/webm/mkv/mov+mp3/m4a/flac/wav, 오디오→오디오, 데이터→json/csv/xlsx, 이미지/벡터/문서→이미지+pdf+OCR
- '변환…(옵션 선택)'은 항상 표시 (만능 경로)
2026-06-01 18:11:04 +09:00
Yun Chan
c9e890b091 feat(msix): 셸 컨텍스트 메뉴에 영상/오디오/데이터/벡터 확장자 등록
신규 변환 카테고리를 우클릭 1차 메뉴에 노출: 영상(mp4/webm/mkv/mov/avi), 오디오(mp3/aac/m4a/opus/ogg/flac/wav), 데이터(csv/json/xlsx), 벡터(svg), 마크다운(md/markdown), 텍스트(txt). 빠른변환 서브항목은 이미지용이고, 영상/데이터는 '변환…(옵션 선택)'으로 메인 창에서 멀티홉 출력 선택.
2026-06-01 17:20:11 +09:00
Yun Chan
529fbd593e fix(msix): MaxVersionTested 26100→26220 — 25H2 셸 익스텐션 컨텍스트 메뉴 등록 복구
Windows 11 25H2(빌드 26220)에서 MaxVersionTested가 OS보다 낮아 PackagedCom 셸 익스텐션(IExplorerCommand)이 게이트되어 1차 우클릭 메뉴에 등록되지 않던 문제. MaxVersionTested를 현재 OS로 올려 등록 복구 확인(ClassIndex 등록 검증됨).
2026-06-01 17:02:55 +09:00
Yun Chan
e30559b3cd feat(ui): 디자인 마무리 — AI 작업종류 옵션 + 큐 accent bar + 빈 상태 + polish
디자인 세션 마지막 단계(순차 workflow). Linear/Geist 영감 polish + AI 작업 선택 UI.

- AI 작업종류 ComboBox(요약/번역/교정) + 번역 대상언어 → BuildOptions의 opts.Ai.Task/TargetLanguage 연결. 이제 Codex로 번역·교정도 가능
- 큐 row 좌측 형식색 accent bar + hover, 빈 상태(Browse + 안내) 개선
- FormatShiftTheme: FsNumStyle/FsLossPillStyle/FsListRowStyle/FsIconButtonStyle 재사용 스타일
2026-06-01 16:03:50 +09:00
Yun Chan
5c7a4a9ee3 feat(ui): 출력 드롭다운에 형식 색 dot + 손실 등급 dot
변환 전에 '무엇으로 / 얼마나 보존되나'를 한눈에. 드롭다운 각 항목을 형식색 dot(8px) + 라벨 + 손실 등급 dot(6px, 큐 입력 기준 worst-case)로 렌더링.

- 형식색: FormatPalette.For 색 (csv 틸·json 골드·svg 핑크·영상 코랄·오디오 퍼플)
- 손실 dot: Lossless 초록 / Container 회색 / Recode 앰버 / Rasterize 빨강 (hover 툴팁)
- 손실 계산: ConversionGraph.FindBestPath worst Loss
2026-06-01 15:11:36 +09:00
Yun Chan
2a3d220db4 feat(ui): AI 설정창 + Codex CLI OAuth 백엔드 + ⚙ 진입점
사용자 원래 요구였던 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 상태 토큰 영감
2026-06-01 14:47:07 +09:00
Yun Chan
faffb8f205 feat(ui): 형식 색상 + 손실/상태 시맨틱 토큰 (Catppuccin/Material/Radix 영감)
디자인 리서치(VS Code Material Icon Theme·Seti UI·Linguist·Radix dark·Catppuccin·Linear·Geist) 기반으로 형식 색상과 시맨틱 토큰을 확장.

- 신규 형식색 FsFmtCsv/Xlsx/Json/Svg/Video/Audio (회색→카테고리별 hue) + AllFormats/FormatPalette 매핑
- 손실 등급 토큰 FsLoss*(Lossless=초록/Container=회색/Recode=앰버/Rasterize=빨강, Radix dark)
- 상태 토큰 FsStatus*(Success/Warn/Danger/Info × dot/text/bg)
- Geist식 8% 투명 보더 FsBorderHairline
2026-06-01 14:32:59 +09:00
Yun Chan
df07eb9bdd fix: UI 출력 형식 카탈로그 확장 + 멀티홉 노출 2홉 제한
구버전 앱에서 새 변환이 드롭다운에 안 보이던 문제 — AllFormats(UI 화이트리스트)에 데이터/벡터/영상/오디오 형식이 없었음. 추가.

- AllFormats에 csv/json/xlsx/svg + 영상(mp4/webm/mkv/mov/avi) + 오디오(mp3/aac/m4a/opus/ogg/flac/wav) 16종 추가
- OutputsForInput 노출 maxHops 3→2: html→png→gif→mp4 같은 카테고리 횡단 과도 노출 차단 (실제 변환 FindBestPath는 3홉 유지)
- 테스트 38개 통과
2026-06-01 14:04:22 +09:00
Yun Chan
47a4a961e2 feat: 멀티홉 변환 UI 자동 노출 (OutputsForInput → 그래프 reachability)
ProviderRegistry.OutputsForInput을 그래프 transitive closure로 전환. UI 코드 변경 0으로 멀티홉 변환(json→xlsx, svg→jpg 등)이 사이드바·카스케이드 메뉴에 자동 노출된다. 동일 포맷 self-edge는 제외.

- DirectOutputsForInput(1홉)도 별도 보존
- 카스케이드 메뉴는 PopularOutputs 교집합이라 폭발 없이 풍부해짐
- 테스트 1개 추가 (멀티홉 노출 검증) — 총 38개 통과
- SSOT P6 in_progress
2026-06-01 13:44:46 +09:00
Yun Chan
7235fc87f5 feat: 영상·오디오 Provider (FfmpegProvider) — FFmpeg 설치 시 활성화
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개 통과
2026-06-01 13:24:50 +09:00
Yun Chan
b76d51f3c1 feat: AI 텍스트 Provider (LlmProvider) — OpenAI/Anthropic 요약·번역·교정
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개 통과
2026-06-01 13:21:14 +09:00
Yun Chan
937d9e7878 feat: 외부도구 활성화 인프라 — ISettingsStore(DPAPI) + ExternalProcessRunner
AI 키·외부 도구 경로를 안전 저장하고 외부 CLI를 일원화 실행하는 토대. 둘 다 순수 .NET, 실동작 테스트 검증.

- DpapiSettingsStore: DPAPI(CurrentUser) 암호화로 %LOCALAPPDATA%에 저장, 평문 노출 없음 검증
- ExternalProcessRunner: stdout/stderr 수집 + 타임아웃 + 프로세스 트리 Kill (LibreOffice/FFmpeg/Ghostscript 공용)
- 테스트 6개 추가 (암호화 round-trip, echo/비정상종료/타임아웃) — 총 29개 통과
2026-06-01 13:16:56 +09:00
Yun Chan
d49ee6365f feat: 순수 .NET Provider 3종 (Data/Vector/ImageOptim) + Loss 분류 정확화
검증 가능한 순수 .NET 변환기를 우선 추가. 외부 도구 불필요, 실제 동작까지 테스트로 검증.

- DataProvider: csv<->json, csv<->xlsx 원자 엣지 (json<->xlsx는 그래프가 csv 경유 자동 합성). CsvHelper/ClosedXML
- VectorProvider: svg->png/pdf (svg->기타이미지는 png 경유 합성). Svg.Skia
- ImageOptimProvider: 동일포맷 재압축 self-edge (jpg/png/webp/tiff/bmp)
- Loss 분류 정확화: OCR·문서/HTML->이미지=Rasterize, ->pdf=Recode (멀티홉 이상경로 svg->pdf->docx->jpg 차단)
- 그래프 합성/실동작 테스트 9개 추가 (총 23개 통과)
- DocumentFormat.OpenXml 3.1.0->최신 (ClosedXML 호환)
2026-06-01 13:09:27 +09:00
Yun Chan
e3ef59e009 feat(P1): 변환 그래프 엔진 + 멀티홉 경로탐색 + PDF 압축
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
2026-06-01 12:48:58 +09:00
Yun Chan
232f453e15 docs: 변환 그래프 OS 마스터플랜 SSOT (멀티에이전트 분석+리서치 종합)
전체 소스 심층 분석(5) + 인터넷 리서치(7) → 3 독립 아키텍트 → 심사 랭킹 → 마스터플랜 종합을 Workflow로 오케스트레이션해 생성.

- docs/ssot/_data/*.json : SSOT 원천 데이터 (master/analyses/researches/designs/ranking)
- docs/ssot/build.py : JSON → index.html(웹 대시보드) + PLAN.md 제너레이터
- 9 ADR · 8단계 로드맵(P1 그래프엔진+PDF압축 → P8 굳히기)
- 양방향/다방향 그래프 라우팅, Codex OAuth+API, FFmpeg/Ghostscript 미디어 레이어
2026-06-01 11:38:36 +09:00
Yun Chan
25bebb46bf feat: 텍스트 문서 5종 양방향 변환 매트릭스 (DocumentProvider)
신규 DocumentProvider — html/htm/hwp/hwpx/docx/doc/md/markdown/txt 입력 →
html/docx/md/txt 출력 (HWP 출력은 H2Orestart 한계로 미지원).

라우팅 (멀티홉)
- {docx, html, txt, hwp} ↔ {docx, html, txt}: LibreOffice --convert-to
- md → html: Markdig (advanced extensions)
- html → md: ReverseMarkdown (GitHub flavored)
- md → docx/txt: md → html(Markdig) → LibreOffice 체인
- {docx, html, hwp} → md: → html(LibreOffice) → md(ReverseMarkdown) 체인
- md ↔ txt, html ↔ html 등: trivial copy
- txt → html: pre-wrapped HTML 인코딩

NuGet 추가
- Markdig 0.37.0
- ReverseMarkdown 4.6.0 (HtmlAgilityPack 의존성 자동 포함)

UI/메뉴 갱신
- AllFormats에 .html, .md 추가 (총 12종)
- PopularOutputs 카스케이드 12개로 확장:
  JPEG/PNG/WebP/PDF/Word/HTML/MD/TXT/AVIF/GIF/TIFF/BMP

요구 외부 도구: LibreOffice (DocxProvider/HwpxProvider와 공통)
MSIX 갱신: Markdig.dll + ReverseMarkdown.dll + HtmlAgilityPack.dll 포함
2026-05-07 17:22:15 +09:00
Yun Chan
50a195f9db chore: packaging 스크립트에 UTF-8 BOM + 카스케이드 라벨 갱신
- Windows PowerShell 5.1이 BOM 없는 UTF-8을 cp949로 읽어 한글 문자열이 깨지는 문제 수정 (5개 ps1 파일에 BOM 추가)
- BuildAndSign / Install 스크립트의 안내 메시지를
  'JPEG로 빠른 변환' → 'Everything2Everything으로 변환 카스케이드'로 갱신
- Install 스크립트에 Portable EXE 카스케이드 unregister 안내 추가
  (MSIX + 레지스트리 둘 다 등록 시 메뉴 중복 방지)
2026-05-07 17:13:30 +09:00
Yun Chan
198a39fd84 fix: Past Results 폴더 버튼이 출력 파일을 select하도록 변경
- HistoryEntry에 OutputPaths (nullable list) 추가, PrimaryOutputPath 헬퍼
- HistoryRow에 OutputPath + RevealPath (output 우선, fallback to source)
- AddToHistory 호출 시 result.OutputPaths.ToList() 전달
- XAML 폴더 버튼 Tag를 RevealPath로, ToolTip '출력 파일이 있는 폴더 열기'

이전 history.jsonl은 OutputPaths 없이 저장됨 — 새 변환부터 출력 select
2026-05-07 16:44:59 +09:00
Yun Chan
81d0a04eb0 feat: 진행 표시 보강 — 취소 버튼 + 큐 row inline progress bar
사이드바 진행 패널
- '취소' 버튼 추가 (FsSecondaryButtonStyle, ProcessingPercentLabel 우측)
- 클릭 시 _cts.Cancel() + 라벨/버튼 '취소 중…'으로 전환
- finally에서 버튼 상태 복원

큐 row inline progress
- QueueItem에 ProgressValue (0~100), ProgressVisibility 속성 추가
- SetState() 안에서 텍스트 파싱: 'queued'/'done'/'NN%' → 자동 갱신
- ItemTemplate에 Height=3 ProgressBar 추가 (MetaLine 아래)
- 변환 중인 row만 시각적 bar 표시
2026-05-07 16:40:38 +09:00
Yun Chan
ae897ea043 feat: 메인 창 사이드바에 변환 진행 표시 패널 추가
ProcessQueueButton 위에 ProcessingProgressPanel:
- 현재 변환 중인 파일명 (이름만, ellipsis 처리)
- N / Total 카운터
- 0~100% ProgressBar (Index + FileProgress 기준 누적)
- % 텍스트

ShowProcessingProgress(total) → 변환 시작 시 표시,
UpdateProcessingProgress(p) → reporter 콜백에서 실시간 갱신,
HideProcessingProgress() → finally에서 숨김
2026-05-07 16:37:54 +09:00
Yun Chan
2633a928c1 feat: 배치 결합 모드 + IExplorerCommand DLL 카스케이드
#10 다중 이미지 → 단일 PDF/TIFF/GIF 결합
- ConversionEngine: BatchMode { Independent, CombineToSingle } enum 추가
- ConvertManyAsync에 batchMode 파라미터, CombineToSingle 시 N:1 라우팅
- CombineAsync: MagickImageCollection으로 모든 입력 디코드 후
  단일 다중-페이지 파일로 출력 (PDF/TIFF/GIF만 지원)
- 결합 가능 검증: ImageMagick 디코드 가능 입력 + 결합 가능 출력
- 정적 헬퍼 CanCombine(outputExt), CanCombineInput(sourcePath)

UI
- MainWindow.xaml에 '단일 파일로 결합' CheckBox 추가
  (출력이 결합 가능 + 큐 ≥2 + 모든 입력 결합 가능일 때 활성화)
- 큐 변경/형식 변경 시 토글 상태 + 안내 텍스트 자동 갱신
- MainWindow.xaml.cs UpdateCombineState / OnCombineToggleChanged

#9 IExplorerCommand DLL 카스케이드 (MSIX 메인 메뉴)
- dllmain.cpp 전면 재작성:
  RootCascadeCommand (CLSID F1A2B3C4-...-2B3C4D5E6F70)
  + 11개 동적 SubVerbCommand
  + SubCommandEnumerator (IEnumExplorerCommand)
  + ECF_HASSUBCOMMANDS 플래그
- 서브메뉴 항목: JPEG/PNG/WebP/PDF/TXT/DOCX/AVIF/GIF/TIFF/BMP/변환…
- 기존 Quick/Dialog 핸들러는 backward compat용으로 유지
- 빌드: x64 Release Everything2Everything.Shell.dll (207KB)

Package.appxmanifest
- com:Class에 RootCascadeCommand CLSID 등록
- 모든 desktop5:ItemType verb를 Quick+Dialog 두 개에서 단일 Convert로 통합
  (29개 ItemType × 2 verbs → 29 × 1 verb)

quick CLI는 기본 .jpg 호환 유지, dialog는 메인 창에서 형식 선택

빌드: dotnet 0 errors, MSBuild C++ 0 errors
2026-05-07 15:46:38 +09:00
Yun Chan
9b7e5f0d0c feat: Everything2Everything 양방향 변환 매트릭스 피보팅
EverythingToJpeg(N→JPEG 단방향)에서 Everything2Everything(N×M 매트릭스)으로
앱을 피보팅. 7개 Provider, 200+ 변환 쌍 지원.

리네이밍
- 디렉토리/솔루션/csproj/namespace/AssemblyName/MSIX Identity 일괄 치환
- 임시파일 prefix e2j_ → e2e_, 로고 라벨 E2J → E2E

아키텍처
- ConversionPair(input, output) 신규 + ProviderCapability.SupportedConversions
- IConverterProvider.ConvertAsync에 outputExtension 파라미터 추가
- ProviderRegistry를 Dictionary<(input, output), Provider> 매트릭스로 재작성
  + OutputsForInput / OutputsForFile 쿼리 API
- ConversionEngine: 출력 ext 라우팅, 동일 입출력 자동 skip,
  서브폴더 suffix를 출력 ext에서 자동 도출
- ConvertOptions를 형식별 sub-record로 분리
  (Jpeg/Png/Webp/Avif/Tiff/Pdf*/Html*/Ocr)

Provider 매트릭스
- MagickProvider: PNG/JPEG/WebP/AVIF/BMP/TIFF/GIF/PDF 양방향 + RAW/PSD 디코딩
  (단일이미지→1페이지 PDF, GIF/TIFF→다페이지 PDF)
- HeicProvider: HEIC/HEIF → 이미지 7종
- PdfProvider: PDF → 이미지 6종 (PNG임베드 후 ImageMagick 인코딩)
- HtmlProvider: HTML/HTM → 이미지 + PDF (CDP printToPDF)
- DocxProvider/HwpxProvider: PDF + 이미지 7종 (LibreOffice 활용)
- OcrProvider 신규: 이미지/PDF → TXT/DOCX
  (Windows.Media.Ocr + DocumentFormat.OpenXml, PDF는 페이지별 OCR 후 결합)

UI
- 사이드바 TARGET FORMAT을 동적 ComboBox로 (큐 파일 매트릭스의 교집합만 표시)
- 출력 형식별 색상 배지 + Quality 패널 라벨 동적
- OUTPUT DESTINATION hint도 출력 ext 기반 동적

CLI
- 신규 'to <ext> <files...>' verb (예: to png photo.heic doc.docx)
- help 텍스트 양방향 컨셉으로 갱신

셸 통합
- ContextMenuRegistrar 카스케이드로 재설계
  (ExtendedSubCommandsKey + Everything2Everything.SubMenu.<ext>)
- 입력별 매트릭스에 따라 인기 출력 10종(JPEG/PNG/WebP/PDF/TXT/DOCX/AVIF/GIF/TIFF/BMP)
  동적 노출, 마지막에 '변환…' 옵션
- 메뉴 라벨 'JPEG로 변환' → 'Everything2Everything으로 변환'

기타
- Core.csproj TFM net9.0-windows → net9.0-windows10.0.19041.0 (WinRT API용)
- DocumentFormat.OpenXml 3.1.0 NuGet 추가
- README 양방향 매트릭스 기준 전면 개편
- MSIX appxmanifest Description / IExplorerCommand DLL 라벨 갱신

빌드: 0 errors, 0 warnings
2026-05-07 13:40:08 +09:00
Yun Chan
96861e627d chore: pivot 시작 — origin/master 코드 흡수 (Everything2Everything 베이스) 2026-05-07 03:03:50 +09:00
Yun Chan
0e752d76e2 ci: vcxproj를 packages.config 형식으로 복귀, BuildMsix가 nuget.exe 자동 처리
증상: VS 2022 Enterprise(GitHub windows-latest)에서 PackageReference 형식
vcxproj 빌드 시 ResolveNuGetPackageAssets가 "Sequence contains no elements"
오류로 실패. native vcxproj + PackageReference + msbuild restore 조합의
알려진 회귀.

해결:
- src/EverythingToJpeg.Shell/EverythingToJpeg.Shell.vcxproj: PackageReference
  제거, packages.config + Microsoft.Windows.ImplementationLibrary.targets
  imports 복귀, EnsureNuGetPackageBuildImports target 복귀.
- src/EverythingToJpeg.Shell/packages.config 재추가.
- packaging/BuildMsix.ps1: nuget.exe 없으면 dist.nuget.org에서 자동 다운로드,
  packages.config 기반 restore를 packages/ 폴더에 수행.
- .gitignore: packages/, tools/ 제외.

이러면 사용자 PC(VS 2026)와 CI(VS 2022) 모두 동일한 흐름으로 빌드.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 23:20:45 +09:00
Yun Chan
fc73b3c9a7 ci: PlatformToolset v145 → v143 (CI 호환)
GitHub Actions windows-latest runner는 VS 2022 Enterprise를 제공하므로
v145 (VS 2026 toolset) 빌드 도구가 없어 MSB8020 발생.
v143 toolset은 VS 2022 + VS 2026 모두 지원하므로 통일.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 23:16:15 +09:00
Yun Chan
d24cb90ed2 ci: build.yml + release.yml 보강 (서명 옵션 + workflow_dispatch)
- build.yml 추가: PR/push 시 솔루션 빌드 + MSIX 산출 검증, 14일 보관
- release.yml: PFX_BASE64 / PFX_PASSWORD secrets 있으면 자동 서명, 없으면
  unsigned. workflow_dispatch로 수동 트리거도 가능.
- 릴리즈 본문에 인증서 등록 + 사이드로드 가이드 inline 포함.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 23:13:03 +09:00
Yun Chan
784167ccff feat: P4-P8 한방 마무리 — 자체서명 MSIX, 영구저장, 단축키, capability 알림
P4 — 자체 서명 MSIX 자동화
- packaging/BuildAndSign.ps1: 인증서 생성→PFX export→MSIX 빌드→서명을
  한 스크립트로 일관 처리. 기존 인증서 있으면 재사용.
- Install-EverythingToJpeg.ps1: 기본 비밀번호 'EverythingToJpegDev' 자동
  사용 (사용자 5대 PC 본인 사용 한정).
- 검증: 53MB 서명된 MSIX 산출, signtool 정상 통과(DigiCert TimeStamp 박힘).

P6 — Past Results 영구 저장
- HistoryStorage.cs: %LocalAppData%\EverythingToJpeg\history.jsonl 에
  변환 결과 append. 시작 시 로드해서 _pastResults에 채움.
- 첫 실행에만 데모 시드, 이후엔 실데이터만 표시.
- Past Results의 Clear All은 영구 파일도 함께 삭제 (확인 다이얼로그 추가).

P7 — 정리 + 단축키
- 사용 안 하는 ConvertWindow.xaml/.cs 폐기 (코드 600줄 제거).
- KeyBinding 4개: Ctrl+O 파일 추가, Ctrl+Enter 변환, Esc 닫기, F5 새로고침.
- RelayCommand 헬퍼 클래스로 단축키 ICommand 패턴 구현.

P8 — Capability 자동 안내
- 시작 시 RequiresExternal Provider들의 가용성 비동기 체크.
- 외부 도구 미설치 형식이 있으면 사이드바 footer에
  "⚠ N개 형식이 외부 도구를 기다립니다 (Diagnose 참조)" 한 줄 표시.

README — Phase 1~8 전체 진척, 단축키 표 정리.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 19:36:55 +09:00
yunchan8804-blip
b2147a643f
Initial commit 2026-05-06 19:28:25 +09:00
Yun Chan
00d1eeff96 ux: 우클릭 → 메인 윈도우 통합 + Preview를 우측 컬럼으로 승격
우클릭 진입 통합
- App.OnStartup의 dialog 분기에서 ConvertWindow 대신 MainWindow를 띄우면서
  파일을 Active Queue에 자동 추가, 첫 항목 자동 Preview 로드.
- 사용자 시점에서 우클릭 → "JPEG로 변환…" 클릭 시 작은 다이얼로그가
  아니라 풀스크린 FormatShift 메인 화면이 그대로 노출.
- ConvertWindow 자체는 FormatShift 토큰으로 통일했지만 더 이상 호출되지
  않음 (코드는 향후 활용 위해 보존).

Preview를 탭 → 우측 메인 컬럼으로 승격
- 메인 영역 그리드를 1 column → 2 column 으로 분할: 좌측 *(min 360),
  우측 380px 고정 Preview 컬럼.
- 탭은 Active Queue / Past Results 두 개만 (Preview 탭과 무의미한 0 뱃지
  제거). Preview는 항상 보임.
- Active Queue 행 클릭 → 우측 Preview에 즉시 표시 (탭 전환 없음).
- Past Results 행도 클릭 가능: 실제 파일이면 미리보기, 데모/소실 파일이면
  안내 문구.
- Drop hint overlay는 ColumnSpan=2로 양쪽 컬럼 모두 덮음.

이벤트 처리 개선
- 행 Border에 PreviewMouseLeftButtonUp(tunnel) 사용 → 자식 컨트롤이 클릭을
  가로채는 이슈 해소.
- IsInsideButton 헬퍼로 Remove/Open 버튼이 발화시킨 클릭은 행 핸들러에서
  무시하여 의도 충돌 방지.

App.xaml 정리
- FormatShiftTheme.xaml 을 App-level resources에 머지 → 모든 윈도우에서
  Application.Current.FindResource("Fs*") 조회 가능 (이전엔 Window-level
  머지만 해서 ResourceReferenceKeyNotFoundException 발생).

LoadPreview 통합
- LoadPreviewByPathAsync(path, fileName, format, size) 단일 메서드로 통합.
- _selectedPreviewPath 로 Active/Past 두 케이스 모두 Open in Explorer 일관
  처리.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 19:26:27 +09:00
Yun Chan
01467a4d27 ux: FormatShift Utility 디자인을 메인 윈도우에 충실히 재현
새 메인 윈도우 (1280x960, dark minimal):
- 320px 사이드바 — Target Format(JPG), Encoding Quality 슬라이더(파란색 fill +
  흰 thumb), Output Destination, Skip/Rename/Replace 세그먼트, Stats Box,
  Processing Queue 버튼(disabled→enabled 상태 전이)
- 메인 영역 — pill 탭 3개(Active Queue / Preview / Past Results), 액션 버튼
  (Register Menu / Diagnose / Export Log / Clear All)
- Past Results — 날짜별 그룹화, "Today/Yesterday" 헤더 + Session Savings 뱃지,
  파일 아이콘(PDF/PNG/HEIC/JPG/...), 사이즈/savings/status 컬럼
- Active Queue — 빈 상태 드롭존 + 파일 행, 행 클릭 시 Preview 자동 전환
- Drop hint overlay — 파일 끌어올 때 흐릿한 가이드 표시

핵심 신규 인프라:
- FormatShiftTheme.xaml — 디자인 토큰(색/타이포/슬라이더 스타일/탭 pill 스타일/
  세그먼트 스타일/primary·secondary 버튼) 전부
- PreviewService — 이미지/RAW(Magick), HEIC(libheif decode), PDF(PDFium)을
  720px 긴변 BitmapSource로 렌더. DOCX/HWP/HTML은 안내 문구 fallback
- HistoryStore — 변환 결과 누적(메모리), 날짜별 group + session savings 합산
- Export Log — Past Results를 CSV/JSON으로 저장

기존 기능 통합:
- 사이드바 옵션이 ConvertOptions에 매핑 (Quality, Output Path, Conflict)
- Process Queue 버튼이 ConvertManyAsync 호출 → 결과를 History에 누적
- Register Menu / Diagnose 액션 유지

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:57:49 +09:00
Yun Chan
8065bf7373 fix: ConvertWindow ItemTemplate XamlReader 실패 + 진단/예외 핸들러
- ConvertWindow의 ItemTemplate을 코드비하인드 XamlReader.Parse 대신
  XAML 안에 <ItemsControl.ItemTemplate>으로 인라인 정의.
  XamlReader는 code-behind 메서드를 wire-up할 수 없어
  Click="OnRemoveEntry"가 매번 실패 → ConvertWindow 생성 시 예외 발생,
  GUI 상태가 깨져 변환 버튼 클릭이 처리되지 않던 근본 원인.
- OnConvertClick에 진단 로그(%TEMP%\EverythingToJpeg_dialog.log) 추가
- App에 전역 unhandled exception 핸들러 — DispatcherUnhandled,
  AppDomain.UnhandledException, TaskScheduler.UnobservedTaskException 모두
  %TEMP%\EverythingToJpeg_unhandled.log에 기록 + 메시지박스로 즉시 노출

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 16:47:41 +09:00
Yun Chan
e663921460 ux: ConvertWindow 좌우 → 상하 레이아웃 재설계
이전 좌우 분할은 IDE 패턴이라 변환 도구에 부자연스러웠음.
옵션 패널 320px 고정 때문에 창을 늘리면 좌측만 늘어나
"우측으로 늘어진" 인상을 줬다.

새 레이아웃 (위→아래):
1. 헤더(타이틀+파일 카운트) + 추가/비우기 버튼
2. 옵션 카드 (한 줄: 품질·출력 위치·이름 충돌)
   + 고급 옵션 expander (긴 변 픽셀·PDF DPI·투명 처리)
3. 파일 리스트 (메인, 세로 스크롤로 끝까지)
4. 하단 액션바 (진행률 + 닫기/변환 시작)

창 비율 940x700 → 640x780 으로 세로 우선.
파일이 많아질수록 자연스럽게 길게 늘어나는 패턴.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:50:48 +09:00
Yun Chan
69a6a1360d fix: 빠른 변환 후 프로세스 자동 종료 + 진단 로그
- ShutdownMode를 OnExplicitShutdown → OnLastWindowClose 로 변경
  변환 끝나도 WPF가 안 닫혀 좀비 프로세스로 남던 문제. 사용자 입장에선
  "결과가 안 보임"으로 인지됐음. 이제 GUI 닫히면 자동 종료(1초 내)
- RunQuickAsync에 %TEMP%\EverythingToJpeg_quick.log 진단 로그 추가
  (소스 경로, 결과 상태, 출력 경로, 예외 스택을 모두 기록)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:50:32 +09:00
Yun Chan
5750aed16f Phase 3: HTML(WebView2) + HWP/HWPX(LibreOffice) 실구현
HTML / HTM
- HtmlProvider: STA 스레드 + WPF Dispatcher에서 WebView2 헤드리스 컨트롤러(HWND_MESSAGE) 생성
- CDP Page.captureScreenshot(captureBeyondViewport=true)으로 풀페이지 PNG 획득
- Magick.NET으로 JPEG 인코드, 알파/리사이즈/품질 옵션 일관 적용
- ConvertOptions: HtmlViewportWidth/Height, HtmlWaitMilliseconds, HtmlFullPage

HWP / HWPX
- HwpxProvider: LibreOffice headless --convert-to pdf + H2Orestart 확장 자동 감지
- DocxProvider 패턴 재사용 (소스→PDF→PdfProvider 위임)
- ExternalToolDetector.IsH2OrestartInstalled — uno_packages/extensions 검색

기타
- Core csproj: UseWPF=true (WebView2가 WPF 의존), Microsoft.Web.WebView2 1.0.3912.50 추가
- AppX 매니페스트에 .html/.htm/.hwp/.hwpx ItemType 추가
- 파일 다이얼로그 필터 확장
- 두 ComingSoon 상태였던 Provider가 이제 Available/RequiresExternal로 노출됨

검증
- 솔루션 Release 빌드 통과
- MSIX 38개 페이로드 패키징 성공 (WebView2 SDK 포함)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 13:23:47 +09:00
Yun Chan
f2c8610ff6 Phase 2: MSIX 패키지 + IExplorerCommand 셸 익스텐션
C++ 셸 익스텐션 (src/EverythingToJpeg.Shell/)
- WRL RuntimeClass 패턴으로 IExplorerCommand 두 핸들러 구현
- Quick(빠른 변환) / Dialog(설정 창) verb를 다른 CLSID로 분리
- Invoke()에서 EverythingToJpeg.exe로 verb + 파일 경로 전달
- VS 2026 빌드 검증, /utf-8 한글 라벨 지원

MSIX 패키징 (packaging/)
- Package.appxmanifest: com:SurrogateServer + desktop4:FileExplorerContextMenus
- 26개 확장자 × 2 verb 자동 노출
- BuildMsix.ps1: dotnet publish + msbuild + makeappx 일관 파이프라인
- CreateDevCert.ps1 / Install-EverythingToJpeg.ps1: 자체 서명 인증서 워크플로
- GenerateAssets.ps1: placeholder 로고 자동 생성

CI/CD
- .github/workflows/release.yml: 태그 푸시 시 미서명 MSIX 자동 빌드 + 첨부

검증
- 50MB MSIX 산출 확인 (packaging/dist/EverythingToJpeg-x64.msix)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 13:03:16 +09:00
Yun Chan
8fa4a613d7 초기 커밋: Phase 1 — 레지스트리 기반 컨텍스트 메뉴 + 핵심 변환 파이프라인
- Provider 추상화(IConverterProvider + ProviderCapability) — Available/RequiresExternal/ComingSoon 1급 시민
- 변환 구현: Magick(이미지·RAW·GIF·TIFF), HEIC/HEIF(libheif decode→Magick encode), PDF(PDFium), DOCX(Word COM 또는 LibreOffice 자동 감지)
- ComingSoon 스텁: HTML, HWP/HWPX (UI 노출, 컨텍스트 메뉴 등록 자동 제외)
- WPF + WPF-UI 4.3 Fluent 2 UI: 메인 창(드래그&드롭, Provider 카드), 변환 창(썸네일·옵션·진행률), 빠른 변환 진행 창, 진단 창
- 단일 EXE에 verb 라우팅: quick / dialog / register / unregister / diagnose / help
- HKCU SystemFileAssociations 기반 컨텍스트 메뉴 등록 (Win11 "추가 옵션 표시"에 노출)
- README, packaging/ Phase 2 placeholder 포함

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 12:50:35 +09:00