ksj09406 9b5fdc6343 11차 지시서에 F 절(2026-09-18 추가 요청 열한 가지)
사용자가 한꺼번에 준 요청을 코드에 비춰 보고 F-1 ~ F-11 로 적었다(코드 변경 없음).
- F-1 칸 이름 맞추고 칸마다 어느 파일인지 · F-2 메서드 단위 반영 · F-3 폴더 두 개 보내기(설치 없이 되는지 포함)
- F-4 툴박스 감추기 · F-5 글자 크기 · F-6 넓게 보기 · F-7 모니터
- F-8 저장 뒤 되돌리기 · F-9 백업본 저장 · F-10 덩어리 잇기 UI · F-11 Git 계정 · 토큰 저장 확인
- 항목마다 지금 코드 상태(파일 · 줄)와 정할 것 · 판정 기준을 적음

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 13:39:57 +09:00

33 KiB
Raw Blame History

작업 지시 — MergeHub 11차 (변경분 추출을 믿고 들고 가게 · 베타 전에 깨지는 것 · 남은 기획 범위)

대상: D:\Sorce\MergeTool\MergeHub (플러그인) · D:\Sorce\MergeTool\UbisamPlatform (셸) 전제: 1~10차 지시서는 모두 끝났다(../진행상황.md).

이번 지시서가 나온 곳 — 10차 E-1 에서 다섯 길(병합 · pull · rebase · cherry-pick · revert)을 다시 끝까지 했고 새로 걸린 것은 없었다. 그래서 11차는 "고칠 버그" 가 아니라 기획안 v1.2 에서 아직 "일부" 인 것과 사내 베타(기획 4단계, 09.29 ~ 10.02) 전에 막아야 할 것에서 나왔다. 근거는 코드를 읽고 적은 것이다 — 실제로 해 보기 전의 짐작이므로 항목마다 먼저 다시 내고 시작한다.

어디서 무엇을 봤나 근거
변경분 추출 (기획안 "일부") 지운 파일은 개수만 알리고 목록이 어디에도 안 남는다(코드 주석은 "목록에만 남긴다") · 어느 범위를 뽑았는지 폴더에 안 남는다 · 이미 파일이 있는 폴더에 묻지 않고 덮어쓰고 옛 파일이 섞인다 · ZIP 없음 GitService.ExportChangedFiles · GitViewModel.ExportChangesAsync
배포 폴더 매뉴얼이 가리키는 bin\Release\net48 의 MergeHub.dll 이 09-07 14:11, 셸이 09-07 13:41 — 10일 동안 Debug 로만 빌드했다. 폴더 크기 96MB(LiveCharts · Skia · OpenTK 등 플랫폼 런타임 포함) 파일 시각 · README.txt
설정 · 로그 위치 플랫폼이 D:\UbisamConfig 를 고정으로 쓴다. D 드라이브가 없는 PC 에서 어떻게 되는지 모른다 UbisamAppBuilder.ConfigRoot · LogService · LockConfirmDialog
커밋 메시지 수정 (기획안 "일부") 마지막 커밋만 커밋 수정. 기획안은 "커밋 우클릭 → 이름 변경". 있는 [커밋 수정] 에도 걸리는 것이 보인다 — [마지막 메시지] 가 HEAD 가 아니라 이력 목록 맨 위 메시지를 가져옴([모든 브랜치] 면 다른 브랜치 커밋) · 스테이징해 둔 파일이 말없이 같이 들어감 · 원래 작성자 · 작성 시각을 지금 사람으로 바꿈(git 은 남김) · 병합 · rebase 중에도 켜짐 · 확인 창 · 되돌릴 옛 해시 없음 · 하네스에 amend 검사 0건 GitViewModel.AmendAsync · LoadLastMessage · GitService.Commit
10차 E-1 시험 도구 줄끝 검사 스크립트가 부모 하나인 커밋에서 오류를 찍음 · 요약 읽는 함수가 "차이 없음" 을 못 읽음 ../history/2026-09-17-10차.md E-1 "남긴 것"

