연속 개선: 권한 상태 간소화·설정창 외부 진입 안정화·컴포저 반응형 보강
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- 권한 상태 텍스트(/permissions,/allowed-tools)를 운영 모드 포함 축약형으로 재정리 - 하단 권한 버튼 툴팁에 운영 모드/기본값/예외 개수 정보를 일관 반영 - 탭 전환 시 좌측 메뉴 Visibility 재할당을 최소화해 UI 흔들림 완화 - 상단 모델 라벨에 MaxWidth+말줄임 적용으로 긴 모델명 레이아웃 깨짐 방지 - AX Agent 설정창 오픈 시 리소스 병합 예외를 방어하고 외부 진입 경로를 Dispatcher 기반으로 안정화 - UI 체크리스트/개발문서/README에 2026-04-04 12:41 기준 점검 이력 업데이트 - 검증: build 경고0/오류0, 운영모드 필터 18건 통과, 전체 테스트 436건 통과
This commit is contained in:
@@ -222,7 +222,7 @@ public class MyHandler : IActionHandler
|
||||
|
||||
### v0.7.3 — AX Agent 권한 코어 재구성 + 입력 계층 정리
|
||||
|
||||
업데이트: 2026-04-04 12:33 (KST)
|
||||
업데이트: 2026-04-04 12:41 (KST)
|
||||
|
||||
| 분류 | 내용 |
|
||||
|------|------|
|
||||
@@ -270,6 +270,9 @@ public class MyHandler : IActionHandler
|
||||
| 권한 팝업 밀도 재정돈 | 권한 섹션 헤더/카드/행의 패딩·폰트·줄간격을 조정해 과밀 영역을 완화하고 Codex/Claude형 스캔 속도에 맞춤 |
|
||||
| 좌측/컴포저 라벨 정리 | 좌측 기본 카테고리 라벨을 `주제 선택/작업 선택`으로 통일하고, 입력 상단 바 패딩·간격을 미세 조정해 단일 라인 정돈 강화 |
|
||||
| 체크리스트 실행 결과 기록 | `docs/UI_UX_CHECKLIST.md`에 2026-04-04 12:22 기준 점검 결과(운영모드 필터 18건 + 전체 436건 통과)를 기록 |
|
||||
| 권한 상태 표시 간소화 | 권한 상태 텍스트(`/permissions`, `/allowed-tools`)를 운영 모드 포함 축약형으로 정리하고 권한 버튼 툴팁에 동일 정보를 반영 |
|
||||
| 설정창 외부 진입 안정화 | AX Agent 설정창 오픈 시 리소스 병합 실패를 방어하고, 외부 진입 경로를 Dispatcher 기반으로 안정화 |
|
||||
| 모델 라벨 반응형 보강 | 컴포저 상단 모델 라벨에 말줄임(`MaxWidth` + `CharacterEllipsis`)을 적용해 좁은 폭에서 레이아웃 깨짐을 방지 |
|
||||
| Slash palette 상태 분리 시작 | `ChatWindow`에 몰려 있던 slash 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편 기반 마련 |
|
||||
| 런처 이미지 미리보기 추가 | `#` 클립보드 이미지 항목에서 `Shift+Enter`로 전용 미리보기 창을 열고, 줌·원본 해상도 확인·PNG/JPEG/BMP 저장·클립보드 복사를 지원 |
|
||||
| 검증 | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed |
|
||||
|
||||
@@ -3239,6 +3239,37 @@ else:
|
||||
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
|
||||
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj` 통과 (436 passed, 0 failed).
|
||||
|
||||
## 2026-04-04 추가 진행 기록 (연속 실행 24차: 권한/설정 안정화 보강 + 시나리오 점검)
|
||||
|
||||
업데이트: 2026-04-04 12:41 (KST)
|
||||
|
||||
### 1) 권한 상태 표시 간소화
|
||||
- `/permissions`, `/allowed-tools` 상태 텍스트를 축약형으로 재정리:
|
||||
- 현재 권한 모드
|
||||
- 운영 모드
|
||||
- 기본값/예외 개수
|
||||
- 예외 미리보기(최대 3개)
|
||||
- 하단 권한 버튼 툴팁에도 동일한 운영 모드/기본값/예외 정보를 반영.
|
||||
|
||||
### 2) 좌측 패널 전환 안정화
|
||||
- `UpdateSidebarModeMenu()`에서 탭별 메뉴 표시를 동일 값 재할당하지 않도록 보강해 전환 시 불필요한 렌더 흔들림을 완화.
|
||||
|
||||
### 3) 컴포저 반응형 보강
|
||||
- 상단 모델 라벨에 `MaxWidth=280`, `TextTrimming=CharacterEllipsis` 적용.
|
||||
- 긴 모델명 선택 시 컴포저 레이아웃 깨짐을 방지.
|
||||
|
||||
### 4) AX Agent 설정창 오픈 안정성 보강
|
||||
- 설정창 리소스 병합 실패 시에도 창 오픈이 유지되도록 예외 방어 추가.
|
||||
- `OpenAgentSettingsFromExternal()`를 Dispatcher 경유로 변경해 트레이/외부 진입 시 타이밍 이슈를 완화.
|
||||
|
||||
### 5) 시나리오/회귀 점검
|
||||
- 운영 모드 필터 테스트(18건) 재통과:
|
||||
- `OperationModePolicyTests`
|
||||
- `OperationModeReadinessTests`
|
||||
- `LlmOperationModeTests`
|
||||
- 전체 테스트 436건 재통과.
|
||||
- `dotnet build` 경고 0 / 오류 0 유지.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -54,3 +54,12 @@
|
||||
- [x] AX Agent 설정 권한 순환 순서와 `/sandbox-toggle` 순환 순서 일치 확인
|
||||
- [x] 운영 모드 회귀 필터 테스트 18건 통과 (`OperationModePolicy/Readiness/LlmOperationMode`)
|
||||
- [x] 전체 테스트 436건 통과
|
||||
|
||||
점검 시각: 2026-04-04 12:41 (KST)
|
||||
|
||||
- [x] 권한 버튼 툴팁에 운영 모드 + 기본 권한 + 예외 개수 표시 확인
|
||||
- [x] 권한 상태 텍스트(`/permissions`, `/allowed-tools`)를 축약형으로 정리 확인
|
||||
- [x] 모델 라벨 말줄임 처리(`MaxWidth`, `CharacterEllipsis`) 적용 확인
|
||||
- [x] 설정창 외부 진입(`OpenAgentSettingsFromExternal`) Dispatcher 경유 오픈 경로 확인
|
||||
- [x] 운영 모드 필터 테스트 18건 재통과
|
||||
- [x] 전체 테스트 436건 재통과
|
||||
|
||||
@@ -1115,6 +1115,8 @@
|
||||
VerticalAlignment="Center" Margin="0,0,5,0"/>
|
||||
<TextBlock x:Name="ModelLabel" FontSize="12.5"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
MaxWidth="280"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="9"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
|
||||
@@ -717,9 +717,12 @@ public partial class ChatWindow : Window
|
||||
if (SidebarChatMenu == null || SidebarCoworkMenu == null || SidebarCodeMenu == null)
|
||||
return;
|
||||
|
||||
SidebarChatMenu.Visibility = _activeTab == "Chat" ? Visibility.Visible : Visibility.Collapsed;
|
||||
SidebarCoworkMenu.Visibility = _activeTab == "Cowork" ? Visibility.Visible : Visibility.Collapsed;
|
||||
SidebarCodeMenu.Visibility = _activeTab == "Code" ? Visibility.Visible : Visibility.Collapsed;
|
||||
var chatVisible = _activeTab == "Chat" ? Visibility.Visible : Visibility.Collapsed;
|
||||
var coworkVisible = _activeTab == "Cowork" ? Visibility.Visible : Visibility.Collapsed;
|
||||
var codeVisible = _activeTab == "Code" ? Visibility.Visible : Visibility.Collapsed;
|
||||
if (SidebarChatMenu.Visibility != chatVisible) SidebarChatMenu.Visibility = chatVisible;
|
||||
if (SidebarCoworkMenu.Visibility != coworkVisible) SidebarCoworkMenu.Visibility = coworkVisible;
|
||||
if (SidebarCodeMenu.Visibility != codeVisible) SidebarCodeMenu.Visibility = codeVisible;
|
||||
|
||||
if (SidebarModeBadgeTitle != null && SidebarModeBadgeIcon != null)
|
||||
{
|
||||
@@ -2139,7 +2142,10 @@ public partial class ChatWindow : Window
|
||||
_ => "\uE8D7",
|
||||
};
|
||||
if (BtnPermission != null)
|
||||
BtnPermission.ToolTip = $"{summary.Description}\n기본값 {PermissionModeCatalog.ToDisplayLabel(summary.DefaultMode)} · override {summary.OverrideCount}개";
|
||||
{
|
||||
var operationMode = OperationModePolicy.Normalize(_settings.Settings.OperationMode);
|
||||
BtnPermission.ToolTip = $"{summary.Description}\n운영 모드: {operationMode}\n기본값 {PermissionModeCatalog.ToDisplayLabel(summary.DefaultMode)} · 예외 {summary.OverrideCount}개";
|
||||
}
|
||||
|
||||
if (!string.Equals(_lastPermissionBannerMode, perm, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -2275,10 +2281,11 @@ public partial class ChatWindow : Window
|
||||
lock (_convLock) currentConversation = _currentConversation;
|
||||
var summary = _appState.GetPermissionSummary(currentConversation);
|
||||
var mode = PermissionModeCatalog.NormalizeGlobalMode(summary.EffectiveMode);
|
||||
var operationMode = OperationModePolicy.Normalize(_settings.Settings.OperationMode);
|
||||
var overrides = summary.TopOverrides.Count > 0
|
||||
? string.Join(", ", summary.TopOverrides.Select(x => $"{x.Key}:{x.Value}"))
|
||||
? string.Join(", ", summary.TopOverrides.Take(3).Select(x => $"{x.Key}:{PermissionModeCatalog.ToDisplayLabel(x.Value)}"))
|
||||
: "없음";
|
||||
return $"현재 권한 모드: {PermissionModeCatalog.ToDisplayLabel(mode)} ({mode})\n설명: {summary.Description}\n기본값: {PermissionModeCatalog.ToDisplayLabel(summary.DefaultMode)} · override: {summary.OverrideCount}개\n상위 override: {overrides}";
|
||||
return $"현재 권한 모드: {PermissionModeCatalog.ToDisplayLabel(mode)}\n운영 모드: {operationMode}\n기본값: {PermissionModeCatalog.ToDisplayLabel(summary.DefaultMode)} · 예외 {summary.OverrideCount}개\n예외 미리보기: {overrides}";
|
||||
}
|
||||
|
||||
private void OpenPermissionPanelFromSlash(string command, string usageText)
|
||||
@@ -12972,13 +12979,19 @@ public partial class ChatWindow : Window
|
||||
_agentSettingsWindow = null;
|
||||
}
|
||||
|
||||
var win = new AgentSettingsWindow(_settings)
|
||||
{
|
||||
Owner = IsLoaded && IsVisible ? this : null,
|
||||
};
|
||||
var win = new AgentSettingsWindow(_settings);
|
||||
if (IsLoaded && IsVisible)
|
||||
win.Owner = this;
|
||||
_agentSettingsWindow = win;
|
||||
win.Closed += (_, _) => _agentSettingsWindow = null;
|
||||
try
|
||||
{
|
||||
win.Resources.MergedDictionaries.Add(Resources);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 리소스 병합 실패 시에도 설정창 자체는 열리도록 유지
|
||||
}
|
||||
|
||||
bool changed;
|
||||
try
|
||||
@@ -12988,8 +13001,12 @@ public partial class ChatWindow : Window
|
||||
catch
|
||||
{
|
||||
// 모달 창 오픈에 실패하면 일반 창으로라도 설정 접근을 보장
|
||||
try
|
||||
{
|
||||
win.Show();
|
||||
win.Activate();
|
||||
}
|
||||
catch { }
|
||||
return;
|
||||
}
|
||||
if (!changed)
|
||||
@@ -13005,10 +13022,13 @@ public partial class ChatWindow : Window
|
||||
}
|
||||
|
||||
public void OpenAgentSettingsFromExternal()
|
||||
{
|
||||
Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
Show();
|
||||
Activate();
|
||||
OpenAgentSettingsWindow();
|
||||
}, DispatcherPriority.Input);
|
||||
}
|
||||
|
||||
private void BtnInlineSettingsClose_Click(object sender, RoutedEventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user