feat(claude-do): UI: Gate-Schwellen im Settings-Modal (General)

Macht die zwei Schwellen einstellbar. Setzt den Data-Subtask (Felder in `app_settings`) und den Hub-Subtask voraus.

**Zu bauen**
1. `AppSettingsDto` durchziehen: `WorkerHub` (`GetAppSettings` / `UpdateAppSettings`) und der UI-seitige Record in `WorkerClient.cs` bekommen `UsageGateFiveHourPct` und `UsageGateSevenDayPct`.
2. `GeneralSettingsTabViewModel`: zwei `[ObservableProperty]`-Felder, Validie

ClaudeDo-Task: 06068810-5b5c-4635-80dd-62eeba89fb8c
This commit is contained in:
mika kuns
2026-08-05 13:38:05 +02:00
parent 7661129202
commit 1e88fefbda
9 changed files with 152 additions and 4 deletions
@@ -21,6 +21,10 @@
"permission": "Berechtigung",
"maxParallelExecutions": "Max. parallele Ausführungen",
"maxParallelExecutionsHint": "Wie viele Aufgaben aus der Warteschlange der Worker gleichzeitig ausführt.",
"usageGateHeading": "Usage-Limit-Stopp",
"usageGateHint": "Ab dieser Auslastung holt die Queue keine neuen Tasks mehr; laufende Tasks laufen zu Ende. 0 schaltet den Stopp ab.",
"usageGateFiveHourPct": "5-Stunden-Fenster (%)",
"usageGateSevenDayPct": "7-Tage-Fenster (%)",
"reportExcludedPaths": "Bericht: ausgeschlossene Pfade (einer pro Zeile)",
"standupWeekday": "Standup-Wochentag",
"weekdaySunday": "Sonntag",
@@ -21,6 +21,10 @@
"permission": "Permission",
"maxParallelExecutions": "Max parallel executions",
"maxParallelExecutionsHint": "How many queued tasks the worker runs at once.",
"usageGateHeading": "Usage limit stop",
"usageGateHint": "Once usage reaches this level, the queue stops picking up new tasks; running tasks finish normally. 0 turns the stop off.",
"usageGateFiveHourPct": "5-hour window (%)",
"usageGateSevenDayPct": "7-day window (%)",
"reportExcludedPaths": "Report: excluded paths (one per line)",
"standupWeekday": "Standup weekday",
"weekdaySunday": "Sunday",
+3 -1
View File
@@ -623,7 +623,9 @@ public sealed record AppSettingsDto(
int StandupWeekday,
int DailyPrepMaxTasks,
List<string>? SessionSkills = null,
List<ModelPresetDto>? ModelPresets = null);
List<ModelPresetDto>? ModelPresets = null,
int UsageGateFiveHourPct = 80,
int UsageGateSevenDayPct = 90);
// Per-model run defaults (effort + turn budget) edited in Settings → General.
public sealed record ModelPresetDto(string Model, string Effort, int MaxTurns);
@@ -18,6 +18,9 @@ public sealed partial class GeneralSettingsTabViewModel : ViewModelBase
[ObservableProperty] private int _defaultMaxTurns = 100;
[ObservableProperty] private string _defaultPermissionMode = PermissionModeRegistry.DefaultMode;
[ObservableProperty] private int _maxParallelExecutions = 1;
// Percentage of the 5h/7d Claude usage window at which the autonomous queue pauses. 0 = gate off.
[ObservableProperty] private int _usageGateFiveHourPct = 80;
[ObservableProperty] private int _usageGateSevenDayPct = 90;
// Newline-separated path prefixes excluded from the weekly report.
[ObservableProperty] private string _reportExcludedPaths = @"C:\Private";
// 0=Sunday..6=Saturday (System.DayOfWeek); default Wednesday.
@@ -91,6 +94,10 @@ public sealed partial class GeneralSettingsTabViewModel : ViewModelBase
{
if (MaxParallelExecutions < 1 || MaxParallelExecutions > 20)
return "Max parallel executions must be between 1 and 20.";
if (UsageGateFiveHourPct < 0 || UsageGateFiveHourPct > 100)
return "Usage gate (5h) must be between 0 and 100.";
if (UsageGateSevenDayPct < 0 || UsageGateSevenDayPct > 100)
return "Usage gate (7d) must be between 0 and 100.";
foreach (var row in ModelPresets)
if (row.MaxTurns is < 1 or > 200)
return $"Max turns for {row.Model} must be between 1 and 200.";
@@ -61,6 +61,8 @@ public sealed partial class SettingsModalViewModel : ViewModelBase
General.DefaultMaxTurns = dto.DefaultMaxTurns;
General.DefaultPermissionMode = dto.DefaultPermissionMode ?? "auto";
General.MaxParallelExecutions = dto.MaxParallelExecutions;
General.UsageGateFiveHourPct = dto.UsageGateFiveHourPct;
General.UsageGateSevenDayPct = dto.UsageGateSevenDayPct;
Worktrees.WorktreeStrategy = dto.WorktreeStrategy ?? "sibling";
Worktrees.CentralWorktreeRoot = dto.CentralWorktreeRoot;
Worktrees.WorktreeAutoCleanupEnabled = dto.WorktreeAutoCleanupEnabled;
@@ -109,7 +111,9 @@ public sealed partial class SettingsModalViewModel : ViewModelBase
General.StandupWeekday,
Prime.DailyPrepMaxTasks,
General.SelectedSessionSkillNames(),
General.ModelPresetDtos());
General.ModelPresetDtos(),
General.UsageGateFiveHourPct,
General.UsageGateSevenDayPct);
await _worker.UpdateAppSettingsAsync(dto);
await Prime.SaveAsync();
await OnlineInbox.SaveAsync();
@@ -149,6 +149,25 @@
<TextBlock Text="{loc:Tr settings.general.maxParallelExecutionsHint}"
Opacity="0.6" FontSize="12"/>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.usageGateHeading}"/>
<TextBlock Text="{loc:Tr settings.general.usageGateHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
<StackPanel Orientation="Horizontal" Spacing="16">
<StackPanel Spacing="4">
<TextBlock Classes="eyebrow" Text="{loc:Tr settings.general.usageGateFiveHourPct}"/>
<NumericUpDown Value="{Binding General.UsageGateFiveHourPct, Mode=TwoWay}"
Minimum="0" Maximum="100" Increment="5" FormatString="0"
HorizontalAlignment="Left" Width="140"/>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="eyebrow" Text="{loc:Tr settings.general.usageGateSevenDayPct}"/>
<NumericUpDown Value="{Binding General.UsageGateSevenDayPct, Mode=TwoWay}"
Minimum="0" Maximum="100" Increment="5" FormatString="0"
HorizontalAlignment="Left" Width="140"/>
</StackPanel>
</StackPanel>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.reportExcludedPaths}"/>
<TextBox AcceptsReturn="True" MinHeight="60" Text="{Binding General.ReportExcludedPaths, Mode=TwoWay}"/>
+8 -2
View File
@@ -43,7 +43,9 @@ public record AppSettingsDto(
int StandupWeekday,
int DailyPrepMaxTasks,
List<string>? SessionSkills = null,
List<ModelPresetDto>? ModelPresets = null);
List<ModelPresetDto>? ModelPresets = null,
int UsageGateFiveHourPct = 80,
int UsageGateSevenDayPct = 90);
// Per-model run defaults (effort + turn budget) edited in Settings -> General.
public record ModelPresetDto(string Model, string Effort, int MaxTurns);
@@ -378,7 +380,9 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
row.DailyPrepMaxTasks,
SkillsFromJson(row.SessionSkills),
Data.Models.ModelPresets.Parse(row.ModelPresets)
.Select(p => new ModelPresetDto(p.Model, p.Effort, p.MaxTurns)).ToList());
.Select(p => new ModelPresetDto(p.Model, p.Effort, p.MaxTurns)).ToList(),
row.UsageGateFiveHourPct,
row.UsageGateSevenDayPct);
}
public async Task UpdateAppSettings(AppSettingsDto dto)
@@ -406,6 +410,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
? Data.Models.ModelPresets.Serialize(
dto.ModelPresets.Select(p => new ModelPreset(p.Model, p.Effort, p.MaxTurns)))
: Data.Models.ModelPresets.SerializeDefaults(),
UsageGateFiveHourPct = dto.UsageGateFiveHourPct,
UsageGateSevenDayPct = dto.UsageGateSevenDayPct,
});
}