namespace Deal.Modules.Discovery.Application.Models; /// /// Создание задачи поиска — вход POST /api/discovery/tasks (DiscoveryTaskDraft: поля с дефолтами сервиса). /// /// /// 1:1 с TaskCreate discovery_routes.py L50–60 и нормализацией create_task discovery.py L234–282: name — строка /// (обязательная, Trim); description/keywords/minSubscribers/lang/autoJoin имеют дефолты в сервисе; /// threshold/sampleSize/planJoins — null → дефолты (threshold/sampleSize — из настроек discEvalThreshold/ /// discEvalSample, planJoins — 1). plan_joins дополнительно проходит план-бюджет (DiscoveryPlanGuard). /// public sealed record DiscoveryTaskDraft { /// /// Название задачи (после Trim непустое — иначе 400 «Укажите название задачи»). /// public string Name { get; init; } = string.Empty; /// /// Описание ниши/цели (может быть пустым). /// public string Description { get; init; } = string.Empty; /// /// Ключевые слова поиска; null → пустой список (start до добавления ключей — 400). /// public IReadOnlyList? Keywords { get; init; } /// /// Минимальное число участников; null → 0. /// public int? MinSubscribers { get; init; } /// /// Язык источников: ru|any; null/иное → ru. /// public string? Lang { get; init; } /// /// Порог подходящих сообщений, % (кламп 1..100); null → настройка discEvalThreshold. /// public int? Threshold { get; init; } /// /// Размер выборки сообщений при оценке (кламп ≥1); null → настройка discEvalSample. /// public int? SampleSize { get; init; } /// /// План авто-вступлений (1..discJoinLimit + бюджет); null → 1. /// public int? PlanJoins { get; init; } /// /// Авто-вступления воркером; null → false. /// public bool? AutoJoin { get; init; } }