AX Agent claw-code 진척율 문서화 및 메시지 축 단순화
Some checks failed
Release Gate / gate (push) Has been cancelled

- claw-code 대비 AX Agent 진척율을 README, DEVELOPMENT, parity 계획 문서에 수치로 기록

- 핵심 엔진 영향 설정 최소화 원칙을 정리하고 계획 모드 잔재 노출을 추가로 축소

- ChatWindow 메시지 버블과 좌측 대화 목록 카드를 더 얇은 밀도로 조정해 claw-code식 읽기 축에 가깝게 정리

- 검증: 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 14:38:03 +09:00
parent 22eebc13d9
commit d99b46e3e2
5 changed files with 46 additions and 93 deletions

View File

@@ -7,6 +7,12 @@ Windows 전용 시맨틱 런처 & 워크스페이스 매니저
개발 참고: Claw Code 동등성 작업 추적 문서 개발 참고: Claw Code 동등성 작업 추적 문서
`docs/claw-code-parity-plan.md` `docs/claw-code-parity-plan.md`
- 업데이트: 2026-04-05 16:55 (KST)
- `claw-code` 대비 AX Agent 추정 진척율 기준선을 문서에 남겼습니다. 현재 기준은 핵심 엔진 `82%`, 채팅 메인 UI `68%`, Cowork/Code 상태 UX `63%`, 내부 설정 연결 `88%`, 전체 AX Agent 동등 품질 `74%`입니다.
- 메인 핵심 엔진 로직에 직접 영향을 주는 설정은 최소화 원칙으로 다시 검토하기 시작했습니다. 이미 실질 선택지가 사라진 `계획 모드` 계열은 사용자 노출을 더 줄였고, 남은 엔진성 설정은 개발자 탭 중심으로 계속 정리합니다.
- 메시지 행과 좌측 대화 목록도 `claw-code` 방향으로 다시 단순화했습니다. 사용자/assistant 버블의 패딩, 라운드, 메타 텍스트를 줄였고, 대화 목록의 실행 상태도 배지 카드보다 얇은 텍스트 요약 중심으로 바꿔 읽는 축이 먼저 보이도록 눌렀습니다.
- 검증 예정: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\`
- 업데이트: 2026-04-05 16:02 (KST) - 업데이트: 2026-04-05 16:02 (KST)
- `document_plan` 후속 실행 분기를 `claw-code` 기준으로 다시 보강했습니다. 이제 문서 플래너 출력에서 body 골격과 즉시 실행 지시를 깨진 문자열 비교에 의존하지 않고 안정적으로 추출해, `html_create / document_assemble / docx_create / markdown_create` 후속 호출 유도가 실제로 이어집니다. - `document_plan` 후속 실행 분기를 `claw-code` 기준으로 다시 보강했습니다. 이제 문서 플래너 출력에서 body 골격과 즉시 실행 지시를 깨진 문자열 비교에 의존하지 않고 안정적으로 추출해, `html_create / document_assemble / docx_create / markdown_create` 후속 호출 유도가 실제로 이어집니다.
- 코워크 문서형 작업은 설정이 `planMode=off`여도 내부적으로 `always` 플랜 경로를 타도록 보정했습니다. 그래서 문서/보고서/제안서 요청은 먼저 계획을 세우고, 그 계획을 바탕으로 실제 문서 생성 단계까지 이어가도록 정리했습니다. - 코워크 문서형 작업은 설정이 `planMode=off`여도 내부적으로 `always` 플랜 경로를 타도록 보정했습니다. 그래서 문서/보고서/제안서 요청은 먼저 계획을 세우고, 그 계획을 바탕으로 실제 문서 생성 단계까지 이어가도록 정리했습니다.

View File

@@ -1,5 +1,8 @@
# AX Copilot - 媛쒕컻 臾몄꽌 # AX Copilot - 媛쒕컻 臾몄꽌
- Document update: 2026-04-05 16:55 (KST) - Recorded the current `claw-code` parity estimate for AX Agent: core execution engine `82%`, main chat UI `68%`, Cowork/Code status UX `63%`, internal settings linkage `88%`, overall AX Agent parity `74%`.
- Document update: 2026-04-05 16:55 (KST) - Added an engine-settings review rule for ongoing cleanup: settings that materially alter the main execution route should be minimized, kept developer-only when necessary, or removed from user-facing surfaces when they no longer represent real runtime choices. Plan-mode remnants were reduced further as part of this pass.
- Document update: 2026-04-05 16:55 (KST) - Simplified AX Agent message rows and sidebar conversation items toward the `claw-code` reading model. Message bubbles now use tighter padding/radius/meta text, and conversation rows now prefer lightweight running/failure summary text over heavier success/failure badge cards.
- Document update: 2026-04-05 16:02 (KST) - Fixed the Cowork document execution handoff around `document_plan`. The loop no longer depends on broken localized marker strings to detect the scaffold/body block or the immediate-next-step hint; it now extracts body markers robustly and resolves the correct follow-up tool (`html_create`, `document_assemble`, `docx_create`, `markdown_create`) before re-prompting the model. - Document update: 2026-04-05 16:02 (KST) - Fixed the Cowork document execution handoff around `document_plan`. The loop no longer depends on broken localized marker strings to detect the scaffold/body block or the immediate-next-step hint; it now extracts body markers robustly and resolves the correct follow-up tool (`html_create`, `document_assemble`, `docx_create`, `markdown_create`) before re-prompting the model.
- Document update: 2026-04-05 16:02 (KST) - Added `ResolveEffectivePlanMode(...)` so Cowork document/content tasks automatically use the `always` plan path even when the persisted plan mode is `off`. This brings Cowork closer to the `claw-code` expectation of plan-first execution for document-heavy work. - Document update: 2026-04-05 16:02 (KST) - Added `ResolveEffectivePlanMode(...)` so Cowork document/content tasks automatically use the `always` plan path even when the persisted plan mode is `off`. This brings Cowork closer to the `claw-code` expectation of plan-first execution for document-heavy work.
- Document update: 2026-04-05 16:02 (KST) - Strengthened `BuildCoworkSystemPrompt()` so document/report/proposal/manual requests must produce an execution plan first and are not considered complete until a real output file path has been created or updated. - Document update: 2026-04-05 16:02 (KST) - Strengthened `BuildCoworkSystemPrompt()` so document/report/proposal/manual requests must produce an execution plan first and are not considered complete until a real output file path has been created or updated.

View File

@@ -7,6 +7,9 @@
- Updated: 2026-04-05 15:34 (KST) - Updated: 2026-04-05 15:34 (KST)
- Rebased the AX Agent improvement plan on actual `claw-code` runtime files instead of earlier AX snapshots. The reference spine is now `src/bootstrap/state.ts -> src/bridge/initReplBridge.ts -> src/bridge/sessionRunner.ts -> src/screens/REPL.tsx -> src/components/Messages.tsx -> src/components/StatusLine.tsx`. - Rebased the AX Agent improvement plan on actual `claw-code` runtime files instead of earlier AX snapshots. The reference spine is now `src/bootstrap/state.ts -> src/bridge/initReplBridge.ts -> src/bridge/sessionRunner.ts -> src/screens/REPL.tsx -> src/components/Messages.tsx -> src/components/StatusLine.tsx`.
- AX Agent work should follow that same quality order: state first, execution second, render last. UI-only fixes that bypass state/execution should be treated as temporary. - AX Agent work should follow that same quality order: state first, execution second, render last. UI-only fixes that bypass state/execution should be treated as temporary.
- Updated: 2026-04-05 16:55 (KST)
- Current estimated parity vs `claw-code`: core execution engine `82%`, main chat UI `68%`, Cowork/Code status UX `63%`, internal settings linkage `88%`, overall AX Agent `74%`.
- Engine-affecting settings should be handled conservatively during parity work. If a setting changes the main execution route, approval flow, or recovery behavior without representing a stable real-world user choice, it should be moved to developer-only UI or removed from user-facing surfaces.
## Preserved History (Summary) ## Preserved History (Summary)
- Core loop guards and post-tool verification gates are already partially implemented. - Core loop guards and post-tool verification gates are already partially implemented.

View File

@@ -1888,6 +1888,7 @@
<Button x:Name="BtnInlinePlanMode" <Button x:Name="BtnInlinePlanMode"
Style="{StaticResource OutlineHoverBtn}" Style="{StaticResource OutlineHoverBtn}"
Visibility="Collapsed" Visibility="Collapsed"
IsEnabled="False"
Margin="0,0,6,6" Margin="0,0,6,6"
Padding="9,4" Padding="9,4"
Click="BtnInlinePlanMode_Click"/> Click="BtnInlinePlanMode_Click"/>
@@ -2873,6 +2874,7 @@
</StackPanel> </StackPanel>
<ComboBox x:Name="CmbOverlayPlanMode" <ComboBox x:Name="CmbOverlayPlanMode"
Grid.Column="1" Grid.Column="1"
Visibility="Collapsed"
Style="{StaticResource OverlayComboBox}" Style="{StaticResource OverlayComboBox}"
SelectionChanged="CmbOverlayPlanMode_SelectionChanged"> SelectionChanged="CmbOverlayPlanMode_SelectionChanged">
<ComboBoxItem Content="계획 · 끄기" Tag="off"/> <ComboBoxItem Content="계획 · 끄기" Tag="off"/>
@@ -4498,7 +4500,7 @@
Style="{StaticResource ToggleSwitch}"/> Style="{StaticResource ToggleSwitch}"/>
</Grid> </Grid>
</Border> </Border>
<Border x:Name="OverlayTogglePlanModeTools" Style="{StaticResource OverlayAdvancedToggleRowStyle}"> <Border x:Name="OverlayTogglePlanModeTools" Style="{StaticResource OverlayAdvancedToggleRowStyle}" Visibility="Collapsed">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>

View File

@@ -3227,16 +3227,16 @@ public partial class ChatWindow : Window
var border = new Border var border = new Border
{ {
Background = isSelected Background = isSelected
? new SolidColorBrush(Color.FromArgb(0x14, 0x4B, 0x5E, 0xFC)) ? new SolidColorBrush(Color.FromArgb(0x10, 0x4B, 0x5E, 0xFC))
: Brushes.Transparent, : Brushes.Transparent,
CornerRadius = new CornerRadius(7), CornerRadius = new CornerRadius(6),
Padding = new Thickness(8, 5, 8, 5), Padding = new Thickness(7, 4, 7, 4),
Margin = isBranch ? new Thickness(14, 1, 0, 1) : new Thickness(0, 1, 0, 1), Margin = isBranch ? new Thickness(12, 1, 0, 1) : new Thickness(0, 1, 0, 1),
Cursor = Cursors.Hand Cursor = Cursors.Hand
}; };
var grid = new Grid(); var grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(20) }); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(18) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
@@ -3255,7 +3255,7 @@ public partial class ChatWindow : Window
{ {
Text = iconText, Text = iconText,
FontFamily = new FontFamily("Segoe MDL2 Assets"), FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 11, FontSize = 10,
Foreground = iconBrush, Foreground = iconBrush,
VerticalAlignment = VerticalAlignment.Center VerticalAlignment = VerticalAlignment.Center
}; };
@@ -3270,7 +3270,7 @@ public partial class ChatWindow : Window
var title = new TextBlock var title = new TextBlock
{ {
Text = item.Title, Text = item.Title,
FontSize = 11, FontSize = 10.5,
FontWeight = isSelected ? FontWeights.SemiBold : FontWeights.Normal, FontWeight = isSelected ? FontWeights.SemiBold : FontWeights.Normal,
Foreground = titleColor, Foreground = titleColor,
TextTrimming = TextTrimming.CharacterEllipsis TextTrimming = TextTrimming.CharacterEllipsis
@@ -3278,7 +3278,7 @@ public partial class ChatWindow : Window
var date = new TextBlock var date = new TextBlock
{ {
Text = item.UpdatedAtText, Text = item.UpdatedAtText,
FontSize = 8.5, FontSize = 8,
Foreground = dateColor, Foreground = dateColor,
Margin = new Thickness(0, 1, 0, 0) Margin = new Thickness(0, 1, 0, 0)
}; };
@@ -3286,16 +3286,7 @@ public partial class ChatWindow : Window
stack.Children.Add(date); stack.Children.Add(date);
if (item.IsRunning) if (item.IsRunning)
{ {
stack.Children.Add(new Border stack.Children.Add(new TextBlock
{
Background = BrushFromHex("#EEF2FF"),
BorderBrush = BrushFromHex("#C7D2FE"),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(6),
Padding = new Thickness(4, 1, 4, 1),
Margin = new Thickness(0, 2, 0, 0),
HorizontalAlignment = HorizontalAlignment.Left,
Child = new TextBlock
{ {
Text = _appState.ActiveTasks.Count > 0 Text = _appState.ActiveTasks.Count > 0
? $"진행 중 {_appState.ActiveTasks.Count}" ? $"진행 중 {_appState.ActiveTasks.Count}"
@@ -3303,72 +3294,21 @@ public partial class ChatWindow : Window
FontSize = 8, FontSize = 8,
FontWeight = FontWeights.Medium, FontWeight = FontWeights.Medium,
Foreground = BrushFromHex("#4F46E5"), Foreground = BrushFromHex("#4F46E5"),
} Margin = new Thickness(0, 2, 0, 0),
}); });
} }
if (item.AgentRunCount > 0) if (item.AgentRunCount > 0)
{ {
var runSummaryPanel = new DockPanel
{
Margin = new Thickness(0, 2, 0, 0),
LastChildFill = true,
};
if (item.FailedAgentRunCount > 0 && item.LastFailedAt.HasValue)
{
var failedBadge = new Border
{
Background = BrushFromHex("#FEF2F2"),
BorderBrush = BrushFromHex("#FEE2E2"),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(6),
Padding = new Thickness(4, 1, 4, 1),
Margin = new Thickness(0, 0, 4, 0),
VerticalAlignment = VerticalAlignment.Center,
Child = new TextBlock
{
Text = $"실패 {FormatDate(item.LastFailedAt.Value)}",
FontSize = 8,
FontWeight = FontWeights.Medium,
Foreground = BrushFromHex("#B91C1C"),
}
};
DockPanel.SetDock(failedBadge, Dock.Right);
runSummaryPanel.Children.Add(failedBadge);
}
else if (item.LastCompletedAt.HasValue)
{
var completedBadge = new Border
{
Background = BrushFromHex("#ECFDF5"),
BorderBrush = BrushFromHex("#DCFCE7"),
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(6),
Padding = new Thickness(4, 1, 4, 1),
Margin = new Thickness(0, 0, 4, 0),
VerticalAlignment = VerticalAlignment.Center,
Child = new TextBlock
{
Text = $"성공 {FormatDate(item.LastCompletedAt.Value)}",
FontSize = 8,
FontWeight = FontWeights.Medium,
Foreground = BrushFromHex("#166534"),
}
};
DockPanel.SetDock(completedBadge, Dock.Right);
runSummaryPanel.Children.Add(completedBadge);
}
var runSummaryText = new TextBlock var runSummaryText = new TextBlock
{ {
Text = item.FailedAgentRunCount > 0 Text = item.FailedAgentRunCount > 0
? $"실행 {item.AgentRunCount} · 실패 {item.FailedAgentRunCount} · {TruncateForStatus(item.LastAgentRunSummary, 28)}" ? $"실패 {item.FailedAgentRunCount} · {TruncateForStatus(item.LastAgentRunSummary, 26)}"
: $"실행 {item.AgentRunCount} · {TruncateForStatus(item.LastAgentRunSummary, 32)}", : $"실행 {item.AgentRunCount} · {TruncateForStatus(item.LastAgentRunSummary, 28)}",
FontSize = 8.25, FontSize = 8.25,
Foreground = item.FailedAgentRunCount > 0 Foreground = item.FailedAgentRunCount > 0
? BrushFromHex("#B91C1C") ? BrushFromHex("#B91C1C")
: (TryFindResource("SecondaryText") as Brush ?? Brushes.Gray), : (TryFindResource("SecondaryText") as Brush ?? Brushes.Gray),
Margin = new Thickness(0, 1, 0, 0), Margin = new Thickness(0, 2, 0, 0),
TextTrimming = TextTrimming.CharacterEllipsis TextTrimming = TextTrimming.CharacterEllipsis
}; };
if (!string.IsNullOrWhiteSpace(item.LastAgentRunSummary)) if (!string.IsNullOrWhiteSpace(item.LastAgentRunSummary))
@@ -3377,8 +3317,7 @@ public partial class ChatWindow : Window
? $"최근 실패 포함\n{item.LastAgentRunSummary}" ? $"최근 실패 포함\n{item.LastAgentRunSummary}"
: item.LastAgentRunSummary; : item.LastAgentRunSummary;
} }
runSummaryPanel.Children.Add(runSummaryText); stack.Children.Add(runSummaryText);
stack.Children.Add(runSummaryPanel);
} }
Grid.SetColumn(stack, 1); Grid.SetColumn(stack, 1);
grid.Children.Add(stack); grid.Children.Add(stack);
@@ -4447,7 +4386,7 @@ public partial class ChatWindow : Window
{ {
HorizontalAlignment = HorizontalAlignment.Right, HorizontalAlignment = HorizontalAlignment.Right,
MaxWidth = GetMessageMaxWidth(), MaxWidth = GetMessageMaxWidth(),
Margin = new Thickness(172, 2, 16, 2), Margin = new Thickness(196, 2, 12, 2),
}; };
var bubble = new Border var bubble = new Border
@@ -4455,16 +4394,16 @@ public partial class ChatWindow : Window
Background = userBubbleBg, Background = userBubbleBg,
BorderBrush = borderBrush, BorderBrush = borderBrush,
BorderThickness = new Thickness(1), BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(13), CornerRadius = new CornerRadius(12),
Padding = new Thickness(12, 8, 12, 8), Padding = new Thickness(11, 7, 11, 7),
Child = new TextBlock Child = new TextBlock
{ {
Text = content, Text = content,
TextAlignment = TextAlignment.Left, TextAlignment = TextAlignment.Left,
FontSize = 12, FontSize = 11.5,
Foreground = primaryText, Foreground = primaryText,
TextWrapping = TextWrapping.Wrap, TextWrapping = TextWrapping.Wrap,
LineHeight = 19, LineHeight = 18,
} }
}; };
wrapper.Children.Add(bubble); wrapper.Children.Add(bubble);
@@ -4492,7 +4431,7 @@ public partial class ChatWindow : Window
userBottomBar.Children.Add(new TextBlock userBottomBar.Children.Add(new TextBlock
{ {
Text = timestamp.ToString("HH:mm"), Text = timestamp.ToString("HH:mm"),
FontSize = 8.5, Opacity = 0.46, FontSize = 8, Opacity = 0.42,
Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
HorizontalAlignment = HorizontalAlignment.Right, HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,
@@ -4530,19 +4469,19 @@ public partial class ChatWindow : Window
{ {
HorizontalAlignment = HorizontalAlignment.Left, HorizontalAlignment = HorizontalAlignment.Left,
MaxWidth = GetMessageMaxWidth(), MaxWidth = GetMessageMaxWidth(),
Margin = new Thickness(6, 2, 180, 2) Margin = new Thickness(4, 2, 164, 2)
}; };
if (animate) ApplyMessageEntryAnimation(container); if (animate) ApplyMessageEntryAnimation(container);
// AI 에이전트 이름 + 아이콘 // AI 에이전트 이름 + 아이콘
var (agentName, _, _) = GetAgentIdentity(); var (agentName, _, _) = GetAgentIdentity();
var headerSp = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(3, 0, 0, 1) }; var headerSp = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(2, 0, 0, 1) };
var iconBlock = new TextBlock var iconBlock = new TextBlock
{ {
Text = "\uE945", Text = "\uE945",
FontFamily = new FontFamily("Segoe MDL2 Assets"), FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 7.5, FontSize = 7,
Foreground = secondaryText, Foreground = secondaryText,
VerticalAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,
}; };
@@ -4551,7 +4490,7 @@ public partial class ChatWindow : Window
headerSp.Children.Add(new TextBlock headerSp.Children.Add(new TextBlock
{ {
Text = agentName, Text = agentName,
FontSize = 8.5, FontSize = 8,
FontWeight = FontWeights.Normal, FontWeight = FontWeights.Normal,
Foreground = secondaryText, Foreground = secondaryText,
Margin = new Thickness(3, 0, 0, 0), Margin = new Thickness(3, 0, 0, 0),
@@ -4564,8 +4503,8 @@ public partial class ChatWindow : Window
Background = assistantBubbleBg, Background = assistantBubbleBg,
BorderBrush = borderBrush, BorderBrush = borderBrush,
BorderThickness = new Thickness(1), BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(13), CornerRadius = new CornerRadius(12),
Padding = new Thickness(12, 8, 12, 8), Padding = new Thickness(11, 7, 11, 7),
}; };
var contentStack = new StackPanel(); var contentStack = new StackPanel();