공통 규칙

  • A → B → C → D → E → F 순서로 진행한다. A 는 사용자가 물어 본 것이라 먼저다. B 는 베타 날짜가 있어 C 보다 앞이다. F(2026-09-18 추가 요청)는 앞의 것을 끝낸 뒤 하나씩 올린다 — 급한 것이 있으면 사용자가 순서를 바꿔 말한다.
  • 항목 하나를 끝낼 때마다 빌드하고 실제로 실행해 화면을 확인한 뒤 보고한다.
  • 항목 하나가 끝나면 기록을 세 군데에 남기고 로컬 커밋한다(4차 D-2 규칙).
    1. 상세는 doc/history/YYYY-MM-DD-11차.md — 원인 · 판단 · 확인한 결과
    2. ../진행상황.md 은 대기 → 완료로 상태만
    3. ../history/changelog.md 에 한 줄 — 날짜 · 무엇을 왜 · 커밋
  • 푸쉬하지 않는다.
  • 실제 소스를 열지 않는다(2026-09-11 결정). 시험 재료는 C1Repo(병합 저장소) · FolderPerf/Corpus.cs(폴더 묶음) · 직접 만든 파일로 만든다. 고치기 전에 문제가 다시 나는 것부터 보이고, 고친 뒤 안 나는 것을 보인다. 다시 나지 않으면 짐작으로 고치지 않고 되풀이한 횟수와 짚은 곳을 적어 보고한다.
  • 기존 검사 하네스(22벌 1,147건)는 계속 통과해야 한다. 로직을 건드리면 테스트를 먼저 늘린다.
  • 빌드 경고 0 · 오류 0 을 유지한다. 앱이 실행 중이면 UbisamBase.Shell 을 먼저 종료한다.
  • 사용자 설정 파일(D:\UbisamConfig\Settings\MergeHubSettings.json)은 시험 전에 백업하고, 끝나면 바이트 그대로 되돌린다. 창 기억(ShellWindowPlacement.json)은 시험 뒤 "기억 없음" 으로 둔다.
  • 자동 조작으로 확인할 때는 사람이 갈 수 있는 길만 쓴다. 이름 창은 [저장], 접힌 영역은 [펴기], 이력 줄은 마우스로(10차 B-1 은 누르기 전에 묻는 길).
  • 문서 글을 PowerShell 로 넣을 때는 작은따옴표 문자열만 쓴다(8차). PowerShell 변수 이름은 대소문자를 가리지 않는다 — 매개변수와 겹치는 이름을 쓰지 않는다(9차 A-2).
  • 앱 안에 임시 측정 코드를 넣었다면 커밋하지 않고 잰 뒤 되돌리고 다시 빌드한다(9차 B-2).
  • 레지스트리 HKLM · 셸 확장 · 보안(백신) 설정은 건드리지 않는다. 시스템 설정을 바꿔야만 재볼 수 있는 것은 재지 않고 적는다.
  • 플랫폼을 고치면 다른 소비 프로그램에 미치는 영향을 함께 적고 UbisamPlatform/doc/history/changelog.md 에 남긴다. 배포는 사용자 확인 뒤.

A. 변경분 추출을 믿고 들고 가게

기획안: "장비에 소스를 통째로 넣지 못하는 현장에서 바뀐 파일만 들고 간다." 들고 간 폴더만 보고 무엇이 바뀌고 무엇을 지워야 하는지 알 수 있어야 쓸 수 있다.

A-1. 먼저 뽑아 보고 적는다 (고치지 않음)

  • C1Repo 로 저장소를 새로 만들고 Git 탭 → 이력에서 사람 순서로 뽑는다. 경우마다 뽑은 폴더를 git diff --name-status · git show <커밋>:<경로> 바이트와 견준다.
# 경우 볼 것
1 커밋 하나(시작점 없음) 뽑은 파일 수 = git diff --name-status 부모 커밋 의 A · M 수, 바이트 같음
2 [여기부터] 로 범위 범위 안 중간 커밋에서만 바뀌고 되돌려진 파일이 들어가는지
3 지운 파일이 있는 범위 알림 "삭제되어 건너뜀 N개" 뒤 어느 파일인지 알 길이 있는지
4 이름 바뀐 파일 새 경로로 뽑히는지 · 옛 경로를 알 길이 있는지
5 병합 커밋 하나 첫 부모와만 견주는지(상대 브랜치에서 들어온 파일이 모두 나오는지)
6 시작점이 고른 커밋보다 뒤 무엇이 뽑히는지 · 경고가 있는지
7 이진 파일 · 한글 경로 · 깊은 폴더 바이트 · 경로 그대로인지
8 이미 파일이 있는 폴더에 다시 뽑기 덮어쓰기 · 옛 파일이 남아 섞이는지 · 묻는지
9 뽑는 중 대상 파일이 읽기 전용 · 열려 있음 오류 문구 · 반쯤 뽑힌 채 남는지
  • 판정 기준: 9가지 경우의 결과를 값(파일 수 · 해시 · 알림 문구)으로 표에 적는다. 걸린 것은 A-2 ~ A-4 에 붙이거나 새로 적는다.

A-2. 뽑은 폴더에 "무엇을 뽑았는지" 를 남긴다 — 먼저 정한다

  • A-1 의 3 · 4 · 6 결과를 보인 뒤 사용자에게 형식을 정한다.
    1. 뽑은 폴더 안에 안내 파일 하나(예: _변경분.txt) — 범위(커밋 해시 · 제목 · 날짜) · 뽑은 사람 · 뽑은 파일 목록(추가 / 수정 / 이름 바뀜 옛 경로) · 지워야 할 파일 목록
    2. 폴더 밖(옆)에 같은 내용 — 장비에 폴더째 넣을 때 안내 파일이 섞이지 않게
    3. 파일은 만들지 않고 화면(Git 탭 로그 · 결과 창)에만
  • 결과 내보내기(3차)와 보고서의 머리글(만든 사람 · 만든 때, 4차 A-2)과 같은 꼴을 쓴다.
  • 판정 기준: 정한 대로 뽑은 결과만 보고 지워야 할 파일 · 이름 바뀐 옛 경로 · 범위를 알 수 있다. A-1 의 1 · 2 · 7 바이트 결과가 고치기 전과 같다. 하네스로 "지운 파일 · 이름 바뀜 · 병합 커밋" 목록을 만든다.

