using System.Text.Json.Serialization; namespace ClawdDotNet.Core.Cases; /// #689: The limits that make escalation end. public sealed class CaseSettings { /// /// Hours the agents have to solve a case. After that a human is called — a case nobody /// can solve must not exist. Short rather than long (decision of 2026-09-22). /// [JsonPropertyName("deadlineHours")] public double DeadlineHours { get; set; } = 4; /// /// Escalations one unit may raise in 24 hours. Beyond that each new one goes straight to /// a human: a unit that hands everything up is itself a finding, and every level costs a run. /// [JsonPropertyName("escalationsPerUnitPerDay")] public int EscalationsPerUnitPerDay { get; set; } = 10; /// #690: Who decides at the top of the tree. [JsonPropertyName("top")] public TopSettings Top { get; set; } = new(); public TimeSpan Deadline => TimeSpan.FromHours(Math.Clamp(DeadlineHours, 0.25, 24 * 14)); } /// #690: How the top of the tree is filled — a role, not a person. [JsonConverter(typeof(JsonStringEnumConverter))] public enum TopMode { /// A human. Cases wait in the web interface. Human, /// An agent — a strong model that runs rarely, decides and gives reasons. Agent, /// /// The human first; without an answer in the agent /// decides and presents the decision. For an organisation that goes on at night. /// HumanFirst } public sealed class TopSettings { [JsonPropertyName("mode")] public TopMode Mode { get; set; } = TopMode.Human; /// The deciding agent, for and . [JsonPropertyName("agentId")] public string? AgentId { get; set; } /// How long the human has before the agent decides, in . [JsonPropertyName("humanFirstHours")] public double HumanFirstHours { get; set; } = 2; public TimeSpan HumanFirst => TimeSpan.FromHours(Math.Clamp(HumanFirstHours, 0.25, 24 * 7)); /// Whether an agent takes part at the top at all. [JsonIgnore] public bool UsesAgent => Mode != TopMode.Human && !string.IsNullOrWhiteSpace(AgentId); }