diff --git a/README.md b/README.md index cd41c42..b6b2c69 100644 --- a/README.md +++ b/README.md @@ -222,7 +222,7 @@ public class MyHandler : IActionHandler ### v0.7.3 — AX Agent 권한 코어 재구성 + 입력 계층 정리 -업데이트: 2026-04-04 15:48 (KST) +업데이트: 2026-04-04 15:52 (KST) | 분류 | 내용 | |------|------| @@ -290,6 +290,7 @@ public class MyHandler : IActionHandler | 권한 모드 별칭 정합 보강 | `/permissions`, `/allowed-tools`에서 `none/passive/active/planning/fullauto/silent` 별칭을 지원하고 카탈로그 정규화와 일치시킴 | | 권한 기본값 정책 정렬 | 신규/초기 상태의 기본 권한을 `활용하지 않음(Deny)`으로 변경하고 AppState 기본/요약 상태와 slash 사용 가이드를 동일 체계로 정렬 | | 탭 전환 빈 대화 누적 방지 | 탭 전환 중 생성되는 무의미한 빈 대화를 저장 대상에서 제외하고, 목록에서도 빈 노이즈 항목을 숨겨 이력 누적 체감 버그를 완화 | +| 권한 팝업 즉시반영 정렬 | 권한 팝업에 `활용하지 않음`을 핵심 영역 맨 위에 배치하고, 대화 권한이 없을 때도 탭 기본값(Deny/DefaultAgentPermission)을 즉시 반영하도록 로딩 경로를 보강 | | Slash palette 상태 분리 시작 | `ChatWindow`에 몰려 있던 slash 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편 기반 마련 | | 런처 이미지 미리보기 추가 | `#` 클립보드 이미지 항목에서 `Shift+Enter`로 전용 미리보기 창을 열고, 줌·원본 해상도 확인·PNG/JPEG/BMP 저장·클립보드 복사를 지원 | | 검증 | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed | diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 7240057..fa1d0d5 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -3605,3 +3605,25 @@ else: ### 4) 품질 게이트 - `dotnet build src/AxCopilot/AxCopilot.csproj -c Debug -p:UseSharedCompilation=false -nodeReuse:false` 통과 (경고 0, 오류 0). - `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj --filter "FullyQualifiedName~ChatSessionStateServiceTests|FullyQualifiedName~AppStateServiceTests|FullyQualifiedName~OperationModePolicyTests|FullyQualifiedName~ChatWindowSlashPolicyTests"` 통과 (132 passed, 0 failed). + +## 2026-04-04 추가 진행 기록 (연속 실행 40차: 권한 팝업 순서/즉시반영 정렬) + +업데이트: 2026-04-04 15:52 (KST) + +### 1) 권한 팝업 표시 순서 정렬 +- `ChatWindow` 권한 팝업의 핵심 모드 목록에 `활용하지 않음(Deny)`을 포함해 맨 위에서 선택 가능하도록 조정. +- 고급 모드는 `질문 없이 진행(DontAsk)`만 유지해 핵심/고급 구분을 단순화. + +### 2) 탭/대화 전환 시 권한 즉시반영 보강 +- `LoadConversationSettings`에서 대화 권한이 비어 있는 경우에도 명시적으로 탭 기본값을 적용: + - `Chat` 탭: `Deny` + - `Cowork/Code` 탭: `DefaultAgentPermission` +- 효과: 이전 대화의 권한 값이 남아 2번 눌러야 반영되는 현상 완화. + +### 3) 권한 프리젠테이션 카탈로그 문자열 정리 +- `PermissionModePresentationCatalog`의 권한 라벨/설명 문자열을 정상 한글 문구로 정리(깨짐 문자열 제거). +- 표시 문구와 실제 권한 의미를 일치시켜 UX 혼선을 줄임. + +### 4) 품질 게이트 +- `dotnet build src/AxCopilot/AxCopilot.csproj -c Debug -p:UseSharedCompilation=false -nodeReuse:false` 통과 (경고 0, 오류 0). +- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj --filter "FullyQualifiedName~PermissionModePresentationCatalogTests|FullyQualifiedName~PermissionModeCatalogTests|FullyQualifiedName~ChatWindowSlashPolicyTests|FullyQualifiedName~ChatSessionStateServiceTests"` 통과 (111 passed, 0 failed). diff --git a/src/AxCopilot/Services/Agent/PermissionModePresentationCatalog.cs b/src/AxCopilot/Services/Agent/PermissionModePresentationCatalog.cs index e04d187..f9ef431 100644 --- a/src/AxCopilot/Services/Agent/PermissionModePresentationCatalog.cs +++ b/src/AxCopilot/Services/Agent/PermissionModePresentationCatalog.cs @@ -1,4 +1,4 @@ -namespace AxCopilot.Services.Agent; +namespace AxCopilot.Services.Agent; internal sealed record PermissionModePresentation( string Mode, @@ -15,37 +15,37 @@ internal static class PermissionModePresentationCatalog PermissionModeCatalog.Deny, "\uE711", "활용하지 않음", - "파일 읽기만 허용하고 생성/수정/삭제를 차단합니다", + "파일 읽기만 허용하고 생성/수정/삭제는 차단합니다.", "#107C10"), new PermissionModePresentation( PermissionModeCatalog.Default, "\uE8D7", "소극 활용", - "변경 전 확인하며 필요할 때만 파일 접근을 진행합니다", + "변경 전 확인하고, 필요한 경우에만 파일 접근을 진행합니다.", "#2563EB"), new PermissionModePresentation( PermissionModeCatalog.AcceptEdits, "\uE73E", "적극 활용", - "파일 편집 도구를 자동 승인하고 명령 실행은 계속 확인합니다", + "파일 편집 도구를 자동 승인하고 명령 실행은 계속 확인합니다.", "#107C10"), new PermissionModePresentation( PermissionModeCatalog.Plan, "\uE7C3", "계획 중심", - "쓰기 전 계획/승인 흐름을 우선합니다", + "쓰기 전 계획과 승인 흐름을 우선합니다.", "#4338CA"), new PermissionModePresentation( PermissionModeCatalog.BypassPermissions, "\uE814", "완전 자동", - "권한 확인을 대부분 생략합니다. 민감 작업에 주의하세요", + "권한 확인을 대부분 생략합니다. 민감한 작업은 주의하세요.", "#B45309"), new PermissionModePresentation( PermissionModeCatalog.DontAsk, "\uE8A5", "질문 없이 진행", - "권한 질문 없이 진행합니다. 자동 실행 범위를 점검하세요", + "권한 질문 없이 진행합니다. 자동 실행 범위를 점검하세요.", "#B91C1C"), }; diff --git a/src/AxCopilot/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index 767cc23..9934036 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -1561,8 +1561,13 @@ public partial class ChatWindow : Window lock (_convLock) conv = _currentConversation; var llm = _settings.Settings.Llm; - if (conv != null && conv.Permission != null) - _settings.Settings.Llm.FilePermission = PermissionModeCatalog.NormalizeGlobalMode(conv.Permission); + var fallbackPermission = _activeTab == "Chat" + ? PermissionModeCatalog.Deny + : PermissionModeCatalog.NormalizeGlobalMode(llm.DefaultAgentPermission); + var conversationPermission = !string.IsNullOrWhiteSpace(conv?.Permission) + ? PermissionModeCatalog.NormalizeGlobalMode(conv.Permission) + : fallbackPermission; + _settings.Settings.Llm.FilePermission = conversationPermission; _folderDataUsage = conv?.DataUsage ?? llm.FolderDataUsage ?? "none"; _selectedMood = conv?.Mood ?? llm.DefaultMood ?? "modern"; @@ -1903,15 +1908,14 @@ public partial class ChatWindow : Window var coreLevels = PermissionModePresentationCatalog.Ordered .Where(x => + string.Equals(x.Mode, PermissionModeCatalog.Deny, StringComparison.OrdinalIgnoreCase) || string.Equals(x.Mode, PermissionModeCatalog.Default, StringComparison.OrdinalIgnoreCase) || string.Equals(x.Mode, PermissionModeCatalog.AcceptEdits, StringComparison.OrdinalIgnoreCase) || string.Equals(x.Mode, PermissionModeCatalog.Plan, StringComparison.OrdinalIgnoreCase) || string.Equals(x.Mode, PermissionModeCatalog.BypassPermissions, StringComparison.OrdinalIgnoreCase)) .ToList(); var advancedLevels = PermissionModePresentationCatalog.Ordered - .Where(x => - string.Equals(x.Mode, PermissionModeCatalog.Deny, StringComparison.OrdinalIgnoreCase) || - string.Equals(x.Mode, PermissionModeCatalog.DontAsk, StringComparison.OrdinalIgnoreCase)) + .Where(x => string.Equals(x.Mode, PermissionModeCatalog.DontAsk, StringComparison.OrdinalIgnoreCase)) .ToList(); var current = PermissionModeCatalog.NormalizeGlobalMode(_settings.Settings.Llm.FilePermission); void AddPermissionRows(Panel container, IEnumerable levels)