A-3. 이미 파일이 있는 폴더에 뽑을 때 — 먼저 정한다

  • A-1 의 8 결과를 보인 뒤 정한다.
    1. 비어 있지 않으면 묻는다(덮어쓰기 · 취소)
    2. 고른 폴더 아래에 새 폴더를 만든다(예: 변경분_ace42e3..f310f49_2026-09-17)
    3. 그대로 둔다(한계로 매뉴얼에 적음)
  • 판정 기준: 정한 대로 옛 파일과 새 파일이 말없이 섞이지 않는다. [취소] 뒤 파일이 하나도 바뀌지 않았다.

A-4. ZIP 으로 뽑기 — 할지 먼저 정한다

  • 폴더로만 뽑는다(기획안 "폴더·ZIP"). 필요한지 사용자에게 묻는다. 한다면 A-2 안내 파일이 ZIP 안에 들어가고, 풀었을 때 바이트 · 경로가 폴더로 뽑은 것과 같아야 한다.
  • 판정 기준: 안 하기로 하면 기획안 · 웹 문서에 "폴더로만" 을 까닭과 함께 적는다. 하면 폴더 결과와 ZIP 을 푼 결과의 해시 목록이 같다.

B. 사내 베타 전에 깨지는 것

기획 4단계(09.29 ~ 10.02) 에 다른 사람 PC 에서 처음 켠다. 지금까지는 이 PC · 이 경로 · 이 설정에서만 켰다.

B-1. 배포 폴더가 10일 전 것이다 — 다시 만들고 무엇이 들어가야 하는지 정한다

  • 매뉴얼("개발 PC 에서는 src\MergeHub\bin\Release\net48\UbisamBase.Shell.exe")이 가리키는 Release 출력의 MergeHub.dll 이 2026-09-07 이다. 먼저 지금 Release 로 켜면 무엇이 다른지(예: 6차 이후 기능이 없는지)를 한 번 확인해 적는다.
  • Release 로 다시 빌드하고, 배포 묶음에 꼭 필요한 파일을 가린다: 셸 · 플러그인 · LibGit2Sharp 네이티브(lib\win32 · win-x64) · CommunityToolkit · 설정 기본값 · Lang. LiveCharts · Skia · OpenTK 가 MergeHub 에 필요한지는 지워 보고 켜서 가린다(플랫폼이 쓰는지 같이 본다).
  • 빈 폴더(예: %TEMP%\mergehub-beta)에 묶음만 복사해 켜고, 다섯 탭 · 병합 한 길(C1Repo)을 끝까지 한다.
  • 판정 기준: 배포 묶음 목록(파일 · 크기 · 왜 필요한지)과 총 크기를 적는다. 빈 폴더에서 켜 병합 커밋까지 된다. 매뉴얼의 실행 위치 문장이 사실과 같다. 플랫폼 배포 폴더를 바꿔야 하면 사용자 확인 뒤.

B-2. D 드라이브가 없는 PC · 설정 파일이 없는 첫 실행

  • 플랫폼이 설정 · 로그 · 화면 잠금 기록을 D:\UbisamConfig 에 고정으로 쓴다. D 드라이브를 없애는 시험은 하지 않는다(디스크 설정). 대신 코드로 "D:\ 가 없을 때 어느 줄에서 무엇이 되는지" 를 따라가 적고, 설정 파일 · 폴더가 없는 첫 실행은 백업 뒤 폴더 이름을 잠시 바꿔 재 본다(끝나면 바이트 그대로 되돌림).
  • 첫 실행에서 볼 것: 이름 창 · 기본 설정 값 · 창 위치 · 로그 폴더 생성 · 오류 창 여부.
  • 방향: D 드라이브가 없을 때 켜지지 않는다면 플랫폼 문제다. 고치는 길(예: 없으면 사용자 폴더로)을 다른 소비 프로그램 영향과 함께 사용자에게 보이고 정한다.
  • 판정 기준: 첫 실행이 오류 창 없이 켜지고 기본값이 매뉴얼 설정 표와 같다. D 드라이브 없는 경우의 결과를 코드 근거로 적었다(고쳤다면 플랫폼 changelog).

C. 커밋 메시지 수정 — 기획 범위에서 "일부" 로 남은 것

기획안 1차 범위 "커밋 메시지 수정 — 커밋 우클릭 → 이름 변경. 명령어와 옵션을 외울 필요 없음". 기획안 v1.2 · 웹 문서에는 "마지막 커밋만 커밋 수정" 으로 일부라고 적었다. 그런데 코드를 다시 읽으니 있는 [커밋 수정] 도 믿고 쓰기 어려운 곳이 있다. 새 기능(C-2)을 정하기 전에 있는 길부터 바로잡는다.

