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);
}