AX Agent 계획 승인 UI를 테마에 맞게 정리하고 플랜 뷰어 상호작용을 개선

계획 확인 카드와 플랜 뷰어 하단 승인 영역을 AX Agent 테마 리소스 기준으로 다시 정리했다.

승인 카드의 표면/버튼/입력 패널 간격을 통일하고 플랜 뷰어에는 검토 안내 카드, 수정 요청 입력 패널, 테마 호버를 추가했다.

README.md와 docs/DEVELOPMENT.md에 2026-04-10 08:47 (KST) 기준 변경 이력을 반영했다.

검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ (경고 0 / 오류 0)
This commit is contained in:
2026-04-10 08:48:36 +09:00
parent d24c1f9edc
commit 36a9af8210
4 changed files with 1695 additions and 21 deletions

View File

@@ -7,6 +7,11 @@ Windows 전용 시맨틱 런처 & 워크스페이스 매니저
개발 참고: Claw Code 동등성 작업 추적 문서 개발 참고: Claw Code 동등성 작업 추적 문서
`docs/claw-code-parity-plan.md` `docs/claw-code-parity-plan.md`
- 업데이트: 2026-04-10 08:47 (KST)
- 계획 확인 UI를 AX Agent 테마에 맞춰 다시 정리했습니다. 채팅 안 승인 카드는 `LauncherBackground`/`ItemBackground`/`BorderColor`/`AccentColor`를 기준으로 표면, 버튼 모서리, 입력 패널 간격을 통일해 기본 컨트롤 느낌을 줄였습니다.
- 플랜 뷰어 창의 하단 승인 영역도 같은 시각 언어로 손봤습니다. 승인 전 안내 카드를 추가하고, 수정 입력 패널은 테마 배경과 테두리를 쓰도록 바꿨으며, 액션 버튼 호버도 `ItemHoverBackground` 중심으로 정리했습니다.
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0
- 업데이트: 2026-04-10 00:08 (KST) - 업데이트: 2026-04-10 00:08 (KST)
- `claude-code`와 비교했을 때 AX에 남아 있던 계획 선행과 후속 권유 톤을 더 줄였습니다. 기본 Cowork/Code 루프 안에 남아 있던 plan prelude/승인용 죽은 코드를 제거해, 별도 계획 생성 단계를 끼우지 않고 바로 모델+도구 실행으로 들어갑니다. - `claude-code`와 비교했을 때 AX에 남아 있던 계획 선행과 후속 권유 톤을 더 줄였습니다. 기본 Cowork/Code 루프 안에 남아 있던 plan prelude/승인용 죽은 코드를 제거해, 별도 계획 생성 단계를 끼우지 않고 바로 모델+도구 실행으로 들어갑니다.
- Code 최종 보고 재강제도 review 작업과 고영향 변경으로 좁혔습니다. 일반 수정은 변경 내용과 검증 근거가 충분하면 후속 계획이나 남은 리스크를 덧붙이도록 다시 유도하지 않고 마무리할 수 있습니다. - Code 최종 보고 재강제도 review 작업과 고영향 변경으로 좁혔습니다. 일반 수정은 변경 내용과 검증 근거가 충분하면 후속 계획이나 남은 리스크를 덧붙이도록 다시 유도하지 않고 마무리할 수 있습니다.

View File

@@ -1,6 +1,13 @@
# AX Copilot - 媛쒕컻 臾몄꽌 # AX Copilot - 媛쒕컻 臾몄꽌
## 계획 승인 UI 테마 정렬
- 업데이트: 2026-04-10 08:47 (KST)
- `ChatWindow.AgentStatusPresentation`의 계획 승인 카드를 AX Agent 테마 리소스 기반으로 다시 정리했습니다. 승인/수정/취소 버튼의 라운드, 간격, 입력 패널 배경을 `LauncherBackground`, `ItemBackground`, `BorderColor`, `AccentColor` 축으로 통일해 채팅 본문과 더 자연스럽게 이어지도록 조정했습니다.
- `PlanViewerWindow`의 승인 단계 UI도 같은 방향으로 손봤습니다. 승인 버튼 영역 앞에 검토 안내 카드를 추가하고, 수정 피드백 입력 패널은 테마 배경/테두리를 사용하며, 액션 버튼 호버는 단순 opacity 대신 `ItemHoverBackground` 계열로 반응하도록 바꿨습니다.
- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0
## claude-code식 계획/후속 권유 최소화 ## claude-code식 계획/후속 권유 최소화
- 업데이트: 2026-04-10 00:08 (KST) - 업데이트: 2026-04-10 00:08 (KST)

File diff suppressed because it is too large Load Diff

View File