지금 모양 (Git 탭 → 변경 · 커밋, 아래 줄 커밋 메시지 [칸] [마지막 메시지] [커밋] [커밋 수정]):

  • [커밋 수정] = GitService.Commit(message, amend: true) → LibGit2Sharp Repo.Commit(message, 지금 사람, 지금 사람, AmendPreviousCommit). 켜지는 조건은 저장소가 열려 있고 메시지 칸이 비어 있지 않음 뿐이다.
  • [마지막 메시지] = _workspace.Commits[0].Message — 이력 목록의 맨 위 커밋 메시지.
  • 이력 탭에서 고른 커밋과는 상관없이 늘 HEAD 를 고친다. 우클릭 메뉴는 없다.
  • 하네스(GitOpTest 등)에 amend 를 재는 검사가 없다.

C-1. 있는 [커밋 수정] 을 다시 내 보고 바로잡는다 (원인부터)

  • C1Repo 로 저장소를 새로 만들어 사람 순서로 한다. 경우마다 고치기 전 결과를 git log -1 --format="%H %an %ae %ad %cn %s" · git show --stat · git status 로 적는다.
# 짚이는 것 다시 내는 순서 git 은 어떻게 하나
1 [마지막 메시지] 가 다른 커밋 메시지를 가져온다 이력 [모든 브랜치] 켬(9차 A-2: 맨 위가 다른 브랜치 커밋) → 변경 · 커밋 [마지막 메시지] → 칸의 글이 HEAD 메시지인지 → 그대로 [커밋 수정] 하면 HEAD 가 다른 커밋의 메시지로 바뀌는지 git commit --amend 는 HEAD 메시지를 편집기에 띄운다
2 스테이징해 둔 파일이 같이 들어간다 파일 하나 고쳐 [스테이징] → 메시지만 고칠 생각으로 [마지막 메시지] → [커밋 수정] → 그 파일이 HEAD 에 들어갔는지 · 알림에 그런 말이 있는지 같이 들어간다(--only 없이). 다만 편집기 화면에 바뀔 파일 목록이 보인다
3 원래 작성자 · 작성 시각이 바뀐다 8차 C-2 처럼 작성자 박지훈 인 커밋을 cherry-pick 해 HEAD 로 만든 뒤 [커밋 수정] → %an · %ad 작성자 · 작성 시각은 그대로, 커밋한 사람 · 시각만 바뀐다(--reset-author 를 줄 때만 바뀜)
4 작업 중에도 켜진다 병합 충돌 중 · rebase 중 · cherry-pick / revert 중에 메시지 칸에 글을 넣고 [커밋 수정] 이 켜지는지 · 누르면 무엇이 되는지(부모 수 · MERGE_HEAD · rebase-merge 가 남는지) 병합 중에는 막는다("You are in the middle of a merge -- cannot amend") · rebase 중에는 멈춘 커밋을 고치는 뜻이 된다 · cherry-pick / revert 중은 재어 적는다
5 병합 커밋을 고치면 병합 커밋이 HEAD 일 때 [커밋 수정] → 부모 둘이 남는지 · 8차 F-1 본문(충돌 해결 내역)이 사라지는지 부모는 그대로
6 이미 올린 커밋 pull 길(10차 E-1)의 원격을 흉내 낸 bare 저장소로 push 한 뒤 [커밋 수정] → 막거나 알리는지 · 그 뒤 Push 가 어떻게 되는지 막지 않는다. 다음 push 가 거부된다
7 되돌리는 길 수정 뒤 알림 · 로그에 고치기 전 해시가 남는지 reflog 에 남는다
8 메시지 칸 · 첫 줄 여러 줄 메시지 · 빈 줄 · # 로 시작하는 줄이 그대로 들어가는지(6차 B-3 은 병합 메시지의 # 줄을 뺐다) 편집기를 거치면 # 줄이 빠진다
  • 원인이 확인된 것만 고친다. 고칠 방향(사용자에게 보이고 정할 것은 정함 으로 표시):
    • 1 — [마지막 메시지] 는 HEAD 커밋의 메시지를 읽는다(목록 순서와 무관).
    • 2 — 정함: [커밋 수정] 을 누를 때 스테이징된 파일이 있으면 "파일 N개도 이 커밋에 들어갑니다" 를 묻는다 / 메시지만 고치는 길을 따로 둔다 / 그대로 두고 매뉴얼에 적는다.
    • 3 — 작성자 · 작성 시각은 원래 커밋 것을 쓴다(git 과 같게). 커밋한 사람만 지금 사람.
    • 4 — merge · rebase · cherry-pick · revert 진행 중에는 [커밋 수정] 을 끈다(단추 설명에 까닭).
    • 5 — 병합 커밋 본문이 사라진다면 [마지막 메시지] 가 본문까지 가져오는지 보고 적는다.
    • 6 — 정함: 원격 추적 브랜치에 이미 있는 커밋이면 묻는다 / 막는다 / 매뉴얼에만 적는다.
    • 7 — 알림 · 로그에 "커밋 수정 완료 (옛 abc1234 → 새 def5678)".
  • 판정 기준: 여덟 가지 모두 고치기 전 · 뒤 결과를 값으로 적는다. 고친 것은 하네스에 먼저 넣는다 — HEAD 메시지 읽기([모든 브랜치] 목록에서도) · 작성자 · 작성 시각 보존 · 작업 중 꺼짐 · 병합 커밋 부모 둘 유지. 파일 비교 탭에 저장 안 한 편집이 있을 때 먼저 묻는 것(5차 A-2)이 그대로다.

