권한 코어를 claude-code 기준으로 재구성하고 slash palette 상태 분리를 시작\n\n- Default/AcceptEdits/Plan/BypassPermissions/DontAsk/Deny 권한 모드를 추가하고 기존 Ask/Auto 호환을 유지\n- deny 우선 패턴 규칙, allow/override, 글로벌 모드 순서의 권한 해석 체계를 정리\n- file_write/file_edit/file_manage와 process/build_run/test_loop/snippet_runner/spawn_agent 계열을 권한 클래스별로 분리\n- AcceptEdits는 파일 편집 도구 자동 허용, process 계열은 계속 확인하도록 조정\n- Plan은 쓰기 도구를 차단하고 읽기 중심 진행이 되도록 보강\n- BypassPermissions와 DontAsk는 권한 확인을 생략하는 경로로 정규화\n- AX Agent 권한 팝업, 상단 배너, slash 명령 결과를 새 권한 체계에 맞게 정리\n- /permissions, /allowed-tools, /sandbox-toggle 사용법과 상태 출력을 갱신\n- ChatWindow의 slash palette 상태를 전용 SlashPaletteState로 분리해 이후 composer 개편 기반을 마련\n- AppState, 설정 모델, 테스트를 새 권한 체계에 맞게 갱신\n- dotnet build 경고 0 / 오류 0, dotnet test 436 통과를 확인
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
This commit is contained in:
@@ -37,7 +37,7 @@ public class OperationModePolicyTests
|
||||
var context = new AgentContext
|
||||
{
|
||||
OperationMode = OperationModePolicy.InternalMode,
|
||||
Permission = "Auto"
|
||||
Permission = "AcceptEdits"
|
||||
};
|
||||
|
||||
var blocked = await context.CheckToolPermissionAsync("http_tool", "https://example.com");
|
||||
@@ -53,7 +53,7 @@ public class OperationModePolicyTests
|
||||
var context = new AgentContext
|
||||
{
|
||||
OperationMode = OperationModePolicy.ExternalMode,
|
||||
Permission = "Auto"
|
||||
Permission = "AcceptEdits"
|
||||
};
|
||||
|
||||
var allowed = await context.CheckToolPermissionAsync("http_tool", "https://example.com");
|
||||
@@ -65,18 +65,18 @@ public class OperationModePolicyTests
|
||||
{
|
||||
var context = new AgentContext
|
||||
{
|
||||
Permission = "Ask",
|
||||
Permission = "Default",
|
||||
ToolPermissions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["process"] = "deny",
|
||||
["process@git *"] = "auto",
|
||||
["*@*.md"] = "ask",
|
||||
["process@git *"] = "acceptedits",
|
||||
["*@*.md"] = "default",
|
||||
}
|
||||
};
|
||||
|
||||
context.GetEffectiveToolPermission("process", "git status").Should().Be("auto");
|
||||
context.GetEffectiveToolPermission("process", "powershell -NoProfile").Should().Be("deny");
|
||||
context.GetEffectiveToolPermission("file_read", @"E:\work\README.md").Should().Be("ask");
|
||||
context.GetEffectiveToolPermission("process", "git status").Should().Be("Default");
|
||||
context.GetEffectiveToolPermission("process", "powershell -NoProfile").Should().Be("Deny");
|
||||
context.GetEffectiveToolPermission("file_read", @"E:\work\README.md").Should().Be("AcceptEdits");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -86,10 +86,10 @@ public class OperationModePolicyTests
|
||||
var context = new AgentContext
|
||||
{
|
||||
OperationMode = OperationModePolicy.ExternalMode,
|
||||
Permission = "Ask",
|
||||
Permission = "Default",
|
||||
ToolPermissions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["process@git *"] = "auto",
|
||||
["process@git *"] = "bypassPermissions",
|
||||
},
|
||||
AskPermission = (_, _) =>
|
||||
{
|
||||
@@ -104,29 +104,48 @@ public class OperationModePolicyTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentContext_GetEffectiveToolPermission_DowngradesDangerousAutoToolWhenGlobalAuto()
|
||||
public void AgentContext_GetEffectiveToolPermission_AcceptEditsAllowsWriteButKeepsProcessPrompted()
|
||||
{
|
||||
var context = new AgentContext
|
||||
{
|
||||
Permission = "Auto",
|
||||
ToolPermissions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["process"] = "auto",
|
||||
}
|
||||
Permission = "AcceptEdits"
|
||||
};
|
||||
|
||||
context.GetEffectiveToolPermission("process", "git status").Should().Be("ask");
|
||||
context.GetEffectiveToolPermission("file_read", @"E:\work\README.md").Should().Be("Auto");
|
||||
context.GetEffectiveToolPermission("process", "git status").Should().Be("Default");
|
||||
context.GetEffectiveToolPermission("file_write", @"E:\work\out.txt").Should().Be("AcceptEdits");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AgentContext_CheckToolPermissionAsync_DangerousAutoToolRequiresPromptInGlobalAuto()
|
||||
public async Task AgentContext_CheckToolPermissionAsync_PlanModeBlocksWriteButAllowsRead()
|
||||
{
|
||||
var askCalled = false;
|
||||
var context = new AgentContext
|
||||
{
|
||||
OperationMode = OperationModePolicy.ExternalMode,
|
||||
Permission = "Auto",
|
||||
Permission = "Plan",
|
||||
AskPermission = (_, _) =>
|
||||
{
|
||||
askCalled = true;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
};
|
||||
|
||||
var writeAllowed = await context.CheckToolPermissionAsync("file_write", @"E:\work\out.txt");
|
||||
var readAllowed = await context.CheckToolPermissionAsync("file_read", @"E:\work\in.txt");
|
||||
|
||||
writeAllowed.Should().BeFalse();
|
||||
readAllowed.Should().BeTrue();
|
||||
askCalled.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AgentContext_CheckToolPermissionAsync_BypassPermissionsSkipsPrompt()
|
||||
{
|
||||
var askCalled = false;
|
||||
var context = new AgentContext
|
||||
{
|
||||
OperationMode = OperationModePolicy.ExternalMode,
|
||||
Permission = "BypassPermissions",
|
||||
AskPermission = (_, _) =>
|
||||
{
|
||||
askCalled = true;
|
||||
@@ -135,8 +154,8 @@ public class OperationModePolicyTests
|
||||
};
|
||||
|
||||
var allowed = await context.CheckToolPermissionAsync("process", "git status");
|
||||
allowed.Should().BeFalse();
|
||||
askCalled.Should().BeTrue();
|
||||
allowed.Should().BeTrue();
|
||||
askCalled.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user