claw-code 동등 품질 4단계 연속 반영: Agentic 루프/상태복원/설정연동/릴리즈 게이트 정렬
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- 도구 동등화: task/todo/tool-search + plan/worktree/team/cron 도구군 추가 및 ToolRegistry 등록\n- claw-code CamelCase 별칭 정규화 확장: EnterPlanMode/EnterWorktree/TeamCreate/CronCreate 등 -> 내부 snake_case 매핑\n- AgentLoop 런타임 강화: Code 탭 전용 도구 토글(CodeSettings) 반영, 비활성 도구 자동 차단\n- Worktree 상태 복원 연결: .ax/worktree_state.json 기반 루트 탐색/활성 worktree 복원 및 BuildContext 연동\n- 권한/플러그인 하드닝 기존 반영분 유지: target 기반 권한 판정 + internal 모드 플러그인 경로/manifest 검증\n- 설정 연동(UI): SettingsWindow Code 패널에 Plan/Worktree/Team/Cron 도구 on/off 토글 추가\n- 테스트 보강: AgentParityTools/AgentLoopE2E에 worktree 지속성, alias 정규화, 설정 차단 시나리오 추가\n- 검증 완료: dotnet build(경고0/오류0), ParityBenchmark 11/11, ReplayStability 12/12, 전체 371/371, release-gate 통과\n- 문서 동기화: AGENT_ROADMAP/NEXT_ROADMAP/CLAW_CODE_PARITY_PLAN 수치 및 기준 최신화
This commit is contained in:
85
src/AxCopilot/Services/Agent/WorktreeStateStore.cs
Normal file
85
src/AxCopilot/Services/Agent/WorktreeStateStore.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AxCopilot.Services.Agent;
|
||||
|
||||
internal static class WorktreeStateStore
|
||||
{
|
||||
private const string StateRelativePath = ".ax/worktree_state.json";
|
||||
|
||||
internal sealed class WorktreeState
|
||||
{
|
||||
[JsonPropertyName("root")]
|
||||
public string Root { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("active")]
|
||||
public string Active { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("updatedAt")]
|
||||
public DateTime UpdatedAt { get; set; } = DateTime.Now;
|
||||
}
|
||||
|
||||
private static string GetPath(string root) => Path.Combine(root, StateRelativePath);
|
||||
|
||||
internal static string ResolveRoot(string current)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dir = new DirectoryInfo(Path.GetFullPath(current));
|
||||
while (dir != null)
|
||||
{
|
||||
var candidate = dir.FullName;
|
||||
var statePath = GetPath(candidate);
|
||||
if (File.Exists(statePath))
|
||||
{
|
||||
var state = Load(candidate);
|
||||
if (!string.IsNullOrWhiteSpace(state.Root))
|
||||
{
|
||||
var resolvedRoot = Path.GetFullPath(state.Root);
|
||||
if (Directory.Exists(resolvedRoot))
|
||||
return resolvedRoot;
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
dir = dir.Parent;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore and fallback
|
||||
}
|
||||
|
||||
return Path.GetFullPath(current);
|
||||
}
|
||||
|
||||
internal static WorktreeState Load(string root)
|
||||
{
|
||||
var path = GetPath(root);
|
||||
if (!File.Exists(path))
|
||||
return new WorktreeState { Root = root, Active = root, UpdatedAt = DateTime.Now };
|
||||
|
||||
try
|
||||
{
|
||||
var json = TextFileCodec.ReadAllText(path).Text;
|
||||
var state = JsonSerializer.Deserialize<WorktreeState>(json);
|
||||
return state ?? new WorktreeState { Root = root, Active = root, UpdatedAt = DateTime.Now };
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new WorktreeState { Root = root, Active = root, UpdatedAt = DateTime.Now };
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Save(string root, WorktreeState state)
|
||||
{
|
||||
var path = GetPath(root);
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
state.Root = root;
|
||||
state.UpdatedAt = DateTime.Now;
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(state, new JsonSerializerOptions { WriteIndented = true }), TextFileCodec.Utf8NoBom);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user