C-2. 마지막 커밋이 아닌 커밋의 메시지 수정 — 할지 먼저 정한다

  • C-1 을 끝낸 뒤 정한다. 기획안은 "커밋 우클릭 → 이름 변경" 이고, 이력 탭에서 고른 커밋의 메시지를 바꾸는 일이다.
  • HEAD 가 아니면 그 뒤 커밋을 모두 다시 쓴다(해시가 모두 바뀜 · git rebase -i 의 reword). 사용자에게 보일 것:
    • 되는 범위: 현재 브랜치의 조상 커밋 · 원격에 없는 커밋 · 그 사이에 병합 커밋이 없을 때
    • 막을 것: 원격에 올라간 커밋 · 사이에 병합 커밋 · 작업 중(merge · rebase · cherry-pick · revert) · 워킹트리에 커밋 안 한 변경 · 파일 비교 탭에 저장 안 한 편집 · 다른 브랜치에만 있는 커밋([모든 브랜치])
    • 지켜야 할 것: 다시 쓴 커밋들의 트리 · 작성자 · 작성 시각 그대로, 메시지는 고른 커밋만
    • 되돌리는 길: 바꾸기 전 HEAD 해시를 알림 · 로그에 남긴다
    • 화면: 이력 줄 우클릭 메뉴 또는 이력 탭 단추 — 10차 B-1 대로 두 탭이 같은 커밋을 보는지
  • 판정 기준: 안 하기로 하면 기획안 · 웹 문서에 "마지막 커밋만" 을 까닭과 함께 적고 닫는다. 하면 하네스로 "세 커밋 앞 커밋 메시지 바꾸기 → 그 뒤 커밋 수 같음 · 커밋마다 트리 해시 · 작성자 · 작성 시각 같음 · 고른 커밋 메시지만 바뀜" 을 보이고, 막을 경우 여섯 가지가 실제로 막힌다. 바꾼 뒤 두 탭의 고른 커밋이 새 해시를 따라간다(9차 A-1 · A-2 규칙).

D. 시험 도구 정리 (제품 아님)

D-1. 10차 E-1 에서 남긴 둘

  • 줄끝 검사 스크립트(d1-verify.ps1)가 부모 하나인 커밋(rebase · cherry-pick · revert)에서 둘째 부모가 없어 git merge-base 오류를 찍는다 — 부모 하나면 첫 부모와만 견준다고 적고 오류 없이.
  • 파일 비교 탭 요약을 읽는 함수(FileState)가 "차이 없음" 을 못 읽어 커밋 뒤 요약이 빈칸으로 적힌다.
  • 판정 기준: 10차 E-1 의 rebase 한 길을 다시 돌려 오류 줄 0 · 커밋 뒤 요약 "차이 없음" 이 적힌다. 제품 코드는 바꾸지 않는다.

E. 확인 · 문서

E-1. 바꾼 길을 다시 끝까지

  • F 에서 화면 · 저장을 건드렸으면 그 길도 함께 본다. A 를 고쳤으면 A-1 의 9가지를 다시 돌려 표를 채운다. C-1 을 고쳤으면 C-1 의 여덟 가지를 다시, C-2 를 했으면 메시지를 바꿔 이력을 다시 쓴 저장소로 병합 한 길을 끝까지.
  • 제품의 병합 · 저장 코드를 건드렸다면 10차 E-1 처럼 다섯 길(+ pull) 을 다시 한다. 안 건드렸다면 병합 한 길만(회귀).
  • 판정 기준: 줄끝 · BOM 바뀐 파일 0 · 충돌 표식 0 · class 이름 다른 Unit 파일 0 · 누른 수 = 줄 고른 로그. 10차 B-1(두 탭 같은 커밋)이 다시 나지 않는다.

E-2. 웹 문서 · 기획안을 11차에 맞게

  • MergeHub 문서(doc/web/index.html, 아티팩트 "MergeHub 문서"): 매뉴얼 변경분 추출 · 실행 위치(B-1) · 설정 위치(B-2) · F 에서 바뀐 화면(칸 이름 · 감추기 · 글자 크기 · 백업 저장 · 보내기) · 알아 둘 한계 · 남은 일 · 지금까지 만든 것. 발행본을 먼저 읽고 합쳐 올린다.
  • 기획안 v1.2(잠금 아티팩트 "UbiSam MergeTool 개발 기획안"): 3.2 기능 목록의 변경분 추출 · 커밋 메시지 수정 상태, 4단계 진행. 원문은 로컬에서 고치고 A4 쪽마다 원본과 같은 높이인지 그림으로 견준다. 잠금은 사용자가 비밀번호로 한다 — 잠그지 않은 파일은 올리지 않는다(공유 링크가 열린 사내 문서).
  • 판정 기준: 문서의 단추 이름 · 흐름이 지금 화면과 같다(grep 대조). 태그 짝 맞음. 기획안 새 잠금 파일을 풀면 고친 원문과 바이트가 같다.

F. 추가 요청 (2026-09-18, 사용자)

