UI/UX 정비: 슬래시 탐색 보강·모델 빠른설정 단일화·권한 포커스 안정화 및 체크리스트 문서화
Some checks failed
Release Gate / gate (push) Has been cancelled

- ChatWindow: 슬래시 팝업 스크롤 입력 개선(ScrollViewer 휠 연결, PageUp/PageDown/Home/End 지원, 고해상도 휠 델타 단계 이동)
- ChatWindow: 모델 버튼 클릭 시 AX Agent 내부 빠른 설정 패널 토글로 전환하여 단일 라인 흐름 강화
- ChatWindow: 권한 팝업 오픈 시 재귀 포커스 탐색으로 첫 조작 요소에 안정적으로 진입
- ChatWindow.xaml: 모델/프리셋 버튼 높이·패딩 조정으로 컴포저 상단 밀도 정돈
- 문서: README/DEVELOPMENT 이력 업데이트(2026-04-04 12:11 KST)
- 문서: docs/UI_UX_CHECKLIST.md 신규 추가(내부/사외 모드 포함 UI 회귀 시나리오)
This commit is contained in:
2026-04-04 12:13:24 +09:00
parent c56a841549
commit 57b204649e
5 changed files with 2092 additions and 1005 deletions

View File

@@ -222,7 +222,7 @@ public class MyHandler : IActionHandler
### v0.7.3 — AX Agent 권한 코어 재구성 + 입력 계층 정리
업데이트: 2026-04-04 10:05 (KST)
업데이트: 2026-04-04 12:11 (KST)
| 분류 | 내용 |
|------|------|
@@ -230,6 +230,40 @@ public class MyHandler : IActionHandler
| 규칙 해석 순서 정리 | 권한 판정을 `deny 규칙 → allow/override 규칙 → 글로벌 모드 → 기본 Ask` 순서로 재구성 |
| 도구 권한 클래스 분리 | `file_write/file_edit/file_manage``process/build_run/test_loop/snippet_runner/spawn_agent` 계열을 분리해 `AcceptEdits``Plan`의 실제 동작 차이를 반영 |
| AX Agent 권한 UI 반영 | 권한 팝업, 상단 배너, slash 명령 결과가 새 권한 모드 의미를 표시하도록 정리 |
| AX Agent 설정창 복구 | `AgentSettingsWindow`의 깨진 한글 문자열을 정리하고 운영 모드, 계획 모드, 추론 강도, 폴더 데이터 활용 라벨을 현재 AX 표현 체계로 복구 |
| 권한 용어 통일 | 권한 팝업과 인라인 설정에서 `계획 중심`, `완전 자동`, `질문 없이 진행` 등 한국어 표기를 일관되게 사용하도록 정리 |
| 권한 UI·로직 결합 정리 | `claw-code` 권한 팝업 흐름에 맞춰 코어 4개(`권한 요청/편집 자동 승인/계획 모드/권한 건너뛰기`)를 기본 선택 순서로 정렬하고, 토글 순환도 동일 축으로 단순화 |
| 슬래시 팔레트 단순화 | `/` 팝업의 기본 선택을 첫 항목으로 바꾸고, 즐겨찾기 버튼/배지 UI를 제거해 `아이콘+명령+설명` 중심의 단순 리스트 탐색으로 정리 |
| 컴포저 패널 축소 | 하단 인라인 설정을 `Fast/추론/계획/권한` 중심으로 축소하고, 스킬/브라우저/MCP 버튼은 숨겨 입력 중심 UX로 정리 |
| 모델/프리셋 바 컴팩트화 | 입력창 상단 바를 더 촘촘한 크기로 정리하고, 긴 모델명은 자동 말줄임 처리해 레이아웃이 흔들리지 않도록 보강 |
| 좌측 패널 타이포 정돈 | 사이드바 헤더/메뉴/대화 리스트의 폰트 크기와 여백을 줄여 밀도를 맞추고, 대화 카드 제목·시간·상태 배지의 크기를 통일해 시인성을 개선 |
| 메시지 버블 정돈 | 사용자/어시스턴트 버블의 여백·폰트·타임스탬프·액션 버튼 크기를 줄이고 좌우 마진을 대칭화해 대화 로그 가독성과 정렬감을 개선 |
| 에이전트 이벤트 표시방식 정리 | 실행 배너의 과도한 펼침 UI를 제거하고 요약 길이를 제한해 한눈에 상태를 읽도록 단순화, 권한/계획/실행 라벨을 한국어 기준으로 통일 |
| 도구 결과 카드 단순화 | 파일 경로 배너를 `파일명 + 디렉터리` 2단 구조로 정리하고, 빠른 작업 버튼을 아이콘 전용(프리뷰/열기/폴더/복사)으로 축소해 시각적 복잡도를 낮춤 |
| 작업 요약 팝업 정돈 | 팝업 헤더/필터 밀도를 낮추고 `전체·권한·대기·도구·서브·훅` 중심으로 재정렬해 스크롤 시 탐색 피로를 줄임 |
| 권한 이력 카드 재구성 | 권한 카드/이력을 `현재 모드·설명·기본/예외` + `시간·도구·결과` 구조로 단순화하고, 권한 액션 버튼도 최신 용어(`활용하지 않음/권한 요청/편집 자동 승인/계획 모드/권한 건너뛰기`)로 통일 |
| 최근 실행 카드 압축 | `최근 에이전트 실행` 카드에서 상세 로그/파일 나열과 분기 액션을 줄이고 `요약+카운트+타임라인` 중심으로 정리해 표시 밀도와 스캔 속도를 개선 |
| 작업 카드 버튼 스타일 통일 | 작업 요약/권한/훅/백그라운드 카드 버튼을 공통 생성 함수로 통일해 패딩·폰트·테두리·색상 톤을 일관화하고 카드 간 버튼 밀도 차이를 제거 |
| 카드 타이포 계층 정렬 | 작업/훅/백그라운드 카드의 제목·본문 글자 크기와 굵기를 통일하고 `PrimaryText/SecondaryText` 기반으로 대비를 맞춰 카드 간 시각 리듬을 정리 |
| 카드 아이콘 규칙 통일 | 작업 종류별 아이콘/색을 공통 매핑으로 통일하고, 작업·훅·백그라운드 카드 헤더에 아이콘을 배치해 상태 인지가 한눈에 되도록 정리 |
| 권한 팝업 선택 강조 개선 | 권한 모드 리스트에서 활성 항목에 배경/테두리/체크 아이콘을 적용하고 설명 줄간격·아이콘 정렬을 조정해 선택 상태와 읽기 흐름을 명확화 |
| 권한 예외/거부 영역 압축 | 권한 팝업의 `도구별 예외``최근 권한 거부` 블록을 아이콘 헤더+간결 라벨 체계로 정리하고 버튼 명칭을 권한 용어(`권한 요청/편집 자동 승인/활용하지 않음/예외 해제`)로 통일 |
| 권한 팝업 섹션 접힘/펼침 | 기본 화면은 `핵심 권한 모드`만 노출하고 `현재 권한 요약/도구별 예외/최근 권한 거부/고급 모드`는 접힘 섹션으로 전환해 codex/claude식 간결 흐름으로 정리 |
| 권한 팝업 섹션 상태 기억 | 접힘 섹션의 마지막 펼침 상태를 `settings.dat`에 저장해 팝업 재오픈 시 사용자 마지막 선택을 복원 |
| 슬래시 팔레트 그룹 상태 기억 | `/` 팔레트에 `명령/스킬` 접힘 헤더를 추가하고 마지막 펼침 상태를 저장해 재오픈 시 복원, Up/Down 이동도 펼쳐진 그룹 항목만 순회하도록 보정 |
| 슬래시 최근 사용 상단 고정 | `/` 팔레트의 `명령/스킬` 그룹 내부 항목을 최근 사용(MRU) 기준으로 상단 정렬하고 `최근` 배지를 표시, 선택 스크롤도 실제 렌더 항목 기준으로 정확히 보정 |
| 슬래시 핀 고정 결합 | `/` 팔레트 항목 우측에 핀 토글을 추가하고 정렬 우선순위를 `핀 > 최근 > 이름`으로 적용해 자주 쓰는 명령을 고정 유지 |
| AX Agent 기본 활성화 | `ai_enabled` 기본값을 활성화로 변경하고 설정 로드 정규화 단계에서 비활성 값이 들어와도 자동으로 활성화되도록 보정 |
| 업데이트 안내 메시지 제거 | 앱 시작 시 설정 마이그레이션 후 표시되던 `설정 업데이트` 메시지박스를 제거해 업데이트 설치 직후 팝업 노출을 중단 |
| 슬래시 핀/최근 개수 설정 연동 | AX Agent 설정창에서 `슬래시 핀 최대 개수`, `슬래시 최근 최대 개수`를 조절할 수 있도록 추가하고 런타임(MRU/핀 정렬) 제한에 즉시 반영 |
| 슬래시 개수 설정 QA 완료 | 핀/최근 상한 적용 후 `/` 팔레트 정렬과 실행 경로를 회귀 점검하고 `ChatWindowSlashPolicyTests` 39개를 통과하여 동작 안정성을 확인 |
| 슬래시 퀵관리/권한 키보드 보강 | `/` 팔레트 헤더에 `정리/전체 접기·펼치기`를 추가하고, 권한 팝업에 `Tab/Enter/Esc` 중심 키보드 조작(항목 선택·섹션 토글·닫기)을 보강 |
| 슬래시/권한 접근성 완성도 보강 | `/` 팔레트에 `모두 접힘` 안내와 섹션 상태 라벨을 추가하고, 권한 팝업 오픈 시 첫 포커스 이동/Enter·Space 선택/ESC 닫기를 보강해 키보드 사용성을 개선 |
| 설정 즉시 반영 가시성 보강 | AX Agent 설정의 슬래시 핀/최근 상한 항목에 `저장 후 즉시 반영` 안내를 추가해 조작 결과를 명확히 인지하도록 정리 |
| 회귀 패키지 통과 | 전체 테스트 436개 통과로 슬래시/권한/설정 저장 경로 변경 후 회귀 안정성 확보 |
| 슬래시 탐색 입력 확장 | `/` 팝업에서 휠/방향키 외에 `PageUp/PageDown/Home/End` 이동을 추가하고 고해상도 휠 델타를 단계 이동으로 보정해 스크롤 사용성을 개선 |
| 모델 빠른설정 단일 라인 강화 | 입력창 상단 모델 버튼을 AX Agent 내부 빠른 설정 토글로 전환하고, 모델/프리셋 버튼 높이와 패딩을 정돈해 Codex/Claude형 단일 라인 흐름에 맞춤 |
| UI 점검 체크리스트 추가 | 내부/사외 모드 포함 UI 회귀 점검 문서를 `docs/UI_UX_CHECKLIST.md`로 추가해 시나리오 기반 검증 기준을 명문화 |
| Slash palette 상태 분리 시작 | `ChatWindow`에 몰려 있던 slash 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편 기반 마련 |
| 런처 이미지 미리보기 추가 | `#` 클립보드 이미지 항목에서 `Shift+Enter`로 전용 미리보기 창을 열고, 줌·원본 해상도 확인·PNG/JPEG/BMP 저장·클립보드 복사를 지원 |
| 검증 | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed |
@@ -241,3 +275,9 @@ public class MyHandler : IActionHandler
## 라이선스
MIT License

