AX Agent 계획 승인 흐름과 상태선 표현 계층 정리
Some checks failed
Release Gate / gate (push) Has been cancelled

- 계획 승인 기본 흐름을 transcript inline 우선 구조로 더 정리하고, 계획 버튼은 저장된 계획을 여는 상세 보기 성격으로 분리했습니다.

- OperationalStatusPresentationState를 확장해 runtime badge, compact strip, quick strip의 문구·강조색·노출 여부를 한 번에 계산하도록 통합했습니다.

- ChatWindow 상태선/quick strip/status token 로직을 StatusPresentation partial로 분리해 메인 창 코드의 직접 분기와 렌더 책임을 줄였습니다.

- 문서 이력(README, DEVELOPMENT)을 2026-04-06 01:37 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-06 07:17:16 +09:00
parent 95e40df354
commit 90bd77f945
7 changed files with 290 additions and 165 deletions

View File

@@ -1,3 +1,4 @@
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
@@ -259,6 +260,8 @@ public partial class ChatWindow
await Dispatcher.InvokeAsync(() =>
{
_pendingPlanSummary = planSummary;
_pendingPlanSteps = steps.ToList();
EnsurePlanViewerWindow();
_planViewerWindow?.LoadPlan(planSummary, steps, tcs);
ShowPlanButton(true);
@@ -268,7 +271,11 @@ public partial class ChatWindow
var completed = await Task.WhenAny(tcs.Task, Task.Delay(TimeSpan.FromMinutes(5)));
if (completed != tcs.Task)
{
await Dispatcher.InvokeAsync(() => _planViewerWindow?.Hide());
await Dispatcher.InvokeAsync(() =>
{
_planViewerWindow?.Hide();
ResetPendingPlanPresentation();
});
return "취소";
}
@@ -290,12 +297,15 @@ public partial class ChatWindow
await Dispatcher.InvokeAsync(() =>
{
_planViewerWindow?.SwitchToExecutionMode();
_planViewerWindow?.Hide();
});
}
else
{
await Dispatcher.InvokeAsync(() => _planViewerWindow?.Hide());
await Dispatcher.InvokeAsync(() =>
{
_planViewerWindow?.Hide();
ResetPendingPlanPresentation();
});
}
return agentDecision;
@@ -355,8 +365,18 @@ public partial class ChatWindow
planBtn.MouseLeftButtonUp += (_, e) =>
{
e.Handled = true;
if (string.IsNullOrWhiteSpace(_pendingPlanSummary) && _pendingPlanSteps.Count == 0)
return;
EnsurePlanViewerWindow();
if (_planViewerWindow != null && IsWindowAlive(_planViewerWindow))
{
if (string.IsNullOrWhiteSpace(_planViewerWindow.PlanText)
|| _planViewerWindow.PlanText != (_pendingPlanSummary ?? string.Empty)
|| !_planViewerWindow.Steps.SequenceEqual(_pendingPlanSteps))
{
_planViewerWindow.LoadPlanPreview(_pendingPlanSummary ?? "", _pendingPlanSteps);
}
_planViewerWindow.Show();
_planViewerWindow.Activate();
}
@@ -377,6 +397,13 @@ public partial class ChatWindow
{
if (_planViewerWindow != null && IsWindowAlive(_planViewerWindow))
_planViewerWindow.MarkComplete();
ResetPendingPlanPresentation();
}
private void ResetPendingPlanPresentation()
{
_pendingPlanSummary = null;
_pendingPlanSteps.Clear();
ShowPlanButton(false);
}