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 수치 및 기준 최신화
82 lines
2.4 KiB
C#
82 lines
2.4 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace AxCopilot.Services.Agent;
|
|
|
|
internal static class TaskBoardStore
|
|
{
|
|
private const string StoreRelativePath = ".ax/taskboard.json";
|
|
|
|
internal sealed class TaskItem
|
|
{
|
|
[JsonPropertyName("id")]
|
|
public int Id { get; set; }
|
|
|
|
[JsonPropertyName("title")]
|
|
public string Title { get; set; } = "";
|
|
|
|
[JsonPropertyName("description")]
|
|
public string Description { get; set; } = "";
|
|
|
|
[JsonPropertyName("status")]
|
|
public string Status { get; set; } = "open"; // open | in_progress | blocked | done | stopped
|
|
|
|
[JsonPropertyName("priority")]
|
|
public string Priority { get; set; } = "medium"; // high | medium | low
|
|
|
|
[JsonPropertyName("output")]
|
|
public string Output { get; set; } = "";
|
|
|
|
[JsonPropertyName("createdAt")]
|
|
public DateTime CreatedAt { get; set; } = DateTime.Now;
|
|
|
|
[JsonPropertyName("updatedAt")]
|
|
public DateTime UpdatedAt { get; set; } = DateTime.Now;
|
|
}
|
|
|
|
internal static string GetStorePath(string workFolder)
|
|
=> Path.Combine(workFolder, StoreRelativePath);
|
|
|
|
internal static List<TaskItem> Load(string workFolder)
|
|
{
|
|
var path = GetStorePath(workFolder);
|
|
if (!File.Exists(path))
|
|
return [];
|
|
|
|
try
|
|
{
|
|
var json = TextFileCodec.ReadAllText(path).Text;
|
|
return JsonSerializer.Deserialize<List<TaskItem>>(json) ?? [];
|
|
}
|
|
catch
|
|
{
|
|
return [];
|
|
}
|
|
}
|
|
|
|
internal static void Save(string workFolder, List<TaskItem> tasks)
|
|
{
|
|
var path = GetStorePath(workFolder);
|
|
var dir = Path.GetDirectoryName(path);
|
|
if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir))
|
|
Directory.CreateDirectory(dir);
|
|
|
|
var json = JsonSerializer.Serialize(tasks, new JsonSerializerOptions
|
|
{
|
|
WriteIndented = true
|
|
});
|
|
File.WriteAllText(path, json, TextFileCodec.Utf8NoBom);
|
|
}
|
|
|
|
internal static int NextId(List<TaskItem> tasks)
|
|
=> tasks.Count == 0 ? 1 : tasks.Max(t => t.Id) + 1;
|
|
|
|
internal static bool IsValidStatus(string value)
|
|
=> value is "open" or "in_progress" or "blocked" or "done" or "stopped";
|
|
|
|
internal static bool IsValidPriority(string value)
|
|
=> value is "high" or "medium" or "low";
|
|
}
|