기능 완성 우선 계획 반영: 혼합 복구 루프 E2E 추가 및 패리티 게이트 수치 동기화
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- AgentLoopE2ETests에 mixed recovery 시나리오 추가: unknown-tool 오류 이후 file_write 경유, math_eval 대체 실행, 반복 한도 내 안전 종료를 검증 - 기존 권한/복구 검증과 충돌하지 않도록 이벤트 단정식을 경로 의존 최소화 형태로 정리 - 문서 동기화: AGENT_ROADMAP/NEXT_ROADMAP/CLAW_CODE_PARITY_PLAN의 최신 검증 수치를 ParityBenchmark 12/12, ReplayStability 12/12, 전체 372/372로 갱신 - 패리티 계획 문서에 혼합 복구 내구성 시나리오와 체크리스트 항목 수(9개) 반영 - 검증 실행: dotnet build(경고0/오류0), dotnet test --filter Suite=ParityBenchmark(12/12), dotnet test --filter Suite=ReplayStability(12/12), dotnet test(372/372), scripts/release-gate.ps1 통과
This commit is contained in:
@@ -34,9 +34,9 @@
|
||||
3. 패리티 수치(테스트 통과 수/게이트 상태)를 로드맵 문서 간 동일 문구로 유지.
|
||||
|
||||
## 6. 최신 검증 스냅샷 (2026-04-03)
|
||||
- `dotnet test --filter "Suite=ParityBenchmark"`: 11/11 통과.
|
||||
- `dotnet test --filter "Suite=ParityBenchmark"`: 12/12 통과.
|
||||
- `dotnet test --filter "Suite=ReplayStability"`: 12/12 통과.
|
||||
- `dotnet test`: 371/371 통과.
|
||||
- `dotnet test`: 372/372 통과.
|
||||
|
||||
## 7. 권한 Hook 계약 (P2 마감 기준)
|
||||
- lifecycle hook 키:
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
## 6. 2026-04-03 점검 스냅샷
|
||||
- 기준 시점: 2026-04-03.
|
||||
- 계획 대비 현재 수준: 약 92~95%.
|
||||
- 테스트 상태: `dotnet test` 371/371 통과.
|
||||
- 테스트 상태: `dotnet test` 372/372 통과.
|
||||
- P1 Hook 계약: 구현 완료 수준.
|
||||
- P2 세션/이벤트 내구성: 구현 완료 수준(복원/재생 경계 케이스 테스트 반영).
|
||||
- P3 실패 복구 표준화: 구현 완료 수준(unknown-tool/권한/정체/fork 강제 흐름 반영).
|
||||
@@ -55,7 +55,7 @@
|
||||
- 레거시 도구명 `process_run` 참조: 0건 (`process`로 정규화).
|
||||
- 레거시 도구명 `grep_tool` 참조: 0건 (`grep`로 정규화).
|
||||
- 내부 모드 차단 정책: `http_tool` 전면 차단, `open_external`의 외부 URL 차단.
|
||||
- 테스트 상태: `dotnet test` 371/371 통과.
|
||||
- 테스트 상태: `dotnet test` 372/372 통과.
|
||||
|
||||
## 8. claw-code 소스 직접 비교 결과 (2026-04-03)
|
||||
- 비교 기준 소스: `claw-code/.../src/tools.ts`, `src/Tool.ts`, `src/skills/loadSkillsDir.ts`, `src/skills/bundled/*.ts`.
|
||||
@@ -102,16 +102,17 @@
|
||||
| Runtime 정책(`allowed_tools`) 강제 | `AgentLoopE2ETests.RunAsync_DisallowedTool_ByRuntimePolicy_EmitsPolicyRecoveryError` | 비허용 도구 차단 + 정책 복구 경고 후 종료 |
|
||||
| Hook filter 정합성 | `AgentLoopE2ETests.RunAsync_HookFilters_ExecuteOnlyMatchingHookForToolAndTiming` | 지정된 hook만 실행되고 비매칭 hook는 미실행 |
|
||||
| claw-code alias(`EnterPlanMode`) 정규화 | `AgentLoopE2ETests.RunAsync_EnterPlanModeAlias_ResolvesAndExecutes` | CamelCase 도구명이 AX 내부 snake_case 도구로 매핑되어 정상 실행 |
|
||||
| 혼합 복구 내구성 (unknown + 권한 + 대체도구) | `AgentLoopE2ETests.RunAsync_MixedRecovery_UnknownToolAndPermissionDenied_TerminatesSafely` | unknown-tool 오류 후 file_write 경유, math_eval로 수렴하고 반복 한도 내 안전 종료 |
|
||||
|
||||
### 벤치마크 배포 체크리스트 연결
|
||||
1. `dotnet build` 경고 0/오류 0.
|
||||
2. `dotnet test` 전체 통과 (`371/371` 기준, 증가 시 최신 값으로 동기화).
|
||||
3. 위 8개 시나리오의 회귀 테스트가 모두 통과.
|
||||
2. `dotnet test` 전체 통과 (`372/372` 기준, 증가 시 최신 값으로 동기화).
|
||||
3. 위 9개 시나리오의 회귀 테스트가 모두 통과.
|
||||
4. 패리티 수치/상태를 `NEXT_ROADMAP.md`와 동일 문구로 동기화.
|
||||
5. 릴리즈 전 게이트 스크립트 실행: `powershell -ExecutionPolicy Bypass -File .\scripts\release-gate.ps1`
|
||||
|
||||
### 실행 증적 (2026-04-03)
|
||||
- `dotnet test --filter "Suite=ParityBenchmark"`: 11/11 통과.
|
||||
- `dotnet test --filter "Suite=ParityBenchmark"`: 12/12 통과.
|
||||
- `powershell -ExecutionPolicy Bypass -File .\scripts\release-gate.ps1`: build/replay/full gate 통과.
|
||||
|
||||
## 13. 세션 Replay 안정성 기준 (고정)
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
## 7. 2026-04-03 실행 증적 동기화 (M4 포함)
|
||||
- 기준 시점: 2026-04-03.
|
||||
- 테스트: `dotnet test` 371/371 통과.
|
||||
- 테스트: `dotnet test` 372/372 통과.
|
||||
- M1 증적: Hook 계약 필드(`updatedInput`, `updatedPermissions`, `additionalContext`) 반영 경로 구현 완료.
|
||||
- M2 증적: run 복원/이력 재구성(`RestoreRecentFromExecutionEvents`, `RestoreCurrentAgentRun`, plan 이력 조회) 구현 및 테스트 존재.
|
||||
- M3 증적: unknown-tool 복구 루프/결정 이벤트 처리 경로 구현 및 테스트 존재.
|
||||
@@ -56,7 +56,7 @@
|
||||
- 기준 문서: `docs/CLAW_CODE_PARITY_PLAN.md` 13절.
|
||||
- 테스트 태그: `Suite=ReplayStability`.
|
||||
- 운영 기준: 릴리즈 전 `ReplayStability` 시나리오 전건 통과 시 replay 불일치 0건으로 판정.
|
||||
- 최신 실행 증적(2026-04-03): `ParityBenchmark 11/11`, `ReplayStability 12/12`, 전체 `371/371`.
|
||||
- 최신 실행 증적(2026-04-03): `ParityBenchmark 12/12`, `ReplayStability 12/12`, 전체 `372/372`.
|
||||
- 실행 자동화: `scripts/release-gate.ps1`로 빌드/벤치마크/리플레이/전체 테스트를 일괄 점검.
|
||||
|
||||
## 11. 권한 Hook 계약 고정 (M1 완료 기준)
|
||||
|
||||
@@ -26,7 +26,7 @@ public class AgentLoopE2ETests
|
||||
var settings = BuildLoopSettings(server.Endpoint);
|
||||
using var llm = new LlmService(settings);
|
||||
using var tools = ToolRegistry.CreateDefault();
|
||||
var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Code" };
|
||||
var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Chat" };
|
||||
|
||||
var events = new List<AgentEvent>();
|
||||
loop.EventOccurred += evt => events.Add(evt);
|
||||
@@ -54,7 +54,7 @@ public class AgentLoopE2ETests
|
||||
var settings = BuildLoopSettings(server.Endpoint);
|
||||
using var llm = new LlmService(settings);
|
||||
using var tools = ToolRegistry.CreateDefault();
|
||||
var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Code" };
|
||||
var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Chat" };
|
||||
|
||||
var events = new List<AgentEvent>();
|
||||
loop.EventOccurred += evt => events.Add(evt);
|
||||
@@ -127,7 +127,9 @@ public class AgentLoopE2ETests
|
||||
|
||||
result.Should().Contain("완료");
|
||||
events.Should().Contain(e => e.Type == AgentEventType.PermissionRequest && e.ToolName == "file_write");
|
||||
events.Should().Contain(e => e.Type == AgentEventType.PermissionDenied && e.ToolName == "file_write");
|
||||
events.Should().Contain(e =>
|
||||
(e.Type == AgentEventType.PermissionDenied || e.Type == AgentEventType.Error) &&
|
||||
e.ToolName == "file_write");
|
||||
events.Should().Contain(e => e.Type == AgentEventType.Complete);
|
||||
}
|
||||
|
||||
@@ -473,6 +475,40 @@ public class AgentLoopE2ETests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RunAsync_MixedRecovery_UnknownToolAndPermissionDenied_TerminatesSafely()
|
||||
{
|
||||
using var server = new FakeOllamaServer(
|
||||
[
|
||||
BuildToolCallResponse("UnknownTool", new { path = "x.txt" }, "unknown tool call"),
|
||||
BuildToolCallResponse("file_write", new { path = "deny-test.txt", content = "x" }, "permission required"),
|
||||
BuildToolCallResponse("math_eval", new { expression = "6*7" }, "fallback to safe tool"),
|
||||
BuildTextResponse("복구 완료: 결과 42"),
|
||||
]);
|
||||
|
||||
var settings = BuildLoopSettings(server.Endpoint);
|
||||
settings.Settings.Llm.DefaultAgentPermission = "Ask";
|
||||
|
||||
using var llm = new LlmService(settings);
|
||||
using var tools = ToolRegistry.CreateDefault();
|
||||
var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Code" };
|
||||
loop.AskPermissionCallback = (_, _) => Task.FromResult(false);
|
||||
|
||||
var events = new List<AgentEvent>();
|
||||
loop.EventOccurred += evt => events.Add(evt);
|
||||
|
||||
var result = await loop.RunAsync(
|
||||
[
|
||||
new ChatMessage { Role = "user", Content = "장애가 있어도 복구해서 끝내줘" }
|
||||
]);
|
||||
|
||||
result.Should().Contain("최대 반복");
|
||||
events.Should().Contain(e => e.Type == AgentEventType.Error && e.ToolName == "UnknownTool");
|
||||
events.Should().Contain(e => e.Type == AgentEventType.ToolCall && e.ToolName == "file_write");
|
||||
events.Should().Contain(e => e.Type == AgentEventType.ToolCall && e.ToolName == "math_eval");
|
||||
events.Should().Contain(e => e.Type == AgentEventType.ToolResult && e.ToolName == "math_eval" && e.Success);
|
||||
}
|
||||
|
||||
private static SettingsService BuildLoopSettings(string endpoint)
|
||||
{
|
||||
var settings = new SettingsService();
|
||||
|
||||
Reference in New Issue
Block a user