열한 가지를 한꺼번에 받았다. 다 하는 것이 아니라 하나씩 올린다 — F-1 · F-2 · F-3 은 화면과 저장에 바로 닿고, F-4 ~ F-7 은 보이는 양을 늘리는 한 묶음, F-8 ~ F-11 은 저장 · 확인이다. 아래 "지금은" 은 코드를 읽고 적은 것이다(2026-09-18). 항목마다 화면에서 먼저 다시 보이고 시작한다.

F-1. LOCAL · REMOTE · MERGED 이름을 맞추고, 그 칸이 어느 파일인지 보이게

  • 지금은: 칸 이름이 BaseTitle => "BASE" · LocalTitle => IsThreeWay ? "MERGED" : "LOCAL"(HomeViewModel.cs:2393)뿐이고, "한글 풀이를 붙이지 않는다" 는 판단이 바로 위 주석(:2389)에 적혀 있다. 파일 경로는 맨 위 한 줄에 한 번만 나온다(4차 C-1 에서 세 곳 → 한 곳으로 줄였다). BASE 칸에만 (merge base) 경로, REMOTE 칸에는 브랜치 · 커밋이 붙는다.
  • 그래서 git mergetool 로 열었을 때처럼 네 칸이 서로 다른 파일(임시 --base · --local · --remote · --merged)을 볼 때 어느 칸이 어느 파일인지 화면에 없다.
  • 방향: 칸 머리마다 한 줄로 무엇 · 어느 파일 · 어느 커밋/브랜치. 예) MERGED · Weld/Unit1.cs (저장할 파일) · REMOTE(Theirs) · feature/theirs · Weld/Unit1.cs. 긴 경로는 가운데를 줄이고 전체는 마우스를 올리면 보이게. 로그 · 보고서 · 매뉴얼에서 쓰는 말도 같은 말로 맞춘다.
  • 정할 것: 이름을 표준 용어 그대로 둘지(LOCAL(Mine)), 한글 풀이를 함께 붙일지(LOCAL(내 쪽)). 4차 · 6차에 "표준 용어 그대로" 로 정한 적이 있어 뒤집는 결정이다.
  • 판정 기준: 두 칸 · 네 칸 · git mergetool · --merge 네 길에서 칸마다 파일 이름이 보이고, 그 파일이 실제로 읽은 · 저장할 파일과 같다(8차 A-1 의 "화면에 실린 파일" 과 같은 값). 좁은 폭에서도 줄이 늘어나지 않는다.