View File

@@ -1992,7 +1992,7 @@ allowed-tools: process file_read grep_tool
### v0.7.3
> **개발 범위**: AX Agent 권한 코어 재구성 + slash 입력 계층 분리 + 설정/상태 표현 정리
업데이트: 2026-04-04 10:05 (KST)
업데이트: 2026-04-04 10:49 (KST)
| 구분 | 내용 |
|------|------|
@@ -2000,6 +2000,16 @@ allowed-tools: process file_read grep_tool
| **권한 판정 체인 재구성** | 권한 해석 순서를 `deny 패턴 규칙 → allow/override 규칙 → 글로벌 모드 → 기본 Ask` 순서로 재정리하여 `claude-code` 수준의 정책 해석 흐름에 맞춤 |
| **도구 권한 클래스 분리** | `file_write/file_edit/file_manage``process/build_run/test_loop/snippet_runner/spawn_agent`를 별도 권한 클래스로 분리해 `AcceptEdits`는 파일 편집 자동 허용, `Plan`은 쓰기 차단으로 동작하도록 보강 |
| **AX Agent 권한 UI 반영** | 권한 팝업, 상단 배너, slash 명령 응답, 상태 요약에 새 권한 명칭과 설명을 반영하고, 도구별 override 요약이 현재 모드와 함께 보이도록 정리 |
| **AX Agent 설정창 문자열 복구** | `AgentSettingsWindow`를 전면 정리해 깨진 한글 문자열을 복구하고, 운영 모드/계획 모드/추론 강도/폴더 데이터 활용을 현재 AX 용어로 표시하도록 수정 |
| **권한 용어 및 상태 표현 통일** | `Plan`, `Bypass`, `DontAsk`처럼 영문으로 남아 있던 권한 표현을 `계획 중심`, `완전 자동`, `질문 없이 진행`으로 정리하고 인라인 설정 패널 문구도 함께 통일 |
| **권한 UI·실행 로직 결합 정리** | 권한 팝업을 `권한 요청/편집 자동 승인/계획 모드/권한 건너뛰기` 중심 리스트로 재구성하고, `BtnPermissionMode` 및 인라인 `NextPermission` 순환 로직도 같은 4단계 축으로 단순화 |
| **슬래시 팔레트 UI 정리** | `/` 입력 시 첫 항목을 기본 선택하도록 조정하고, 항목 우측 즐겨찾기 버튼/유형 배지를 제거해 `아이콘+명령+설명` 중심의 단순 리스트 탐색 구조로 정리 |
| **하단 컴포저 패널 단순화** | 인라인 설정 빠른 버튼을 `Fast/추론/계획/권한` 중심으로 줄이고 부가 버튼(스킬/명령 브라우저/MCP)을 숨겨 입력 흐름을 방해하지 않도록 정리 |
| **모델/프리셋 상단 바 컴팩트화** | 입력창 상단 모델/프리셋 버튼의 높이와 패딩을 줄이고, 모델명이 길 때 자동 말줄임(`…`) 처리해 입력창 폭이 좁아도 상단 바가 깨지지 않도록 보강 |
| **좌측 사이드바 밀도 정리** | 사이드바 헤더/검색/메뉴/대화 리스트의 간격과 글자 크기를 재조정하고, 대화 카드의 제목/시간/상태 배지 크기를 낮춰 `claw-code`형 컴팩트 밀도에 맞춤 |
| **메시지 버블 레이아웃 정리** | 사용자/어시스턴트 버블의 패딩·폰트·타임스탬프 크기와 좌우 마진을 조정해 대화 영역을 더 촘촘하게 정리하고, 액션 버튼 크기도 줄여 시각적 잡음을 완화 |
| **에이전트 이벤트 배너 표시방식 정리** | 실행 이벤트 배너의 카드 밀도(패딩/마진/폰트)를 줄이고, ToolCall/ToolResult 긴 요약은 자동 절단해 펼침 토글 없이 읽히도록 정리. 권한/계획/결정 배지 라벨도 한국어로 통일 |
| **도구 결과 카드 시각 단순화** | 파일 경로 배너를 파일명 중심 2단 표기(파일명/디렉터리)로 바꾸고, 빠른 작업 버튼을 텍스트 라벨 대신 아이콘 전용으로 축소해 이벤트 카드 본문 가독성을 개선 |
| **Slash palette 상태 분리 시작** | `ChatWindow` 내부에 퍼져 있던 slash 선택 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편의 기반을 마련 |
| **설정/상태 연동** | `AppSettings`, `AppStateService`, `AgentSettingsWindow`, `ChatWindow`가 동일 권한 체계를 참조하도록 정리하고 대화별 권한 상태 저장 흐름을 유지 |
| **런처 이미지 미리보기 창 (Phase L2-3)** | `ClipboardImagePreviewWindow` 신규 추가. 원본 해상도 이미지 표시, `Ctrl+휠`/`+`/`-`/`0`/`F`/`Esc` 단축키, PNG·JPEG·BMP 저장, 클립보드 복사, `#` 이미지 항목 `Shift+Enter` 연결, 단축키 도움말 갱신 |
@@ -2811,6 +2821,361 @@ else:
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj` 통과 (421 passed, 0 failed).
## 2026-04-04 추가 진행 기록 (연속 실행 5차: 작업 요약 팝업 표시 정렬)
업데이트: 2026-04-04 10:55 (KST)
### 1) 작업 요약 팝업 밀도/표시 방식 정리
- 팝업 타이틀을 `작업 요약`으로 정리하고 보조 설명(`현재 실행/권한/작업 흐름`)을 추가.
- 필터 칩을 `전체·권한·대기·도구·서브·훅` 중심으로 재배치하고, 칩 패딩/폰트/마진을 축소해 스크롤 피로를 완화.
- 팝업 루트 배경을 테마 리소스(`LauncherBackground`) 기반으로 정리하고, 본문 텍스트는 `PrimaryText/SecondaryText`를 우선 사용하도록 정돈.
### 2) 권한 카드/이력 구조 단순화
- 권한 요약 카드를 `현재 권한·설명·기본 모드·예외 개수` 구조로 단순화.
- 모드별 시각 팔레트 함수를 도입해 `활용하지 않음/권한 요청/편집 자동 승인/계획 모드/권한 건너뛰기` 상태를 일관 색상으로 표시.
- 최근 권한 이력을 기존 단일 문장 포맷에서 `시간·도구·결과·요약` 포맷으로 재구성.
### 3) 권한 액션 라벨 최신 체계 반영
- Task Summary의 권한 액션 버튼을 아래 순서로 통일:
- `활용하지 않음`
- `권한 요청`
- `편집 자동 승인`
- `계획 모드`
- `권한 건너뛰기`
- `해제`
### 4) 불필요 실패 중심 액션 축소
- 작업 요약 팝업 하단 액션에서 `실패 대화만 보기` 버튼을 제거하고, 재시도/진행중 필터 중심으로 단순화.
### 5) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 6차: 최근 실행 카드 압축)
업데이트: 2026-04-04 11:00 (KST)
### 1) 최근 에이전트 실행 카드 표시 간소화
- 최근 실행 표시 개수를 4개에서 3개로 축소.
- 카드 본문 요약을 길이 제한(말줄임) 기반으로 정리해 긴 설명이 레이아웃을 깨지 않도록 조정.
- `관련 실행 로그/관련 파일` 상세 목록 나열을 제거하고 `실행 로그 n · 관련 파일 n` 한 줄 요약으로 압축.
### 2) 실행 카드 액션 정리
- 실행 상세 이동은 `타임라인 보기` 단일 액션으로 통일.
- 완료 상태 카드에서 `새 분기에서 이어가기`를 제거하고 `후속 작업 큐에 넣기` 중심으로 단순화.
### 3) 시각 밀도 정리
- 카드 패딩/간격을 축소해 동일 영역에서 더 빠르게 스캔 가능하도록 조정.
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 7차: 작업 카드 버튼 스타일 통일)
업데이트: 2026-04-04 11:03 (KST)
### 1) 공통 버튼 빌더 도입
- `ChatWindow.xaml.cs`에 `CreateTaskSummaryActionButton(...)` 추가.
- 작업 요약 팝업 내 액션 버튼 공통 속성을 일원화:
- `FontSize 10.5`, `MinHeight 28`, `Padding 9x4`, `BorderThickness 1`
- 일관된 마진 규칙(기본 trailing 6px)
### 2) 적용 범위
- `BuildTaskSummaryActionRow` (queue/permission)
- `BuildHookSummaryCard`
- `BuildActiveBackgroundSummaryCard`
- `BuildRecentBackgroundJobCard`
- `ShowTaskSummaryPopup`의 최근 실행/재시도/진행중 필터 버튼
### 3) 효과
- 카드 영역마다 버튼 크기/두께/간격이 달라 보이던 문제를 해소.
- 색상 체계는 유지하면서 시각적 밀도와 클릭 영역 일관성을 확보.
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 8차: 카드 타이포 계층 통일)
업데이트: 2026-04-04 11:06 (KST)
### 1) 타이포 계층 정렬
- `BuildTaskSummaryCard`의 핵심 라벨을 `11px + SemiBold`로 정리해 카드 헤더 위계를 고정.
- `BuildHookSummaryCard`, `BuildActiveBackgroundSummaryCard`, `BuildRecentBackgroundJobCard` 본문을 `10.5px` 기준으로 통일.
### 2) 테마 대비 일관화
- 카드 본문/보조문구의 기본 색상을 `SecondaryText` 리소스 우선 사용으로 정리.
- 활성/강조 상태만 별도 강조색을 유지하여 정보 계층이 더 명확해지도록 조정.
### 3) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 9차: 카드 아이콘/표시 규칙 통일)
업데이트: 2026-04-04 11:08 (KST)
### 1) 작업 카드 아이콘 헤더 도입
- `BuildTaskSummaryCard`에 작업 종류별 아이콘을 헤더에 추가하고, 제목/요약을 2줄 구조로 분리.
- 작업 종류별 공통 매핑 함수 `GetTaskKindVisual(kind)` 추가:
- permission, queue, tool, hook, subagent, default
### 2) 훅/백그라운드 카드 아이콘 정렬
- `BuildHookSummaryCard`에 `훅 이벤트` 아이콘 헤더 추가.
- `BuildActiveBackgroundSummaryCard`에 실행중 배경작업 아이콘 헤더 추가.
- `BuildRecentBackgroundJobCard`에 작업 상태 아이콘 헤더 추가.
### 3) 효과
- 카드 타입을 텍스트 읽기 전에 아이콘/색으로 먼저 인지 가능.
- 동일 카드군에서 헤더 표시 방식이 통일되어 시각 흐름이 안정화됨.
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 10차: 권한 팝업 표시/강조 정렬)
업데이트: 2026-04-04 11:11 (KST)
### 1) 권한 모드 리스트 선택 강조
- 활성 항목에 `배경(#EEF2FF) + 테두리(#C7D2FE) + 체크 아이콘`을 적용해 선택 상태 인지를 강화.
- hover 시 비활성 항목은 연한 배경/테두리, 활성 항목은 강조색을 유지하도록 분리.
### 2) 설명 가독성 정리
- 권한 요약 설명/모드 설명 텍스트에 줄간격(`LineHeight`)을 적용.
- 아이콘/텍스트 정렬과 패딩을 조정해 각 행의 시각 중심을 맞춤.
### 3) 라벨/색상 보정
- 권한 요약에 기본 모드를 내부 값 대신 표시 라벨(`PermissionModeCatalog.ToDisplayLabel`)로 출력.
- `권한 건너뛰기` 색상을 경고형 붉은 계열에서 허용형 녹색 계열로 보정.
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 11차: 권한 예외/거부 블록 정리)
업데이트: 2026-04-04 11:12 (KST)
### 1) 도구별 예외 블록 정리
- `도구별 override` 명칭을 `도구별 예외`로 변경.
- 각 예외 칩에 권한 아이콘을 추가하고, 모드 값은 내부 키 대신 표시 라벨로 출력.
- 칩 패딩/마진을 줄여 팝업 높이 사용량을 절감.
### 2) 최근 권한 거부 블록 정리
- 블록 헤더를 아이콘+제목 구조로 정리하고, 이벤트 상세를 본문 줄로 분리.
- 본문 줄간격(LineHeight) 적용으로 긴 문장 가독성 개선.
### 3) 빠른 액션 용어 통일
- `기본으로/적극 허용/차단 유지/override 해제`를
- `권한 요청/편집 자동 승인/활용하지 않음/예외 해제`
로 통일.
- 버튼 크기/마진을 축소해 같은 영역에 더 많은 액션을 안정적으로 배치.
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 12차: 권한 팝업 섹션 접힘/펼침)
업데이트: 2026-04-04 11:17 (KST)
### 1) 기본 노출 구조 변경
- 권한 팝업에서 기본 노출 영역을 `핵심 권한 모드`로 고정.
- `현재 권한 요약`, `도구별 예외`, `최근 권한 거부`, `고급 모드`는 접힘 섹션으로 재구성.
### 2) 접힘 UI 구현
- 섹션 헤더(아이콘/타이틀/캐럿) + 본문 토글 구조를 공통 빌더(`CreateCollapsibleSection`)로 구현.
- hover/클릭 반응과 펼침 상태 캐럿(▶/▼)을 동기화.
### 3) 기대 효과
- 초기 팝업 높이가 줄어 입력/채팅 영역을 가리는 정도 완화.
- 필요한 정보만 단계적으로 열람 가능해 권한 메뉴 탐색 피로 감소.
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 13차: 권한 팝업 섹션 상태 저장)
업데이트: 2026-04-04 11:19 (KST)
### 1) 설정 모델 확장
- `LlmSettings`에 `permissionPopupSections` 딕셔너리 추가.
- 권한 팝업 섹션별 마지막 펼침 상태를 설정 파일(`settings.dat`)에 저장 가능하도록 확장.
### 2) ChatWindow 상태 연동
- `GetPermissionPopupSectionExpanded(sectionKey)` / `SetPermissionPopupSectionExpanded(sectionKey, expanded)` 헬퍼 추가.
- 접힘 헤더 클릭 시 상태를 즉시 저장하고, 팝업 재오픈 시 저장된 상태를 복원.
### 3) 적용 섹션 키
- `permission_summary`
- `permission_overrides`
- `permission_denied`
- `permission_advanced`
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 14차: 슬래시 팔레트 그룹 접힘/상태 저장)
업데이트: 2026-04-04 11:23 (KST)
### 1) 설정 모델 확장
- `LlmSettings`에 `slashPaletteSections` 딕셔너리 추가.
- `/` 팔레트 그룹의 펼침 상태를 `settings.dat`에 저장 가능하게 확장.
### 2) 슬래시 팔레트 그룹 UI
- `RenderSlashPage()`에 그룹 헤더 추가:
- `명령`
- `스킬`
- 각 헤더에서 접기/펼치기 토글 가능하며, 상태를 즉시 저장.
### 3) 선택/이동 보정
- 접힘 상태를 고려해 기본 선택 인덱스를 계산(`GetFirstVisibleSlashIndex`).
- Up/Down/휠 이동(`SlashPopup_ScrollByDelta`)이 펼쳐진 그룹 항목만 순회하도록 보정.
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 15차: 슬래시 최근 사용 상단 고정)
업데이트: 2026-04-04 11:32 (KST)
### 1) 설정 모델 확장
- `LlmSettings`에 `recentSlashCommands`(MRU) 추가.
- 최근 실행한 슬래시 명령어를 최신 순으로 저장(최대 20개).
### 2) 실행 시점 기록
- `ExecuteSlashSelectedItem()`에서 실제 실행된 명령을 MRU에 기록.
### 3) 그룹 내부 정렬/표시
- `RenderSlashPage()`에서 `명령`/`스킬` 그룹 각각을 최근 사용 순으로 정렬.
- 최근 사용 항목에 `최근` 배지를 표시해 시각적으로 구분.
### 4) 선택 스크롤 정확도 보강
- 섹션 헤더/접힘으로 인해 발생하던 인덱스 불일치를 제거:
- 렌더된 실제 아이템 맵(`_slashVisibleItemByAbsoluteIndex`)으로 가시 영역 스크롤 보정.
### 5) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 16차: 슬래시 핀 고정 결합)
업데이트: 2026-04-04 11:36 (KST)
### 1) 수동 핀 고정 UI 추가
- 슬래시 팔레트 항목 우측에 핀 토글(고정/해제) 추가.
- 핀 상태 항목에 `` 배지 표시.
### 2) 정렬 우선순위 통합
- 그룹 내부 정렬을 `핀(Favorite) > 최근(MRU) > 명령어 이름` 순으로 통합.
- 명령/스킬 그룹 모두 동일 우선순위 적용.
### 3) 상호작용 보정
- 핀 토글 클릭 시 명령 실행 이벤트로 전파되지 않도록 처리(`Handled=true`).
- 팝업 오픈 상태에서는 TextChanged 트리거 없이 즉시 재렌더링하도록 `ToggleSlashFavorite()` 보강.
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 17차: AX Agent 기본 활성 + 업데이트 팝업 제거)
업데이트: 2026-04-04 11:39 (KST)
### 1) AX Agent 기본 활성화
- `AppSettings.AiEnabled` 기본값을 `true`로 변경.
- 설정 로드 정규화(`SettingsService.NormalizeRuntimeSettings`)에서 `AiEnabled=false`인 기존 값도 자동으로 `true`로 보정.
### 2) 업데이트 설치 후 메시지박스 제거
- `App.xaml.cs` 시작 로직에서 `MigrationSummary`를 `CustomMessageBox`로 표시하던 블록 제거.
- 결과적으로 업데이트/마이그레이션 직후 표시되던 안내 팝업이 더 이상 노출되지 않음.
### 3) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 18차: 슬래시 핀/최근 최대 개수 설정창 연동)
업데이트: 2026-04-04 11:41 (KST)
### 1) 설정 모델 확장
- `LlmSettings`에 아래 항목 추가:
- `maxFavoriteSlashCommands` (기본 10)
- `maxRecentSlashCommands` (기본 20)
### 2) 설정창(UI) 연동
- AX Agent > 스킬 섹션에 슬라이더 2종 추가:
- `슬래시 핀 최대 개수` (1~30)
- `슬래시 최근 최대 개수` (5~50)
- `SettingsViewModel`에 바인딩 속성/Load/Save 매핑 추가.
### 3) 런타임 제한 반영
- `ToggleSlashFavorite()`에서 핀 개수 상한을 설정값으로 적용.
- `RegisterRecentSlashCommand()`에서 최근(MRU) 상한을 설정값으로 적용.
- `BuildFavoriteSlashRankMap()`은 최대 핀 개수까지만 정렬 우선순위에 반영.
### 4) 정규화 보강
- `SettingsService.NormalizeRuntimeSettings()`에서 핀/최근 최대값 범위 보정 및 기존 리스트 길이 자동 정리.
### 5) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
## 2026-04-04 추가 진행 기록 (연속 실행 19차: 슬래시 개수 설정 회귀 점검)
업데이트: 2026-04-04 11:46 (KST)
### 1) 슬래시 설정 연동 검증
- `maxFavoriteSlashCommands`, `maxRecentSlashCommands` 설정값이
- 핀 토글 상한
- 최근(MRU) 누적 상한
- 그룹 정렬 우선순위
에 반영되는 경로를 점검.
### 2) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj --filter "FullyQualifiedName~ChatWindowSlashPolicyTests"` 통과 (39 passed, 0 failed).
## 2026-04-04 추가 진행 기록 (연속 실행 20차: 슬래시/권한 UX 마무리 + 전체 회귀)
업데이트: 2026-04-04 12:05 (KST)
### 1) 슬래시 팔레트 퀵관리 마무리
- `/` 팝업 헤더에 `정리`, `전체 접기/펼치기` 버튼을 추가.
- 모든 섹션이 접힌 경우 하단 안내 문구를 노출해 빈 화면 오인 방지.
- 섹션 상태 라벨(`전체 접기`/`전체 펼치기`)을 현재 상태에 맞춰 즉시 갱신.
### 2) 권한 팝업 키보드 접근성 보강
- 섹션 헤더를 키보드 포커스 가능 상태로 변경하고 `Enter/Space` 토글 지원.
- 권한 모드 행을 키보드 포커스 가능 상태로 변경하고 `Enter/Space` 즉시 적용 지원.
- 팝업 오픈 시 첫 포커스 자동 이동, `Esc` 닫기 지원으로 키보드 완결성 확보.
### 3) 설정 연동 가시성 개선
- AX Agent 설정의 슬래시 핀/최근 상한 슬라이더에 `저장 후 즉시 반영` 힌트를 추가해 반영 시점을 명확화.
### 4) 품질 게이트
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj` 통과 (436 passed, 0 failed).
## 2026-04-04 추가 진행 기록 (연속 실행 21차: Codex/Claude형 입력 UX 보강 + 체크리스트 정비)
업데이트: 2026-04-04 12:11 (KST)
### 1) 슬래시 입력 탐색 보강
- `/` 팝업 `ScrollViewer`에 직접 휠 이벤트를 연결해 스크롤 누락을 줄임.
- 키보드 탐색을 `Up/Down`에서 `PageUp/PageDown/Home/End`까지 확장.
- 고해상도 휠 델타를 단계 이동으로 환산해 과도한 점프/미동작을 방지.
### 2) 권한 팝업 포커스 안정화
- 권한 팝업 오픈 시 최상위 자식만 확인하던 포커스 로직을 재귀 탐색으로 교체.
- 실질적으로 포커스 가능한 첫 항목(행/섹션 헤더)에 안정적으로 진입하도록 보강.
### 3) 모델 선택 UX 단순화
- 입력창 상단 모델 버튼 클릭 동작을 AX Agent 내부 `빠른 설정 패널` 토글로 변경.
- 모델/프리셋 버튼 높이/패딩을 줄여 단일 라인 컴포저 밀도를 정돈.
### 4) UI 회귀 문서화
- `docs/UI_UX_CHECKLIST.md` 신규 추가.
- 공통 품질, 슬래시, 권한, 설정, 내부/사외 운영 모드, 빌드/테스트까지 시나리오 점검 기준을 문서화.

47
docs/UI_UX_CHECKLIST.md Normal file
View File

@@ -0,0 +1,47 @@
# AX Agent UI/UX 점검 체크리스트
업데이트: 2026-04-04 12:22 (KST)
## 1. 공통 화면 품질
- [ ] 창 진입 시 레이아웃 깨짐/문자열 깨짐 없이 렌더링된다.
- [ ] 상단 탭(`Chat`, `Cowork`, `Code`) 전환 시 불필요한 새 대화 이력이 자동 생성되지 않는다.
- [ ] 좌측 패널은 탭별 목적에 맞는 최소 메뉴만 표시된다.
- [ ] 입력창 상단의 모델/프리셋 바가 단일 라인으로 정돈되어 표시된다.
- [ ] 메시지 버블(사용자/어시스턴트)의 여백/폰트/액션 배치가 일관된다.
## 2. 슬래시(`/`) 팔레트
- [ ] `/` 입력 시 팝업이 즉시 열리고 첫 가시 항목이 선택된다.
- [ ] 마우스 휠 스크롤이 정상 동작한다.
- [ ] 방향키(Up/Down), `PageUp/PageDown`, `Home/End`, `Enter`, `Esc`가 모두 동작한다.
- [ ] `정리`, `전체 접기/펼치기` 버튼이 정상 동작한다.
- [ ] 모든 그룹을 접었을 때 안내 문구가 노출된다.
- [ ] 핀/최근 정렬 우선순위가 `핀 > 최근 > 이름`으로 유지된다.
## 3. 권한 팝업
- [ ] 권한 버튼 클릭 시 팝업이 즉시 열리고 키보드 포커스가 진입한다.
- [ ] `Tab`으로 항목 이동, `Enter/Space`로 모드 적용, `Esc`로 닫기가 동작한다.
- [ ] 섹션 접힘 상태(요약/예외/거부/고급)가 재오픈 시 복원된다.
- [ ] 하단 권한 표시와 상단 권한 배너의 표현이 현재 모드와 일치한다.
## 4. AX Agent 설정
- [ ] AX Agent 설정 창이 예외 없이 열린다(트레이/앱 내부 모두).
- [ ] 슬래시 핀 최대 개수, 최근 최대 개수 변경 후 즉시 반영된다.
- [ ] 모델 서비스/모델 변경이 입력창 모델 라벨과 일치한다.
## 5. 운영 모드 시나리오
### External 모드
- [ ] AX Agent 설정에서 `operationMode=external` 전환 후 저장한다.
- [ ] `? 검색어`를 실행하면 웹 검색이 정상 수행된다.
- [ ] 외부 LLM 호출(허용된 서비스)이 정상 수행된다.
### Internal 모드
- [ ] AX Agent 설정에서 `operationMode=internal` 전환 후 저장한다.
- [ ] `? 검색어`를 실행하면 외부 검색이 차단되고 안내 메시지가 표시된다.
- [ ] 외부 URL 열기/외부 HTTP 도구가 차단된다.
- [ ] 사내 허용 경로(온프레미스 LLM/MCP)는 정상 동작한다.
## 6. 회귀 확인
- [ ] `dotnet build src/AxCopilot/AxCopilot.csproj` 경고 0 / 오류 0
- [ ] `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj` 전체 통과

View File

@@ -188,23 +188,24 @@
Background="{DynamicResource ItemBackground}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="54"/>
<RowDefinition Height="52"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="52"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<!-- 헤더: 로고 + 새 대화 -->
<Grid Grid.Row="0" Margin="16,0">
<Grid Grid.Row="0" Margin="14,0">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Border Background="{DynamicResource AccentColor}" CornerRadius="6"
Width="24" Height="24">
<TextBlock Text="&#xE8BD;" FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<TextBlock Text="AX Agent" FontSize="14" FontWeight="Bold"
<TextBlock Text="AX Agent" FontSize="13.5" FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"
VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
@@ -219,7 +220,7 @@
<!-- 검색 -->
<Border Grid.Row="1" Background="{DynamicResource HintBackground}"
CornerRadius="10" Margin="12,0,12,8" Padding="10,7">
CornerRadius="10" Margin="12,0,12,6" Padding="10,6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
@@ -231,32 +232,17 @@
Foreground="{DynamicResource SecondaryText}" VerticalAlignment="Center"/>
<TextBox x:Name="SearchBox" Background="Transparent" BorderThickness="0"
Foreground="{DynamicResource PrimaryText}"
CaretBrush="{DynamicResource AccentColor}" FontSize="12"
CaretBrush="{DynamicResource AccentColor}" FontSize="11.5"
VerticalAlignment="Center" Margin="22,0,8,0"
TextChanged="SearchBox_TextChanged"/>
<Button x:Name="BtnFailedOnlyFilter" Grid.Column="1"
<Button x:Name="BtnConversationSort" Grid.Column="1"
Style="{StaticResource GhostBtn}"
Padding="8,3" MinWidth="54"
VerticalAlignment="Center"
Click="BtnFailedOnlyFilter_Click"
ToolTip="실패한 에이전트 실행이 있는 대화만 보기">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xEA39;" FontFamily="Segoe MDL2 Assets" FontSize="11"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="0,0,5,0"/>
<TextBlock x:Name="FailedOnlyFilterLabel" Text="실패"
FontSize="11" FontWeight="SemiBold"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
</StackPanel>
</Button>
<Button x:Name="BtnConversationSort" Grid.Column="2"
Style="{StaticResource GhostBtn}"
Padding="8,3" MinWidth="54"
Margin="6,0,0,0"
Margin="0,0,0,0"
VerticalAlignment="Center"
Click="BtnConversationSort_Click"
ToolTip="대화 정렬 기준 전환">
ToolTip="대화 정렬 기준 전환"
Visibility="Collapsed">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xE8CB;" FontFamily="Segoe MDL2 Assets" FontSize="11"
Foreground="{DynamicResource SecondaryText}"
@@ -267,13 +253,15 @@
VerticalAlignment="Center"/>
</StackPanel>
</Button>
<Button x:Name="BtnRunningOnlyFilter" Grid.Column="3"
<Button x:Name="BtnRunningOnlyFilter" Grid.Column="2"
Style="{StaticResource GhostBtn}"
Padding="8,3" MinWidth="54"
Margin="6,0,0,0"
VerticalAlignment="Center"
Click="BtnRunningOnlyFilter_Click"
ToolTip="현재 실행 중인 대화만 보기">
ToolTip="비활성"
Visibility="Collapsed"
IsEnabled="False">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xE768;" FontFamily="Segoe MDL2 Assets" FontSize="11"
Foreground="{DynamicResource SecondaryText}"
@@ -288,9 +276,9 @@
</Border>
<!-- 카테고리 드롭다운: "모든 주제 ▼" -->
<Border Grid.Row="2" Margin="12,0,12,6">
<Border Grid.Row="2" Margin="12,0,12,4">
<Button x:Name="BtnCategoryDrop" Style="{StaticResource GhostBtn}"
HorizontalAlignment="Stretch" Padding="10,6"
HorizontalAlignment="Stretch" Padding="10,5"
Click="BtnCategoryDrop_Click">
<Grid HorizontalAlignment="Stretch">
<StackPanel Orientation="Horizontal">
@@ -299,7 +287,7 @@
Foreground="{DynamicResource AccentColor}"
VerticalAlignment="Center" Margin="0,0,8,0"/>
<TextBlock x:Name="CategoryLabel" Text="모든 주제"
FontSize="12" FontWeight="SemiBold"
FontSize="11.5" FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"
VerticalAlignment="Center"/>
</StackPanel>
@@ -310,14 +298,118 @@
</Button>
</Border>
<!-- 탭별 좌측 메뉴 -->
<Border Grid.Row="3" Margin="12,0,12,6"
Background="{DynamicResource HintBackground}"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="1"
CornerRadius="10"
Padding="10,8">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,4">
<TextBlock x:Name="SidebarModeBadgeIcon" Text="&#xE8BD;"
FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="{DynamicResource AccentColor}"
VerticalAlignment="Center" Margin="0,0,6,0"/>
<TextBlock x:Name="SidebarModeBadgeTitle" Text="Chat 메뉴"
FontSize="11.5" FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"
VerticalAlignment="Center"/>
</StackPanel>
<StackPanel x:Name="SidebarChatMenu" Visibility="Visible">
<Border Cursor="Hand" Background="Transparent" CornerRadius="8"
Padding="8,5" Margin="0,0,0,3"
MouseLeftButtonUp="SidebarChatAll_MouseLeftButtonUp">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="&#xE8BD;" FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="{DynamicResource AccentColor}" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="주제 탐색"
Foreground="{DynamicResource PrimaryText}"
FontSize="11.5" Margin="8,0,0,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="&#xE70D;" FontFamily="Segoe MDL2 Assets" FontSize="9"
Foreground="{DynamicResource SecondaryText}" VerticalAlignment="Center"/>
</Grid>
</Border>
<Border x:Name="SidebarChatRunningRow" Cursor="Hand" Background="Transparent" CornerRadius="8"
Padding="8,5"
MouseLeftButtonUp="SidebarChatRunning_MouseLeftButtonUp"
Visibility="Collapsed">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="&#xE768;" FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="#22C55E" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="진행 중 대화만 보기"
Foreground="{DynamicResource PrimaryText}"
FontSize="11.5" Margin="8,0,0,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" x:Name="SidebarChatRunningState" Text="OFF"
Foreground="{DynamicResource SecondaryText}"
FontSize="11" VerticalAlignment="Center"/>
</Grid>
</Border>
</StackPanel>
<StackPanel x:Name="SidebarCoworkMenu" Visibility="Collapsed">
<Border Cursor="Hand" Background="Transparent" CornerRadius="8"
Padding="8,5" Margin="0,0,0,3"
MouseLeftButtonUp="SidebarCoworkCategory_MouseLeftButtonUp">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="&#xE8FD;" FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="#3B82F6" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="작업 유형 선택"
Foreground="{DynamicResource PrimaryText}"
FontSize="11.5" Margin="8,0,0,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="&#xE70D;" FontFamily="Segoe MDL2 Assets" FontSize="9"
Foreground="{DynamicResource SecondaryText}" VerticalAlignment="Center"/>
</Grid>
</Border>
</StackPanel>
<StackPanel x:Name="SidebarCodeMenu" Visibility="Collapsed">
<Border Cursor="Hand" Background="Transparent" CornerRadius="8"
Padding="8,5" Margin="0,0,0,3"
MouseLeftButtonUp="SidebarCodeCategory_MouseLeftButtonUp">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="&#xE943;" FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="#3B82F6" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="코드 작업 유형"
Foreground="{DynamicResource PrimaryText}"
FontSize="11.5" Margin="8,0,0,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="&#xE70D;" FontFamily="Segoe MDL2 Assets" FontSize="9"
Foreground="{DynamicResource SecondaryText}" VerticalAlignment="Center"/>
</Grid>
</Border>
</StackPanel>
</StackPanel>
</Border>
<!-- 대화 목록 -->
<ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto"
<ScrollViewer Grid.Row="4" VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled">
<StackPanel x:Name="ConversationPanel" Margin="6,0"/>
<StackPanel x:Name="ConversationPanel" Margin="8,0"/>
</ScrollViewer>
<!-- 하단: 삭제 -->
<Border Grid.Row="4" BorderBrush="{DynamicResource SeparatorColor}" BorderThickness="0,1,0,0"
<Border Grid.Row="5" BorderBrush="{DynamicResource SeparatorColor}" BorderThickness="0,1,0,0"
Padding="0,4">
<Button x:Name="BtnDeleteAll" Style="{StaticResource GhostBtn}"
HorizontalAlignment="Center" VerticalAlignment="Center"
@@ -331,11 +423,12 @@
</Border>
<!-- 하단: 사용자 계정 -->
<Border Grid.Row="5" Margin="12,0,12,8">
<Border Grid.Row="6" Margin="12,0,12,8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Width="34" Height="34" CornerRadius="17"
Background="{DynamicResource AccentColor}" Margin="0,0,10,0">
@@ -349,6 +442,21 @@
<TextBlock x:Name="UserPcText" Text="" FontSize="10"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<Button x:Name="BtnSidebarSettings"
Grid.Column="2"
Style="{StaticResource GhostBtn}"
Width="32" Height="32"
Margin="8,0,0,0"
VerticalAlignment="Center"
Click="BtnSettings_Click"
ToolTip="AX Agent 설정">
<TextBlock Text="&#xE713;"
FontFamily="Segoe MDL2 Assets"
FontSize="13"
Foreground="{DynamicResource SecondaryText}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Button>
</Grid>
</Border>
</Grid>
@@ -408,16 +516,12 @@
Margin="0,4,0,0">
<Button x:Name="BtnQuickRunningFilter" Style="{StaticResource GhostBtn}"
Padding="8,2" Margin="0,0,6,0"
Click="BtnQuickRunningFilter_Click">
Click="BtnQuickRunningFilter_Click"
Visibility="Collapsed"
IsEnabled="False">
<TextBlock x:Name="QuickRunningLabel" Text="진행"
FontSize="10" FontWeight="SemiBold"/>
</Button>
<Button x:Name="BtnQuickFailedFilter" Style="{StaticResource GhostBtn}"
Padding="8,2" Margin="0,0,6,0"
Click="BtnQuickFailedFilter_Click">
<TextBlock x:Name="QuickFailedLabel" Text="실패"
FontSize="10" FontWeight="SemiBold"/>
</Button>
<Button x:Name="BtnQuickHotSort" Style="{StaticResource GhostBtn}"
Padding="8,2"
Click="BtnQuickHotSort_Click">
@@ -483,6 +587,60 @@
Text="0:00" FontSize="10.5"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
</Grid>
</Border>
<!-- ── 상단 권한 알림 배너 ── -->
<Border x:Name="PermissionTopBanner"
Grid.Row="0" Grid.RowSpan="3"
Visibility="Collapsed"
Margin="16,94,16,0"
VerticalAlignment="Top"
Panel.ZIndex="20"
Background="{DynamicResource HintBackground}"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="1"
CornerRadius="10"
Padding="10,8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="PermissionTopBannerIcon"
Text="&#xE7BA;"
FontFamily="Segoe MDL2 Assets"
FontSize="12"
Margin="0,0,8,0"
VerticalAlignment="Center"
Foreground="{DynamicResource AccentColor}"/>
<StackPanel>
<TextBlock x:Name="PermissionTopBannerTitle"
Text="현재 권한 모드"
FontSize="12"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock x:Name="PermissionTopBannerText"
Text=""
FontSize="11"
TextWrapping="Wrap"
MaxWidth="760"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
</StackPanel>
<Button x:Name="BtnPermissionTopBannerClose"
Grid.Column="1"
Style="{StaticResource GhostBtn}"
Padding="2"
Cursor="Hand"
Click="BtnPermissionTopBannerClose_Click"
ToolTip="닫기">
<TextBlock Text="&#xE711;"
FontFamily="Segoe MDL2 Assets"
FontSize="9"
Foreground="{DynamicResource SecondaryText}"/>
</Button>
</Grid>
</Border>
@@ -517,14 +675,10 @@
</StackPanel>
</Border>
<!-- 우: 설정 + 최소화 + 최대화 + 닫기 -->
<!-- 우: 최소화 + 최대화 + 닫기 -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,0,4,0"
WindowChrome.IsHitTestVisibleInChrome="True">
<Button Style="{StaticResource GhostBtn}" Click="BtnSettings_Click" ToolTip="설정">
<TextBlock Text="&#xE713;" FontFamily="Segoe MDL2 Assets" FontSize="13"
Foreground="{DynamicResource SecondaryText}"/>
</Button>
<Button Style="{StaticResource GhostBtn}" Click="BtnMinimize_Click" ToolTip="최소화">
<TextBlock Text="&#xE921;" FontFamily="Segoe MDL2 Assets" FontSize="11"
Foreground="{DynamicResource SecondaryText}"/>
@@ -677,8 +831,11 @@
AllowsTransparency="True" PopupAnimation="Fade">
<Border Background="{DynamicResource LauncherBackground}"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="1" CornerRadius="12"
Padding="6" MinWidth="260">
BorderThickness="1" CornerRadius="16"
Padding="8" MinWidth="320">
<Border.Effect>
<DropShadowEffect BlurRadius="18" ShadowDepth="0" Opacity="0.14"/>
</Border.Effect>
<StackPanel x:Name="PermissionItems" Margin="2"/>
</Border>
</Popup>
@@ -701,65 +858,102 @@
PlacementTarget="{Binding ElementName=InputBorder}"
Placement="Top" StaysOpen="False"
AllowsTransparency="True" PopupAnimation="Fade">
<Border Background="{DynamicResource ItemBackground}"
<Border Background="{DynamicResource LauncherBackground}"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="1" CornerRadius="18"
Padding="12" MinWidth="560" MaxWidth="820"
Padding="0" MinWidth="620" MaxWidth="780"
PreviewMouseWheel="SlashPopup_PreviewMouseWheel">
<Border.Effect>
<DropShadowEffect BlurRadius="20" ShadowDepth="0" Opacity="0.12"/>
<DropShadowEffect BlurRadius="16" ShadowDepth="0" Opacity="0.16"/>
</Border.Effect>
<StackPanel>
<StackPanel Margin="8,4,8,8">
<TextBlock x:Name="SlashPopupTitle"
Text="명령어와 스킬"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock x:Name="SlashPopupHint"
Text="/ 로 빠른 명령과 스킬을 실행할 수 있습니다"
FontSize="11"
Foreground="{DynamicResource SecondaryText}"
Margin="0,3,0,0"/>
</StackPanel>
<!-- 위 화살표 -->
<Border x:Name="SlashNavUp" Visibility="Collapsed" Cursor="Hand"
CornerRadius="6" Padding="8,4,8,4" Margin="0,0,0,2">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource ItemHoverBackground}"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock x:Name="SlashNavUpText" FontSize="10.5"
HorizontalAlignment="Center"
Foreground="{DynamicResource SecondaryText}"/>
</Border>
<!-- 아이템 목록 -->
<ItemsControl x:Name="SlashItems"/>
<!-- 아래 화살표 -->
<Border x:Name="SlashNavDown" Visibility="Collapsed" Cursor="Hand"
CornerRadius="6" Padding="8,4,8,4" Margin="0,2,0,0">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource ItemHoverBackground}"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock x:Name="SlashNavDownText" FontSize="10.5"
HorizontalAlignment="Center"
Foreground="{DynamicResource SecondaryText}"/>
<Border Background="{DynamicResource ItemBackground}"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="0,0,0,1"
CornerRadius="18,18,0,0"
Padding="14,12,14,10">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Grid.Column="0">
<Border Background="{DynamicResource AccentColor}"
CornerRadius="8"
Padding="6,2"
Margin="0,0,8,0"
VerticalAlignment="Center">
<TextBlock Text="/"
FontSize="12"
FontWeight="SemiBold"
Foreground="White"/>
</Border>
<TextBlock x:Name="SlashPopupTitle"
Text="명령 및 스킬"
FontSize="13.5"
FontWeight="SemiBold"
Foreground="{DynamicResource PrimaryText}"
VerticalAlignment="Center"/>
</StackPanel>
<Button Grid.Column="1"
x:Name="BtnSlashReset"
Click="BtnSlashReset_Click"
Style="{StaticResource GhostBtn}"
Padding="8,4"
Margin="0,0,6,0"
ToolTip="핀/최근 정리">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xE74D;"
FontFamily="Segoe MDL2 Assets"
FontSize="10.5"
Foreground="{DynamicResource SecondaryText}"
Margin="0,0,4,0"/>
<TextBlock Text="정리"
FontSize="11.5"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
</Button>
<Button Grid.Column="2"
x:Name="BtnSlashToggleGroups"
Click="BtnSlashToggleGroups_Click"
Style="{StaticResource GhostBtn}"
Padding="8,4"
ToolTip="명령/스킬 그룹 전체 접기 또는 펼치기">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xE70D;"
FontFamily="Segoe MDL2 Assets"
FontSize="10.5"
Foreground="{DynamicResource SecondaryText}"
Margin="0,0,4,0"/>
<TextBlock x:Name="SlashToggleGroupsLabel"
Text="전체 접기"
FontSize="11.5"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
</Button>
</Grid>
<TextBlock x:Name="SlashPopupHint"
Text="방향키나 마우스 휠로 이동하고 Enter로 바로 실행합니다"
FontSize="11.5"
Foreground="{DynamicResource SecondaryText}"
Margin="0,6,0,0"/>
</StackPanel>
</Border>
<ScrollViewer x:Name="SlashScrollViewer"
MaxHeight="420"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
CanContentScroll="False"
PanningMode="VerticalOnly"
PreviewMouseWheel="SlashPopup_PreviewMouseWheel"
Padding="10,10,10,8">
<ItemsControl x:Name="SlashItems"/>
</ScrollViewer>
<TextBlock x:Name="SlashPopupFooter"
Margin="8,8,8,2"
Text="Enter 실행 · ↑↓ 탐색 · 별 아이콘 즐겨찾기"
Margin="14,0,14,12"
Text="Enter 실행 · ↑↓ 이동 · 휠 스크롤 · Esc 닫기"
FontSize="10.5"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
@@ -899,19 +1093,27 @@
</Grid.RowDefinitions>
<!-- Row 0: 모델 셀렉터 + 템플릿 버튼 -->
<Grid Grid.Row="0">
<Grid Grid.Row="0" Margin="6,2,6,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button x:Name="BtnModelSelector"
Style="{StaticResource OutlineHoverBtn}"
Grid.Column="0"
HorizontalAlignment="Left"
Margin="8,2,0,2"
Margin="0"
MinHeight="28"
Padding="10,3"
Click="BtnModelSelector_Click"
ToolTip="모델 변경"
ToolTip="모델/추론 빠른 설정"
WindowChrome.IsHitTestVisibleInChrome="True">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xEA86;" FontFamily="Segoe MDL2 Assets" FontSize="13"
<TextBlock Text="&#xEA86;" FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="0,0,5,0"/>
<TextBlock x:Name="ModelLabel" FontSize="13"
<TextBlock x:Name="ModelLabel" FontSize="12.5"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
<TextBlock Text="&#xE70D;" FontFamily="Segoe MDL2 Assets" FontSize="9"
@@ -921,18 +1123,25 @@
</Button>
<Button x:Name="BtnTemplateSelector"
Style="{StaticResource OutlineHoverBtn}"
Grid.Column="2"
HorizontalAlignment="Right"
Margin="0,2,8,2"
Margin="0"
MinHeight="28"
MinWidth="64"
Padding="8,3"
Click="BtnTemplateSelector_Click"
ToolTip="프롬프트 템플릿"
WindowChrome.IsHitTestVisibleInChrome="True">
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xE8A5;" FontFamily="Segoe MDL2 Assets" FontSize="13"
<TextBlock Text="&#xE8A5;" FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="0,0,5,0"/>
<TextBlock Text="템플릿" FontSize="13"
<TextBlock Text="프리셋" FontSize="12"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
<TextBlock Text="&#xE70D;" FontFamily="Segoe MDL2 Assets" FontSize="8"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="4,1,0,0"/>
</StackPanel>
</Button>
</Grid>
@@ -961,8 +1170,9 @@
Foreground="{DynamicResource PrimaryText}"
VerticalAlignment="Center"/>
<TextBlock Grid.Column="1"
x:Name="InlineSettingsHintText"
Margin="8,0,0,0"
Text="모델/실행 옵션"
Text="모델/권한 핵심 옵션"
FontSize="11"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
@@ -1009,7 +1219,7 @@
SelectionChanged="CmbInlineModel_SelectionChanged"/>
</Grid>
<WrapPanel>
<WrapPanel x:Name="InlineSettingsQuickActions">
<Button x:Name="BtnInlineFastMode"
Style="{StaticResource OutlineHoverBtn}"
Margin="0,0,6,6"
@@ -1034,17 +1244,20 @@
Style="{StaticResource OutlineHoverBtn}"
Margin="0,0,6,6"
Padding="10,5"
Click="BtnInlineSkill_Click"/>
Click="BtnInlineSkill_Click"
Visibility="Collapsed"/>
<Button x:Name="BtnInlineCommandBrowser"
Style="{StaticResource OutlineHoverBtn}"
Margin="0,0,6,6"
Padding="10,5"
Click="BtnInlineCommandBrowser_Click"/>
Click="BtnInlineCommandBrowser_Click"
Visibility="Collapsed"/>
<Button x:Name="BtnInlineMcp"
Style="{StaticResource OutlineHoverBtn}"
Margin="0,0,6,6"
Padding="10,5"
Click="BtnInlineMcp_Click"/>
Click="BtnInlineMcp_Click"
Visibility="Collapsed"/>
</WrapPanel>
</StackPanel>
</Border>
@@ -1247,7 +1460,7 @@
<TextBlock x:Name="DataUsageIcon" Text="&#xE9F5;" FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock x:Name="DataUsageLabel" Text="적극" FontSize="12"
<TextBlock x:Name="DataUsageLabel" Text="활용하지 않음" FontSize="12"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
</StackPanel>
@@ -1264,7 +1477,7 @@
<TextBlock x:Name="PermissionIcon" Text="&#xE8D7;" FontFamily="Segoe MDL2 Assets" FontSize="12"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center" Margin="0,0,4,0"/>
<TextBlock x:Name="PermissionLabel" Text="Ask" FontSize="12"
<TextBlock x:Name="PermissionLabel" Text="권한 요청" FontSize="12"
Foreground="{DynamicResource SecondaryText}"
VerticalAlignment="Center"/>
</StackPanel>
@@ -1298,24 +1511,6 @@
</Border>
</Popup>
<!-- Auto 권한 경고 배너 (1회 필수 표시, X로 닫기 가능) -->
<Border x:Name="AutoPermissionWarning" Visibility="Collapsed"
Background="#2ADD6B20" CornerRadius="6" Margin="4,2,4,0" Padding="8,4">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="&#xE7BA;" FontFamily="Segoe MDL2 Assets" FontSize="11"
Foreground="#DD6B20" VerticalAlignment="Center" Margin="0,0,6,0"/>
<TextBlock Text="⚠ Auto 모드: AI가 파일을 자동으로 읽고 수정합니다" FontSize="10.5"
Foreground="#DD6B20" VerticalAlignment="Center" FontWeight="SemiBold"/>
</StackPanel>
<Button x:Name="BtnAutoWarningClose" HorizontalAlignment="Right" VerticalAlignment="Center"
Style="{StaticResource GhostBtn}" Padding="2" Cursor="Hand"
Click="BtnAutoWarningClose_Click" ToolTip="닫기">
<TextBlock Text="&#xE711;" FontFamily="Segoe MDL2 Assets" FontSize="8"
Foreground="#DD6B20"/>
</Button>
</Grid>
</Border>
</StackPanel>
</Border>

File diff suppressed because it is too large Load Diff