AX Agent 상태 UI 최소 노출 기준 정리 및 작업 요약 팝업 경량화
Some checks failed
Release Gate / gate (push) Has been cancelled

- Cowork/Code 보조 상태 스트립과 실행 로그 토글 영역의 패딩/폰트/간격을 추가 축소해 transcript 중심 흐름을 강화함
- 작업 요약 팝업에서 필터 칩과 과한 대시보드형 액션을 제거하고 마지막 실행 1건 중심 요약으로 재구성함
- 훅/백그라운드/최근 작업 카드의 밀도를 낮추고 기본 팝업에서 권한/백그라운드 현재 상태만 남기도록 최소 노출 기준으로 정리함
- README 및 DEVELOPMENT 문서에 2026-04-05 18:40 (KST) 기준 변경 이력과 parity 진척율을 반영함

검증:
- 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-05 16:10:51 +09:00
parent aa3de8a6fd
commit abd6928e4a
4 changed files with 89 additions and 240 deletions

View File

@@ -20148,22 +20148,11 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
});
panel.Children.Add(new TextBlock
{
Text = "현재 실행/권한/작업 흐름",
FontSize = 8.75,
Text = "현재 상태 요약",
FontSize = 8.5,
Foreground = secondaryText,
Margin = new Thickness(8, 0, 8, 3),
Margin = new Thickness(8, 0, 8, 5),
});
var taskFilterRow = new WrapPanel
{
Margin = new Thickness(6, 0, 6, 6),
};
taskFilterRow.Children.Add(CreateTaskSummaryFilterChip("all", "전체"));
taskFilterRow.Children.Add(CreateTaskSummaryFilterChip("permission", "권한"));
taskFilterRow.Children.Add(CreateTaskSummaryFilterChip("queue", "대기"));
taskFilterRow.Children.Add(CreateTaskSummaryFilterChip("tool", "도구"));
taskFilterRow.Children.Add(CreateTaskSummaryFilterChip("subagent", "서브"));
taskFilterRow.Children.Add(CreateTaskSummaryFilterChip("hook", "훅"));
panel.Children.Add(taskFilterRow);
ChatConversation? currentConversation;
lock (_convLock) currentConversation = _currentConversation;
@@ -20211,55 +20200,13 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
panel.Children.Add(currentRun);
}
var recentAgentRuns = _appState.GetRecentAgentRuns(2);
var recentAgentRuns = _appState.GetRecentAgentRuns(1);
if (recentAgentRuns.Count > 0)
{
var latestFailedRun = _appState.GetLatestFailedRun();
if (latestFailedRun != null)
{
panel.Children.Add(new Border
{
Background = BrushFromHex("#FEF2F2"),
BorderBrush = BrushFromHex("#FECACA"),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8),
Padding = new Thickness(8, 6, 8, 6),
Margin = new Thickness(6, 0, 6, 6),
Child = new StackPanel
{
Children =
{
new TextBlock
{
Text = $"최근 실패 · run {ShortRunId(latestFailedRun.RunId)}",
FontWeight = FontWeights.SemiBold,
Foreground = BrushFromHex("#991B1B"),
FontSize = 9.75,
},
new TextBlock
{
Text = $"{latestFailedRun.UpdatedAt:HH:mm:ss} · step {latestFailedRun.LastIteration}",
Margin = new Thickness(0, 2, 0, 0),
Foreground = BrushFromHex("#B45309"),
FontSize = 8.75,
},
new TextBlock
{
Text = string.IsNullOrWhiteSpace(latestFailedRun.Summary) ? "요약 없음" : latestFailedRun.Summary,
Margin = new Thickness(0, 3, 0, 0),
TextWrapping = TextWrapping.Wrap,
Foreground = secondaryText,
FontSize = 8.9,
}
}
}
});
}
panel.Children.Add(new TextBlock
{
Text = "최근 실행",
FontSize = 9.5,
Text = "마지막 실행",
FontSize = 9,
FontWeight = FontWeights.SemiBold,
Foreground = Brushes.DimGray,
Margin = new Thickness(8, 0, 8, 2),
@@ -20267,8 +20214,8 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
foreach (var run in recentAgentRuns)
{
var runEvents = GetExecutionEventsForRun(run.RunId);
var runFilePaths = GetExecutionEventFilePaths(run.RunId);
var runEvents = GetExecutionEventsForRun(run.RunId, 1);
var runFilePaths = GetExecutionEventFilePaths(run.RunId, 1);
var runDisplay = _appState.GetRunDisplay(run);
var runCardStack = new StackPanel
{
@@ -20279,22 +20226,22 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
Text = runDisplay.HeaderText,
FontWeight = FontWeights.SemiBold,
Foreground = GetRunStatusBrush(run.Status),
FontSize = 9.75,
FontSize = 9.5,
},
new TextBlock
{
Text = runDisplay.MetaText,
Margin = new Thickness(0, 2, 0, 0),
Margin = new Thickness(0, 1, 0, 0),
Foreground = secondaryText,
FontSize = 8.75,
FontSize = 8.25,
},
new TextBlock
{
Text = TruncateForStatus(runDisplay.SummaryText, 140),
Margin = new Thickness(0, 2, 0, 0),
Text = TruncateForStatus(runDisplay.SummaryText, 92),
Margin = new Thickness(0, 1.5, 0, 0),
TextWrapping = TextWrapping.Wrap,
Foreground = secondaryText,
FontSize = 8.9,
FontSize = 8.5,
}
}
};
@@ -20305,7 +20252,7 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
activitySummary.Children.Add(new TextBlock
{
Text = $"로그 {runEvents.Count} · 파일 {runFilePaths.Count}",
FontSize = 8.4,
FontSize = 8,
Foreground = secondaryText,
});
@@ -20328,9 +20275,9 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
Background = BrushFromHex("#F8FAFC"),
BorderBrush = BrushFromHex("#E2E8F0"),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8),
Padding = new Thickness(7, 5, 7, 5),
Margin = new Thickness(0, 6, 0, 0),
CornerRadius = new CornerRadius(7),
Padding = new Thickness(6, 4, 6, 4),
Margin = new Thickness(0, 5, 0, 0),
Child = activitySummary
});
}
@@ -20368,64 +20315,21 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
panel.Children.Add(new Border
{
Background = Brushes.White,
Background = popupBackground,
BorderBrush = BrushFromHex("#E5E7EB"),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8),
Padding = new Thickness(8, 5, 8, 5),
Margin = new Thickness(6, 0, 6, 5),
CornerRadius = new CornerRadius(7),
Padding = new Thickness(7, 5, 7, 5),
Margin = new Thickness(6, 0, 6, 4),
Child = runCardStack
});
}
if (_appState.GetLatestFailedRun() != null
&& CanRetryCurrentConversation())
{
var actionsPanel = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(6, 1, 6, 6),
};
var retryButton = CreateTaskSummaryActionButton(
"마지막 요청 다시 시도",
"#EEF2FF",
"#C7D2FE",
"#3730A3",
(_, _) =>
{
_taskSummaryPopup?.SetCurrentValue(Popup.IsOpenProperty, false);
RetryLastUserMessageFromConversation();
});
actionsPanel.Children.Add(retryButton);
if (_appState.ActiveTasks.Count > 0)
{
var runningFilterButton = CreateTaskSummaryActionButton(
"진행 중 대화만 보기",
"#DBEAFE",
"#93C5FD",
"#1D4ED8",
(_, _) =>
{
_runningOnlyFilter = true;
UpdateConversationRunningFilterUi();
PersistConversationListPreferences();
RefreshConversationList();
_taskSummaryPopup?.SetCurrentValue(Popup.IsOpenProperty, false);
},
trailingMargin: false);
runningFilterButton.Margin = new Thickness(2, 0, 0, 0);
actionsPanel.Children.Add(runningFilterButton);
}
panel.Children.Add(actionsPanel);
}
}
foreach (var task in FilterTaskSummaryItems(_appState.ActiveTasks).Take(6))
foreach (var task in FilterTaskSummaryItems(_appState.ActiveTasks).Take(3))
panel.Children.Add(BuildTaskSummaryCard(task, active: true));
foreach (var task in FilterTaskSummaryItems(_appState.RecentTasks).Take(6))
foreach (var task in FilterTaskSummaryItems(_appState.RecentTasks).Take(2))
panel.Children.Add(BuildTaskSummaryCard(task, active: false));
if (!FilterTaskSummaryItems(_appState.ActiveTasks).Any() && !FilterTaskSummaryItems(_appState.RecentTasks).Any())
@@ -21396,15 +21300,15 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
{
Text = "\uE756",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 10,
FontSize = 9,
Foreground = hook.Success ? BrushFromHex("#334155") : BrushFromHex("#991B1B"),
Margin = new Thickness(0, 0, 5, 0),
Margin = new Thickness(0, 0, 4, 0),
VerticalAlignment = VerticalAlignment.Center,
},
new TextBlock
{
Text = "훅 이벤트",
FontSize = 10,
Text = "훅",
FontSize = 9,
FontWeight = FontWeights.SemiBold,
Foreground = hook.Success ? BrushFromHex("#334155") : BrushFromHex("#991B1B"),
}
@@ -21413,7 +21317,7 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
hookCardStack.Children.Add(new TextBlock
{
Text = _appState.FormatHookEventLine(hook),
FontSize = 9.5,
FontSize = 8.75,
TextWrapping = TextWrapping.Wrap,
Foreground = hook.Success ? secondaryText : BrushFromHex("#991B1B"),
});
@@ -21460,9 +21364,9 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
Background = hook.Success ? BrushFromHex("#F8FAFC") : BrushFromHex("#FEF2F2"),
BorderBrush = hook.Success ? BrushFromHex("#E2E8F0") : BrushFromHex("#FECACA"),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8),
Padding = new Thickness(8, 5, 8, 5),
Margin = new Thickness(6, 0, 6, 4),
CornerRadius = new CornerRadius(7),
Padding = new Thickness(7, 4, 7, 4),
Margin = new Thickness(6, 0, 6, 3),
Child = hookCardStack
};
}
@@ -21480,15 +21384,15 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
{
Text = "\uE9F9",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 10,
FontSize = 9,
Foreground = BrushFromHex("#1D4ED8"),
Margin = new Thickness(0, 0, 5, 0),
Margin = new Thickness(0, 0, 4, 0),
VerticalAlignment = VerticalAlignment.Center,
},
new TextBlock
{
Text = $"실행 중인 백그라운드 작업 {activeBackgroundCount}",
FontSize = 10,
Text = $"백그라운드 {activeBackgroundCount}",
FontSize = 9,
Foreground = BrushFromHex("#1D4ED8"),
FontWeight = FontWeights.SemiBold,
}
@@ -21499,45 +21403,22 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
{
activeBackgroundStack.Children.Add(new TextBlock
{
Text = $"· {job.Title} · {TruncateForStatus(job.Summary, 52)}",
Margin = new Thickness(0, 3, 0, 0),
FontSize = 9.5,
Text = $"· {job.Title} · {TruncateForStatus(job.Summary, 40)}",
Margin = new Thickness(0, 2, 0, 0),
FontSize = 8.75,
Foreground = secondaryText,
TextWrapping = TextWrapping.Wrap,
});
}
var activeActionRow = new WrapPanel
{
Margin = new Thickness(0, 6, 0, 0),
};
var runningFilterButton = CreateTaskSummaryActionButton(
"진행 중 대화만 보기",
"#DBEAFE",
"#93C5FD",
"#1D4ED8",
(_, _) => ShowRunningConversationsOnly());
activeActionRow.Children.Add(runningFilterButton);
var subTaskButton = CreateTaskSummaryActionButton(
"서브 작업만 보기",
"#F8FAFC",
"#CBD5E1",
"#334155",
(_, _) => ShowSubAgentTasksOnly(),
trailingMargin: false);
activeActionRow.Children.Add(subTaskButton);
activeBackgroundStack.Children.Add(activeActionRow);
return new Border
{
Background = BrushFromHex("#EFF6FF"),
BorderBrush = BrushFromHex("#BFDBFE"),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8),
Padding = new Thickness(8, 5, 8, 5),
Margin = new Thickness(6, 0, 6, 5),
CornerRadius = new CornerRadius(7),
Padding = new Thickness(7, 4, 7, 4),
Margin = new Thickness(6, 0, 6, 4),
Child = activeBackgroundStack
};
}
@@ -21557,15 +21438,15 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
{
Text = "\uE823",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 10,
FontSize = 9,
Foreground = isFailed ? BrushFromHex("#991B1B") : BrushFromHex("#334155"),
Margin = new Thickness(0, 0, 5, 0),
Margin = new Thickness(0, 0, 4, 0),
VerticalAlignment = VerticalAlignment.Center,
},
new TextBlock
{
Text = $"{job.Title} · {GetTaskStatusLabel(job.Status)}",
FontSize = 10,
FontSize = 9,
FontWeight = FontWeights.SemiBold,
Foreground = isFailed ? BrushFromHex("#991B1B") : BrushFromHex("#334155"),
}
@@ -21573,43 +21454,18 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
});
jobCardStack.Children.Add(new TextBlock
{
Text = $"{job.UpdatedAt:HH:mm:ss} · {TruncateForStatus(job.Summary, 72)}",
FontSize = 9.5,
Text = $"{job.UpdatedAt:HH:mm:ss} · {TruncateForStatus(job.Summary, 48)}",
FontSize = 8.75,
TextWrapping = TextWrapping.Wrap,
Foreground = isFailed
? BrushFromHex("#991B1B")
: secondaryText,
});
var jobActionRow = new WrapPanel
{
Margin = new Thickness(0, 6, 0, 0),
};
var focusButton = CreateTaskSummaryActionButton(
"이 대화로 이동",
"#F8FAFC",
"#CBD5E1",
"#334155",
(_, _) =>
{
_taskSummaryPopup?.SetCurrentValue(Popup.IsOpenProperty, false);
FocusCurrentConversation();
});
jobActionRow.Children.Add(focusButton);
var subagentOnlyButton = CreateTaskSummaryActionButton(
"서브 작업만 보기",
"#F8FAFC",
"#CBD5E1",
"#334155",
(_, _) => ShowSubAgentTasksOnly());
jobActionRow.Children.Add(subagentOnlyButton);
if (string.Equals(job.Status, "failed", StringComparison.OrdinalIgnoreCase) && CanRetryCurrentConversation())
{
var retryBackgroundButton = CreateTaskSummaryActionButton(
"이 작업 다시 시도",
"다시 시도",
"#FEF2F2",
"#FCA5A5",
"#991B1B",
@@ -21619,11 +21475,10 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
RetryLastUserMessageFromConversation();
},
trailingMargin: false);
jobActionRow.Children.Add(retryBackgroundButton);
retryBackgroundButton.Margin = new Thickness(0, 5, 0, 0);
jobCardStack.Children.Add(retryBackgroundButton);
}
jobCardStack.Children.Add(jobActionRow);
return new Border
{
Background = string.Equals(job.Status, "failed", StringComparison.OrdinalIgnoreCase)
@@ -21633,9 +21488,9 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
? BrushFromHex("#FECACA")
: BrushFromHex("#E2E8F0"),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(8),
Padding = new Thickness(8, 5, 8, 5),
Margin = new Thickness(6, 0, 6, 4),
CornerRadius = new CornerRadius(7),
Padding = new Thickness(7, 4, 7, 4),
Margin = new Thickness(6, 0, 6, 3),
Child = jobCardStack
};
}
@@ -21807,33 +21662,15 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
private void AddTaskSummaryBackgroundSection(StackPanel panel)
{
var activeBackgroundJobs = _appState.GetActiveBackgroundJobs(2);
var recentBackgroundJobs = _appState.GetRecentBackgroundJobs(2);
var activeBackgroundCount = _appState.GetBackgroundJobSummary().ActiveCount;
if (activeBackgroundCount > 0)
panel.Children.Add(BuildActiveBackgroundSummaryCard(activeBackgroundJobs, activeBackgroundCount));
if (recentBackgroundJobs.Count == 0)
return;
panel.Children.Add(new TextBlock
{
Text = "최근 백그라운드 작업",
FontSize = 11,
FontWeight = FontWeights.SemiBold,
Foreground = Brushes.DimGray,
Margin = new Thickness(10, 0, 10, 4),
});
foreach (var job in recentBackgroundJobs)
panel.Children.Add(BuildRecentBackgroundJobCard(job));
}
private void AddTaskSummaryObservabilitySections(StackPanel panel, ChatConversation? currentConversation)
{
AddTaskSummaryPermissionSection(panel, currentConversation);
AddTaskSummaryPermissionHistorySection(panel);
AddTaskSummaryHookSection(panel);
AddTaskSummaryBackgroundSection(panel);
}