using ClaudeDo.Data.Models; namespace ClaudeDo.Worker.Runner; /// The task/list/preset/global resolution actually runs with, /// plus where each value came from — so a caller can tell a genuine default from an override /// without re-deriving the resolution order itself. public sealed record EffectiveRunConfig( string Model, string ModelSource, int MaxTurns, string MaxTurnsSource, int RequestedMaxTurns, bool MaxTurnsClamped, string Effort, string? AgentPath, string? AgentPathSource, string PermissionMode, bool SystemPromptSet, IReadOnlyList SystemPromptSources); /// Single source of truth for "which value wins" — shared by 's /// actual run path and any read-only reporting of the same resolution (e.g. the /// get_effective_run_config MCP tool), so the two can never drift apart. public static class EffectiveRunConfigResolver { public static EffectiveRunConfig Resolve( TaskEntity task, ListConfigEntity? listConfig, AppSettingsEntity global, string? systemFile, string? improvementPrompt) { var model = task.Model ?? listConfig?.Model ?? global.DefaultModel; var modelSource = task.Model is not null ? "task" : listConfig?.Model is not null ? "list" : "global"; var preset = ModelPresets.For(global.ModelPresets, model, global.DefaultMaxTurns); var requestedMaxTurns = task.MaxTurns ?? listConfig?.MaxTurns ?? preset.MaxTurns; var maxTurnsSource = task.MaxTurns is not null ? "task" : listConfig?.MaxTurns is not null ? "list" : "preset"; // ResolveMaxTurns is declared int? but always returns a value (Math.Min of non-null inputs). var maxTurns = TaskRunner.ResolveMaxTurns(task.MaxTurns, listConfig?.MaxTurns, preset.MaxTurns, global.MaxTurnsCeiling)!.Value; var agentPath = task.AgentPath ?? listConfig?.AgentPath; var agentPathSource = task.AgentPath is not null ? "task" : listConfig?.AgentPath is not null ? "list" : null; var systemPromptSources = new List(); if (!string.IsNullOrWhiteSpace(systemFile)) systemPromptSources.Add("systemFile"); if (!string.IsNullOrWhiteSpace(improvementPrompt)) systemPromptSources.Add("improvementPrompt"); if (!string.IsNullOrWhiteSpace(global.DefaultClaudeInstructions)) systemPromptSources.Add("global"); if (!string.IsNullOrWhiteSpace(listConfig?.SystemPrompt)) systemPromptSources.Add("list"); if (!string.IsNullOrWhiteSpace(task.SystemPrompt)) systemPromptSources.Add("task"); return new EffectiveRunConfig( model, modelSource, maxTurns, maxTurnsSource, requestedMaxTurns, maxTurns < requestedMaxTurns, preset.Effort, agentPath, agentPathSource, global.DefaultPermissionMode, systemPromptSources.Count > 0, systemPromptSources); } }