F-2. 메서드 단위로 골라 반영 (지금은 줄 · 덩어리 · 전체)

  • 지금은: 반영 단위가 줄([>]) · 이어진 차이 덩어리(이 덩어리 반영) · 전체뿐이다. 덩어리를 반영하면 머지 주석은 덩어리 첫 줄 위에 한 줄 붙는다.
  • 요청: 메서드를 통째로 고르고, 머지 주석은 메서드 이름 위에 한 줄만.
  • 방향: Roslyn 없이 CodeTokenizer 로 중괄호 짝과 시작 줄을 찾아 메서드 범위를 잡는다. 문자열 · 주석 · 전처리기(#if) 안의 중괄호에 속지 않아야 한다. 캐럿이 놓인 메서드를 잡아 [이 메서드 반영]. 범위를 잡지 못하면 단추를 끄고 까닭을 알린다(틀린 범위를 반영하는 것보다 낫다).
  • 정할 것: C# 만 먼저 할지(XAML · C/C++ 은 뒤로), 속성 · 로컬 함수 · 생성자도 "메서드" 로 볼지.
  • 판정 기준: 시험 파일에서 메서드 20개(한 줄 메서드 · 중첩 중괄호 · 문자열 안 중괄호 · #if 로 갈린 메서드 · 주석 안 중괄호 포함)의 범위를 정확히 잡는다(하네스). 반영한 뒤 저장 결과가 줄 단위로 같은 범위를 반영한 것과 바이트가 같다. 머지 주석은 메서드 이름 위 한 줄.

F-3. 탐색기에서 폴더 두 개를 골라 [보내기] 로 바로 비교

  • 지금은: 보내기 등록은 %APPDATA%\Microsoft\Windows\SendTo 에 바로가기 하나를 두는 것이 전부다(ShellIntegration.cs:18, 관리자 권한 · 레지스트리 없음). 명령줄 쪽은 폴더 두 개를 받으면 폴더 비교로 연다(StartupArgs.cs:118~122). 그런데 탐색기가 여러 개를 고른 보내기를 어떻게 넘기는지(한 번에 인자 둘 / 프로세스를 두 번)는 재 보지 않았다.
  • 확인할 것: 파일 2개 · 폴더 2개 · 폴더 1개 · 3개 이상 · 경로에 공백 · 한글 · 아주 긴 경로. 프로세스가 두 번 뜨면 하나로 모으는 길(이미 떠 있는 창으로 보내기)을 정한다.
  • 설치 파일 없이 되는지도 여기서 답한다 — 지금 구조(바로가기 하나 · HKCU/HKLM 안 씀)면 설치 관리자가 필요 없다. 다만 배포 묶음을 옮기면 바로가기 경로가 어긋나므로 [탐색기 보내기 등록] 을 다시 눌러야 하는지, 켤 때 저절로 고칠지 정한다(B-1 배포 묶음과 함께).
  • 판정 기준: 폴더 두 개를 골라 보내기 → 창 하나에 왼쪽 · 오른쪽 폴더가 들어가 비교까지 간다. 위 일곱 경우의 결과를 값으로 적는다. 레지스트리를 쓰지 않는다.

F-4. 파일 비교 탭의 툴박스(ACTIONS)를 감추는 단추

  • 지금은: ACTIONS 칸은 접어도 폭이 그대로다(4차 C-5 결정, HomeView.xaml:864). 접기는 "한 번 정하는 것"(저장 형식 · 비교 규칙)에만 걸려 있다.
  • 방향: 칸 전체를 감춰 코드 폭을 넓히는 단추(또는 F9 같은 키). 감춘 상태를 설정에 기억. 감춘 채로도 저장 · 반영 키는 살아 있어야 한다.
  • 판정 기준: 감추면 코드 칸 폭이 그만큼 늘고, 다시 펴면 원래대로. 앱을 껐다 켜도 상태가 남는다. 감춘 상태에서 Ctrl+S · Alt+←/→ 가 그대로 듣는다.

F-5. 글자 크기 조절

  • 지금은: 코드 칸은 Consolas 12 로 XAML 에 박혀 있고(HomeView.xaml:163 등), 설정에 글자 크기 항목이 없다.
  • 방향: 설정 값 하나 + Ctrl + 휠 · Ctrl + +/- 로. 코드 칸 · 줄 번호 · 미니맵이 같이 커지고 줄 높이도 따라야 한다.
  • 판정 기준: 8pt ~ 24pt 에서 줄 번호 · 여백 단추 · 미니맵 자리가 어긋나지 않는다. 바꾼 크기가 앱을 껐다 켜도 남는다. 네 칸에서 세 칸의 줄 높이가 서로 맞는다.

F-6. 글자를 되도록 많이 보이게

  • 지금은: 6차에서 셸 상 · 하단 띠를 줄여 코드가 3줄 더 보이게 했다. 그 뒤로는 더 재지 않았다.
  • 방향: 한 단추(또는 키)로 넓게 보기 — 색 구분 범례 줄 접기 · ACTIONS 감추기(F-4) · 위 줄 한 줄로 · 줄 간격 좁히기.
  • 판정 기준: 1920 × 1080 에서 지금 몇 줄이 보이는지 재고, 넓게 보기로 몇 줄이 늘었는지 값으로 적는다(예: 34줄 → 44줄). 글자 크기(F-5)와 섞어 써도 깨지지 않는다.

F-7. 어느 모니터에서든 제대로 뜨게

  • 지금은: 창 자리 기억은 플랫폼이 한다(ShellWindow.xaml.cs:475 PreparePlacement · 모니터 작업 영역과 배율로 최소 크기를 다시 계산). 8차 C-3 에서 첫 Win+↓ 와 확인 창 가운데 맞춤을 고쳤다.
  • 먼저 증상부터 적는다 — 어느 모니터에서 무엇이 잘못되는지(창이 화면 밖 · 너무 작음 · 글자만 크게 · 두 번째 모니터에서 안 뜸 · 배율 150% 에서 잘림). 재현되지 않으면 고치지 않는다.
  • 플랫폼을 고치면 다른 소비 프로그램에 영향이 있다 — 영향과 함께 사용자 확인 뒤 배포.
  • 판정 기준: 증상과 조건(모니터 수 · 해상도 · 배율 · 주 모니터 위치)을 적는다. 고쳤다면 같은 조건에서 창이 보이는 자리에 뜨고, 기억한 자리가 사라진 모니터면 주 모니터로 온다.

F-8. 저장한 뒤에도 되돌리기가 되게

  • 지금은: 저장하는 네 길이 모두 되돌리기 스택을 비운다 — SaveResolvedAsync:977 · SaveAndCommitAsync:896 · SavePlainAsync:2686 · SaveWorkingCopy:2836. 저장한 글이 새 기준(_originalLocalText)이 되기 때문이다.
  • 방향: 스택을 비우는 대신 저장 지점을 표시한다. 그 아래로 되돌리면 다시 "저장할 것 있음" 이 되고, 다시 저장 지점으로 오면 없어진다.
  • 정할 것: 병합 중 [Save] 까지 되돌릴지. 이 저장은 git 인덱스에 "해결" 로 등록하므로, 되돌리면 인덱스를 어떻게 할지 함께 정해야 한다(되돌리면 다시 충돌로 / 화면만 되돌리고 인덱스는 그대로 · 알림).
  • 판정 기준: 저장 → Undo → 화면이 저장 전으로, 상태가 "저장할 것 있음". Redo 로 다시 저장 후로. [전체 되돌리기] 의 기준이 정한 대로 움직인다. 하네스로 "저장 표시가 있는 스택" 을 먼저 만든다.

F-9. 백업본으로 저장 — 원본을 건드릴지 고르게

  • 지금은: 저장은 늘 원본 파일을 덮어쓴다. .bak 도, 다른 이름으로 저장도 없다.
  • 방향: [저장] 옆에 [다른 이름으로 저장], 또는 설정 "저장할 때 원본을 파일명.bak 으로 남기기". 남긴 백업의 이름 규칙(날짜 · 번호)과 지우는 시점을 정한다.
  • 정할 것: 병합 중 · Git 저장소에서도 같게 할지. 병합 중 [Save] 는 git 인덱스에 등록하는 일이라 "원본을 건드리지 않음" 과 어울리지 않는다 — Git 아닐 때만 둘지 정한다.
  • 판정 기준: 켠 채로 저장하면 원본과 백업이 둘 다 남고, 백업은 저장 전 바이트 그대로(해시 대조). 끄면 지금과 같다. 폴더 비교 · 변경분 추출이 백업 파일을 결과에 섞지 않는다.

F-10. 덩어리(블록)가 어디로 갔는지 UI 로 잇기

  • 지금은: 자리만 옮긴 덩어리를 찾아 "자리 옮김" 색으로 칠한다(MoveDetector). 하지만 어디에서 어디로 갔는지는 색만으로 알기 어렵다. 줄 위치가 많이 벌어지거나 순서가 바뀌면 두 칸을 눈으로 따라가야 한다.
  • 방향: 두 칸 사이에 잇는 선(또는 같은 번호표)을 그려 짝을 보이게. 미니맵에도 같은 표시. 고른 덩어리의 짝으로 한 번에 건너뛰는 단추.
  • 판정 기준: 메서드 세 개의 순서를 바꾼 시험 파일에서 세 짝이 모두 선으로 이어지고, 잇는 선이 잘못 짝지은 것 0. 스크롤 · 접기 · 글자 크기(F-5)를 바꿔도 선이 제자리. 차이 수 · 저장 내용은 그대로.

F-11. Git 계정 · URL · 암호가 한 번 쓰면 저장되는지 확인

  • 지금은: 서버 주소와 계정은 설정 파일에 저장된다(MergeHubSettings.cs:40 GiteaUrl · :44 GiteaUserName). 암호 · 토큰은 저장되지 않는다 — 화면의 PasswordBox 에서 받아 메모리(GitWorkspace.Password:154)에만 두고, Fetch · Pull · Push 직전에 붙인다(ApplyCredentials:519). 그래서 앱을 껐다 켜면 토큰을 다시 넣어야 한다.
  • 먼저 화면으로 확인해 적는다: 껐다 켠 뒤 주소 · 계정이 남는지, 암호 칸이 비는지, 그 상태로 Fetch 를 누르면 무엇이라 하는지.
  • 정할 것: 토큰을 저장할지. 저장한다면 평문은 안 된다 — 윈도 자격 증명 관리자(DPAPI) 에 사용자 계정으로 묶어 넣는다. 저장하지 않기로 하면 매뉴얼에 그렇게 적는다.
  • 판정 기준: 확인한 결과를 적는다. 저장하기로 하면 설정 파일 어디에도 토큰 글자가 없고(파일 grep 0), 껐다 켜도 Push 가 다시 묻지 않는다. 지우는 단추가 있다.

이번 지시서에서 하지 않는 것

  • 실제 소스로 해 보기 — 실제 소스는 열지 않는다(2026-09-11 결정).
  • 느린 디스크(HDD)에서 폴더 비교 재기 — 이 PC 에는 NVMe 뿐이다. 사내 베타 때 그 PC 에서 잰다(10차 D-1).
  • 사내 베타 배포 자체 · 푸시 — 사내 Gitea 저장소와 대상 PC 가 정해지면 따로 지시한다. B 는 배포 전 확인까지.
  • D 드라이브를 없애거나 디스크 · 백신 · 레지스트리(HKLM) 설정을 바꿔 보는 시험 — 보안 · 시스템 설정이라 하지 않는다.
  • 빈 cherry-pick 을 커밋으로 남기는 길 — 두지 않기로 했다(2026-09-16 사용자 결정).
  • 비교할 때만 C# 스타일을 맞추는 선택지 — 만들지 않기로 했다(2026-09-17 사용자 결정).
  • MergeHub 밖에서 푼 충돌을 병합 본문에 적기 — 알 길이 없다(8차 F-1).
  • 셸 창 반쪽 스냅 · 1px 테두리 — 8차 C-3 결정 그대로.
  • 로그인·권한 · Gitea PR 코멘트 · 멀티 레포 · Roslyn · 같은 줄 접기(4차 B-2) · 외부 편집기(4차 B-4) · 창 여러 개 — 미룬 그대로 둔다.

보고 형식

항목마다 이렇게 적는다.

  • 고치기 전에 문제가 다시 나는 것을 어떻게 보였는지 (만든 저장소 · 묶음의 어느 파일로, 몇 번 되풀이해서)
  • 무엇이 원인이었는지 한두 줄 (코드 · 로그 근거)
  • 사용자에게 정해 달라고 한 것과 정한 것
  • 어떤 파일을 어떻게 고쳤는지
  • 실제로 실행해 확인한 결과 (파일 수 · 해시 · 크기 · 알림 문구 · ms 처럼 눈이 아닌 값으로)
  • 커밋 해시