@@ -859,11 +859,30 @@ internal sealed class PlanViewerWindow : Window
_btnPanel.Children.Clear(); _btnPanel.Children.Clear();
var accentBrush = Application.Current.TryFindResource("AccentColor") as Brush var accentBrush = Application.Current.TryFindResource("AccentColor") as Brush
?? new SolidColorBrush(Color.FromRgb(0x4B, 0x5E, 0xFC)); ?? new SolidColorBrush(Color.FromRgb(0x4B, 0x5E, 0xFC));
var secondaryText = Application.Current.TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
var accentColor = accentBrush is SolidColorBrush accentSolid ? accentSolid.Color : Color.FromRgb(0x4B, 0x5E, 0xFC);
var approveLabel = _uiExpressionLevel == "simple" ? "승인" : "승인 후 실행"; var approveLabel = _uiExpressionLevel == "simple" ? "승인" : "승인 후 실행";
var editLabel = _uiExpressionLevel == "simple" ? "수정" : "수정 피드백"; var editLabel = _uiExpressionLevel == "simple" ? "수정" : "수정 피드백";
var rejectLabel = _uiExpressionLevel == "simple" ? "취소" : "거부"; var rejectLabel = _uiExpressionLevel == "simple" ? "취소" : "거부";
_btnPanel.Children.Add(new Border
{
Background = new SolidColorBrush(Color.FromArgb(0x16, accentColor.R, accentColor.G, accentColor.B)),
BorderBrush = new SolidColorBrush(Color.FromArgb(0x40, accentColor.R, accentColor.G, accentColor.B)),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(10),
Padding = new Thickness(12, 8, 12, 8),
Margin = new Thickness(0, 0, 12, 0),
Child = new TextBlock
{
Text = "검토가 끝나면 바로 실행하거나 방향만 짧게 남길 수 있습니다.",
FontSize = 11.5,
Foreground = secondaryText,
TextWrapping = TextWrapping.Wrap,
}
});
var approveBtn = CreateActionButton("\uE73E", approveLabel, accentBrush, Brushes.White, true); var approveBtn = CreateActionButton("\uE73E", approveLabel, accentBrush, Brushes.White, true);
approveBtn.MouseLeftButtonUp += (_, _) => approveBtn.MouseLeftButtonUp += (_, _) =>
{ {
@@ -904,20 +923,31 @@ internal sealed class PlanViewerWindow : Window
private void ShowEditInput() private void ShowEditInput()
{ {
var itemBackground = Application.Current.TryFindResource("ItemBackground") as Brush
?? new SolidColorBrush(Color.FromRgb(0x2A, 0x2B, 0x40));
var launcherBackground = Application.Current.TryFindResource("LauncherBackground") as Brush
?? new SolidColorBrush(Color.FromRgb(0x1A, 0x1B, 0x2E));
var primaryText = Application.Current.TryFindResource("PrimaryText") as Brush ?? Brushes.White;
var secondaryText = Application.Current.TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
var borderBrush = Application.Current.TryFindResource("BorderColor") as Brush ?? Brushes.Gray;
var accentBrush = Application.Current.TryFindResource("AccentColor") as Brush
?? new SolidColorBrush(Color.FromRgb(0x4B, 0x5E, 0xFC));
var editPanel = new Border var editPanel = new Border
{ {
Margin = new Thickness(20, 0, 20, 12), Margin = new Thickness(20, 0, 20, 12),
Padding = new Thickness(12, 8, 12, 8), Padding = new Thickness(14, 12, 14, 12),
CornerRadius = new CornerRadius(10), CornerRadius = new CornerRadius(12),
Background = Application.Current.TryFindResource("ItemBackground") as Brush Background = itemBackground,
?? new SolidColorBrush(Color.FromRgb(0x2A, 0x2B, 0x40)), BorderBrush = borderBrush,
BorderThickness = new Thickness(1),
}; };
var editStack = new StackPanel(); var editStack = new StackPanel();
editStack.Children.Add(new TextBlock editStack.Children.Add(new TextBlock
{ {
Text = "수정 사항을 입력하세요:", Text = "어떤 방향으로 바꾸면 좋을지 짧게 남겨주세요.",
FontSize = 11.5, FontSize = 11.5,
Foreground = Application.Current.TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, Foreground = secondaryText,
Margin = new Thickness(0, 0, 0, 6), Margin = new Thickness(0, 0, 0, 6),
}); });
var textBox = new TextBox var textBox = new TextBox
@@ -927,29 +957,32 @@ internal sealed class PlanViewerWindow : Window
AcceptsReturn = true, AcceptsReturn = true,
TextWrapping = TextWrapping.Wrap, TextWrapping = TextWrapping.Wrap,
FontSize = 13, FontSize = 13,
Background = Application.Current.TryFindResource("LauncherBackground") as Brush Background = launcherBackground,
?? new SolidColorBrush(Color.FromRgb(0x1A, 0x1B, 0x2E)), Foreground = primaryText,
Foreground = Application.Current.TryFindResource("PrimaryText") as Brush ?? Brushes.White, CaretBrush = primaryText,
CaretBrush = Application.Current.TryFindResource("PrimaryText") as Brush ?? Brushes.White, BorderBrush = borderBrush,
BorderBrush = Application.Current.TryFindResource("BorderColor") as Brush ?? Brushes.Gray,
BorderThickness = new Thickness(1), BorderThickness = new Thickness(1),
Padding = new Thickness(10, 8, 10, 8), Padding = new Thickness(10, 8, 10, 8),
}; };
editStack.Children.Add(textBox); editStack.Children.Add(textBox);
var accentBrush = Application.Current.TryFindResource("AccentColor") as Brush var actionRow = new StackPanel
?? new SolidColorBrush(Color.FromRgb(0x4B, 0x5E, 0xFC)); {
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0, 8, 0, 0),
};
var sendBtn = new Border var sendBtn = new Border
{ {
Background = accentBrush, Background = accentBrush,
CornerRadius = new CornerRadius(8), CornerRadius = new CornerRadius(8),
Padding = new Thickness(14, 6, 14, 6), Padding = new Thickness(14, 6, 14, 6),
Margin = new Thickness(0, 8, 0, 0), Margin = new Thickness(0, 0, 8, 0),
Cursor = Cursors.Hand, Cursor = Cursors.Hand,
HorizontalAlignment = HorizontalAlignment.Right,
Child = new TextBlock Child = new TextBlock
{ {
Text = "전송", FontSize = 12.5, FontWeight = FontWeights.SemiBold, Foreground = Brushes.White, Text = "수정 요청 보내기", FontSize = 12.5, FontWeight = FontWeights.SemiBold, Foreground = Brushes.White,
}, },
}; };
sendBtn.MouseEnter += (s, _) => ((Border)s).Opacity = 0.85; sendBtn.MouseEnter += (s, _) => ((Border)s).Opacity = 0.85;
@@ -960,7 +993,36 @@ internal sealed class PlanViewerWindow : Window
if (string.IsNullOrEmpty(feedback)) return; if (string.IsNullOrEmpty(feedback)) return;
_tcs?.TrySetResult(feedback); _tcs?.TrySetResult(feedback);
}; };
editStack.Children.Add(sendBtn); actionRow.Children.Add(sendBtn);
var closeBtn = new Border
{
Background = Brushes.Transparent,
BorderBrush = borderBrush,
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8),
Padding = new Thickness(14, 6, 14, 6),
Cursor = Cursors.Hand,
Child = new TextBlock
{
Text = "닫기",
FontSize = 12.5,
FontWeight = FontWeights.SemiBold,
Foreground = secondaryText,
},
};
closeBtn.MouseEnter += (s, _) => ((Border)s).Background = itemBackground;
closeBtn.MouseLeave += (s, _) => ((Border)s).Background = Brushes.Transparent;
closeBtn.MouseLeftButtonUp += (_, _) =>
{
if (editPanel.Parent is Grid grid)
{
grid.Children.Remove(editPanel);
_btnPanel.Margin = new Thickness(20, 12, 20, 16);
}
};
actionRow.Children.Add(closeBtn);
editStack.Children.Add(actionRow);
editPanel.Child = editStack; editPanel.Child = editStack;
if (_btnPanel.Parent is Grid parentGrid) if (_btnPanel.Parent is Grid parentGrid)
@@ -1008,10 +1070,12 @@ internal sealed class PlanViewerWindow : Window
Brush textColor, bool filled) Brush textColor, bool filled)
{ {
var color = ((SolidColorBrush)borderColor).Color; var color = ((SolidColorBrush)borderColor).Color;
var hoverBg = Application.Current?.TryFindResource("ItemHoverBackground") as Brush
?? new SolidColorBrush(Color.FromArgb(0x18, 0xFF, 0xFF, 0xFF));
var btn = new Border var btn = new Border
{ {
CornerRadius = new CornerRadius(12), CornerRadius = new CornerRadius(14),
Padding = new Thickness(16, 8, 16, 8), Padding = new Thickness(16, 9, 16, 9),
Margin = new Thickness(4, 0, 4, 0), Margin = new Thickness(4, 0, 4, 0),
Cursor = Cursors.Hand, Cursor = Cursors.Hand,
Background = filled ? borderColor Background = filled ? borderColor
@@ -1033,8 +1097,20 @@ internal sealed class PlanViewerWindow : Window
Foreground = filled ? Brushes.White : textColor, Foreground = filled ? Brushes.White : textColor,
}); });
btn.Child = sp; btn.Child = sp;
btn.MouseEnter += (s, _) => ((Border)s).Opacity = 0.85; btn.MouseEnter += (s, _) =>
btn.MouseLeave += (s, _) => ((Border)s).Opacity = 1.0; {
var border = (Border)s;
border.Opacity = 0.96;
if (!filled)
border.Background = hoverBg;
};
btn.MouseLeave += (s, _) =>
{
var border = (Border)s;
border.Opacity = 1.0;
if (!filled)
border.Background = new SolidColorBrush(Color.FromArgb(0x18, color.R, color.G, color.B));
};
return btn; return btn;
} }