From 73a41111003810ea79ed476e6ea6ba4e6f314a47 Mon Sep 17 00:00:00 2001 From: lacvet Date: Sat, 4 Apr 2026 15:03:22 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B6=8C=ED=95=9C=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=EA=B0=92=20Deny=20=EC=A0=95=EB=A0=AC:=20=EC=B4=88=EA=B8=B0=20?= =?UTF-8?q?=EC=A0=95=EC=B1=85/=EC=83=81=ED=83=9C/=EC=8A=AC=EB=9E=98?= =?UTF-8?q?=EC=8B=9C=20=EA=B0=80=EC=9D=B4=EB=93=9C=20=EC=9D=BC=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AppSettings 기본 권한(FilePermission, DefaultAgentPermission)을 Deny로 변경 - AppStateService 권한 상태/요약 기본값을 Deny로 동기화 - /permissions,/allowed-tools 사용법 문구를 none|passive|active|plan|fullauto|silent 체계로 정리 - AppStateServiceTests 추가 및 빌드/회귀 테스트/문서 이력(2026-04-04 15:02 KST) 반영 --- README.md | 3 +- docs/DEVELOPMENT.md | 31 +++++++++++++++++++ .../Services/AppStateServiceTests.cs | 14 +++++++++ src/AxCopilot/Models/AppSettings.cs | 26 ++++++++++++++-- src/AxCopilot/Services/AppStateService.cs | 6 ++-- src/AxCopilot/Views/ChatWindow.xaml.cs | 8 ++--- 6 files changed, 77 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 64aa07b..ac28bcd 100644 --- a/README.md +++ b/README.md @@ -222,7 +222,7 @@ public class MyHandler : IActionHandler ### v0.7.3 — AX Agent 권한 코어 재구성 + 입력 계층 정리 -업데이트: 2026-04-04 14:57 (KST) +업데이트: 2026-04-04 15:02 (KST) | 분류 | 내용 | |------|------| @@ -288,6 +288,7 @@ public class MyHandler : IActionHandler | 로직 안정화 회귀 보강 | `ContextCondenserTests`와 `LlmRuntimeOverrideTests`를 보강해 compact 실동작과 vLLM 암호화 API키/SSL 우회 해석 규칙을 회귀 검증 | | 권한 패턴 구문 호환성 보강 | 권한 규칙 파서를 `tool@pattern` 외 `tool|pattern`, `tool(pattern)`도 해석하도록 확장하고 deny→allow 우선순위 회귀를 보강 | | 권한 모드 별칭 정합 보강 | `/permissions`, `/allowed-tools`에서 `none/passive/active/planning/fullauto/silent` 별칭을 지원하고 카탈로그 정규화와 일치시킴 | +| 권한 기본값 정책 정렬 | 신규/초기 상태의 기본 권한을 `활용하지 않음(Deny)`으로 변경하고 AppState 기본/요약 상태와 slash 사용 가이드를 동일 체계로 정렬 | | Slash palette 상태 분리 시작 | `ChatWindow`에 몰려 있던 slash 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편 기반 마련 | | 런처 이미지 미리보기 추가 | `#` 클립보드 이미지 항목에서 `Shift+Enter`로 전용 미리보기 창을 열고, 줌·원본 해상도 확인·PNG/JPEG/BMP 저장·클립보드 복사를 지원 | | 검증 | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed | diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index f8c79e8..8069737 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -3553,3 +3553,34 @@ else: ### 4) 품질 게이트 - `dotnet build src/AxCopilot/AxCopilot.csproj -c Debug -p:UseSharedCompilation=false -nodeReuse:false` 통과 (경고 0, 오류 0). - `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj --filter "FullyQualifiedName~PermissionModeCatalogTests|FullyQualifiedName~OperationModePolicyTests|FullyQualifiedName~ChatWindowSlashPolicyTests"` 통과 (88 passed, 0 failed). + +## 2026-04-04 추가 진행 기록 (연속 실행 38차: 권한 기본값 정책 정렬) + +업데이트: 2026-04-04 15:02 (KST) + +### 1) 권한 기본값을 Deny로 정렬 +- `AppSettings.LlmSettings`의 기본값을 변경: + - `FilePermission`: `Default` → `Deny` + - `DefaultAgentPermission`: `Default` → `Deny` +- 목적: 신규 설치/초기 상태에서 요청하신 기본 정책(활용하지 않음)으로 시작. + +### 2) 앱 상태 기본값 동기화 +- `AppStateService.PermissionPolicyState.FilePermission` 기본값을 `Deny`로 변경. +- `AppStateService.PermissionSummaryState` 기본값(`EffectiveMode`, `DefaultMode`)도 `Deny`로 변경. + +### 3) Slash 권한 사용 가이드 문구 정렬 +- `/permissions`, `/allowed-tools`의 사용법 문구를 실사용 별칭 기준으로 정리: + - `none|passive|active|plan|fullauto|silent|status` + +### 4) 회귀 테스트 보강 +- `AppStateServiceTests`에 신규 테스트 추가: + - `LoadFromSettings_DefaultPermission_ShouldBeDeny` +- 검증 범위: + - `AppStateServiceTests` + - `PermissionModeCatalogTests` + - `ChatWindowSlashPolicyTests` + - `OperationModePolicyTests` + +### 5) 품질 게이트 +- `dotnet build src/AxCopilot/AxCopilot.csproj -c Debug -p:UseSharedCompilation=false -nodeReuse:false` 통과 (경고 0, 오류 0). +- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj --filter "FullyQualifiedName~AppStateServiceTests|FullyQualifiedName~PermissionModeCatalogTests|FullyQualifiedName~ChatWindowSlashPolicyTests|FullyQualifiedName~OperationModePolicyTests"` 통과 (132 passed, 0 failed). diff --git a/src/AxCopilot.Tests/Services/AppStateServiceTests.cs b/src/AxCopilot.Tests/Services/AppStateServiceTests.cs index a34424b..bdf5e31 100644 --- a/src/AxCopilot.Tests/Services/AppStateServiceTests.cs +++ b/src/AxCopilot.Tests/Services/AppStateServiceTests.cs @@ -9,6 +9,20 @@ namespace AxCopilot.Tests.Services; public class AppStateServiceTests { + [Fact] + public void LoadFromSettings_DefaultPermission_ShouldBeDeny() + { + var settings = new SettingsService(); + var state = new AppStateService(); + + state.LoadFromSettings(settings); + + state.Permissions.FilePermission.Should().Be("Deny"); + var summary = state.GetPermissionSummary(); + summary.DefaultMode.Should().Be("Deny"); + summary.EffectiveMode.Should().Be("Deny"); + } + [Fact] public void LoadFromSettings_ReflectsPermissionAndMcpSummary() { diff --git a/src/AxCopilot/Models/AppSettings.cs b/src/AxCopilot/Models/AppSettings.cs index 1634b29..6a779b3 100644 --- a/src/AxCopilot/Models/AppSettings.cs +++ b/src/AxCopilot/Models/AppSettings.cs @@ -12,7 +12,7 @@ public class AppSettings /// claw code 미포함 배포는 false로 설정합니다. /// [JsonPropertyName("ai_enabled")] - public bool AiEnabled { get; set; } = false; + public bool AiEnabled { get; set; } = true; /// /// 운영 모드. internal(사내) | external(사외). @@ -599,11 +599,11 @@ public class LlmSettings /// BypassPermissions = 모든 확인 생략 | DontAsk = 권한 질문 없이 진행 | Deny = 읽기 전용 /// [JsonPropertyName("filePermission")] - public string FilePermission { get; set; } = "Default"; + public string FilePermission { get; set; } = "Deny"; /// Cowork/Code 탭의 기본 파일 접근 권한. 탭 전환 시 자동 적용. [JsonPropertyName("defaultAgentPermission")] - public string DefaultAgentPermission { get; set; } = "Default"; + public string DefaultAgentPermission { get; set; } = "Deny"; // ── 서비스별 독립 설정 ────────────────────────────────────── [JsonPropertyName("ollamaEndpoint")] public string OllamaEndpoint { get; set; } = "http://localhost:11434"; @@ -666,6 +666,14 @@ public class LlmSettings [JsonPropertyName("agentUiExpressionLevel")] public string AgentUiExpressionLevel { get; set; } = "balanced"; + /// 권한 팝업 섹션 접힘/펼침 상태. key=section id, value=true(펼침). + [JsonPropertyName("permissionPopupSections")] + public Dictionary PermissionPopupSections { get; set; } = new(StringComparer.OrdinalIgnoreCase); + + /// 슬래시 팔레트 그룹 접힘/펼침 상태. key=group id, value=true(펼침). + [JsonPropertyName("slashPaletteSections")] + public Dictionary SlashPaletteSections { get; set; } = new(StringComparer.OrdinalIgnoreCase); + /// 계획 diff 심각도 중간 기준: 변경 개수 임계값. [JsonPropertyName("planDiffSeverityMediumCount")] public int PlanDiffSeverityMediumCount { get; set; } = 2; @@ -965,6 +973,18 @@ public class LlmSettings [JsonPropertyName("favoriteSlashCommands")] public List FavoriteSlashCommands { get; set; } = new(); + /// 슬래시 핀(즐겨찾기) 최대 개수. 기본 10. + [JsonPropertyName("maxFavoriteSlashCommands")] + public int MaxFavoriteSlashCommands { get; set; } = 10; + + /// 최근 사용 슬래시 명령어 목록(MRU, 최신 순). 예: ["/compact", "/status"] + [JsonPropertyName("recentSlashCommands")] + public List RecentSlashCommands { get; set; } = new(); + + /// 슬래시 최근 사용(MRU) 최대 개수. 기본 20. + [JsonPropertyName("maxRecentSlashCommands")] + public int MaxRecentSlashCommands { get; set; } = 20; + // ─── 드래그 앤 드롭 AI 처리 ────────────────────────────────────── /// 파일 드래그 시 AI 액션 팝업 표시 여부. 기본 true. diff --git a/src/AxCopilot/Services/AppStateService.cs b/src/AxCopilot/Services/AppStateService.cs index 409d199..228cd88 100644 --- a/src/AxCopilot/Services/AppStateService.cs +++ b/src/AxCopilot/Services/AppStateService.cs @@ -30,7 +30,7 @@ public sealed class AppStateService public sealed class PermissionPolicyState { - public string FilePermission { get; set; } = "Default"; + public string FilePermission { get; set; } = "Deny"; public string AgentDecisionLevel { get; set; } = "detailed"; public string PlanMode { get; set; } = "off"; public int ToolOverrideCount { get; set; } @@ -70,8 +70,8 @@ public sealed class AppStateService public sealed class PermissionSummaryState { - public string EffectiveMode { get; init; } = "Ask"; - public string DefaultMode { get; init; } = "Ask"; + public string EffectiveMode { get; init; } = "Deny"; + public string DefaultMode { get; init; } = "Deny"; public int OverrideCount { get; init; } public string RiskLevel { get; init; } = "normal"; public string Description { get; init; } = ""; diff --git a/src/AxCopilot/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index c215c89..288cca4 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -7290,11 +7290,11 @@ public partial class ChatWindow : Window if (permAction == "status") { - AppendLocalSlashResult(_activeTab, "/permissions", $"{BuildPermissionStatusText()}\n사용법: /permissions deny|default|acceptedits|plan|bypass|dontask|status"); + AppendLocalSlashResult(_activeTab, "/permissions", $"{BuildPermissionStatusText()}\n사용법: /permissions none|passive|active|plan|fullauto|silent|status"); return; } - OpenPermissionPanelFromSlash("/permissions", "사용법: /permissions deny|default|acceptedits|plan|bypass|dontask|status"); + OpenPermissionPanelFromSlash("/permissions", "사용법: /permissions none|passive|active|plan|fullauto|silent|status"); return; } if (string.Equals(slashSystem, "__ALLOWED_TOOLS__", StringComparison.Ordinal)) @@ -7308,11 +7308,11 @@ public partial class ChatWindow : Window if (toolAction == "status") { - AppendLocalSlashResult(_activeTab, "/allowed-tools", $"{BuildPermissionStatusText()}\n사용법: /allowed-tools deny|default|acceptedits|plan|bypass|dontask|status"); + AppendLocalSlashResult(_activeTab, "/allowed-tools", $"{BuildPermissionStatusText()}\n사용법: /allowed-tools none|passive|active|plan|fullauto|silent|status"); return; } - OpenPermissionPanelFromSlash("/allowed-tools", "사용법: /allowed-tools deny|default|acceptedits|plan|bypass|dontask|status"); + OpenPermissionPanelFromSlash("/allowed-tools", "사용법: /allowed-tools none|passive|active|plan|fullauto|silent|status"); return; } if (string.Equals(slashSystem, "__MODEL__", StringComparison.Ordinal))