feat(ui): PowerUse-Toggle im Usage-Monitor, Opt-in pro Liste

Der Toggle sitzt unter den Gauges im Usage-Monitor, weil "das restliche Fenster
ausnutzen" eine Entscheidung ist, die man beim Blick auf das restliche Fenster
trifft. Er speichert sofort per Read-modify-write, gleiche Disziplin wie
SaveStagesAsync, damit er keine Felder ueberschreibt, die er nicht besitzt.

Zwei Stellen, die das Opt-in still ausgeschaltet haetten:
- WorkerHub.UpdateListConfig loescht die Config-Zeile, wenn alle Felder leer
  sind. PowerUseAllowed muss in diese Leer-Pruefung, sonst verschwindet das
  Opt-in sofort wieder, wenn es das einzige gesetzte Feld ist.
- SettingsModalViewModel baut das AppSettingsDto positional neu auf. Ohne
  Round-trip haette jedes Speichern der Settings PowerUseEnabled auf den
  Record-Default false zurueckgesetzt. Gleiches Muster wie _throttleStages.

Das Handoff-Budget ist als Spinner in Settings -> General editierbar, weil es
auch fuer normale (interaktive) Handler-Runs gilt und nicht an PowerUse haengt.
Das Addendum selbst ist ueber Settings -> Files anpassbar.
This commit is contained in:
Mika Kuns
2026-09-02 15:44:13 +02:00
parent 453d61ca58
commit 193752540b
11 changed files with 132 additions and 8 deletions
@@ -103,6 +103,13 @@
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
</StackPanel>
<StackPanel Spacing="4">
<CheckBox IsChecked="{Binding PowerUseAllowed, Mode=TwoWay}"
Content="{loc:Tr modals.listSettings.powerUseAllowed}"/>
<TextBlock Text="{loc:Tr modals.listSettings.powerUseAllowedHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
</StackPanel>
<StackPanel Spacing="4" IsVisible="{Binding TicketsAvailable}">
<TextBlock Classes="field-label" Text="{loc:Tr modals.listSettings.ticketProject}"/>
<ComboBox ItemsSource="{Binding TicketProjects}"
@@ -251,6 +251,17 @@
Content="{loc:Tr settings.general.autoContinueOnUsageLimit}"/>
<TextBlock Text="{loc:Tr settings.general.autoContinueOnUsageLimitHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
<!-- PowerUse itself is toggled on the usage monitor; only its handoff budget is
typed here, because it also applies to a normal (interactive) handler run. -->
<StackPanel Spacing="4">
<TextBlock Classes="eyebrow" Text="{loc:Tr settings.general.listHandlerMaxHandoffs}"/>
<NumericUpDown Value="{Binding General.ListHandlerMaxHandoffs, Mode=TwoWay, Converter={StaticResource KeepLastNumber}}"
Minimum="1" Maximum="200" Increment="2" FormatString="0"
HorizontalAlignment="Left" Width="140"/>
<TextBlock Text="{loc:Tr settings.general.listHandlerMaxHandoffsHint}"
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
</StackPanel>
</StackPanel>
<!-- Throttle stages live on the usage-monitor gauges (drag + spinner per stage);
@@ -433,7 +444,7 @@
</StackPanel>
<StackPanel Spacing="6">
<TextBlock Classes="section-label" Text="{loc:Tr settings.files.promptsSection}"/>
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto" ColumnDefinitions="120,*,Auto" RowSpacing="8">
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto" ColumnDefinitions="120,*,Auto" RowSpacing="8">
<TextBlock Grid.Row="0" Grid.Column="0" Classes="field-label" Text="{loc:Tr settings.files.systemPrompt}" VerticalAlignment="Center"/>
<TextBlock Grid.Row="0" Grid.Column="1" Classes="path-mono" Text="{Binding Files.SystemPromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="0" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
@@ -458,6 +469,10 @@
<TextBlock Grid.Row="5" Grid.Column="1" Classes="path-mono" Text="{Binding Files.WeeklyReportPromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="5" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
Command="{Binding Files.ViewPromptCommand}" CommandParameter="WeeklyReport"/>
<TextBlock Grid.Row="6" Grid.Column="0" Classes="field-label" Text="{loc:Tr settings.files.powerUsePrompt}" VerticalAlignment="Center"/>
<TextBlock Grid.Row="6" Grid.Column="1" Classes="path-mono" Text="{Binding Files.PowerUsePromptPath}" VerticalAlignment="Center"/>
<Button Classes="btn" Grid.Row="6" Grid.Column="2" Content="{loc:Tr settings.files.viewPrompt}"
Command="{Binding Files.ViewPromptCommand}" CommandParameter="PowerUseAddendum"/>
</Grid>
</StackPanel>
<StackPanel Spacing="6" IsVisible="{Binding Files.ViewedKindName, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
@@ -134,6 +134,19 @@
Text="{loc:Tr modals.usageMonitor.noGauges}"
IsVisible="{Binding !GaugeRows.Count}"/>
<!-- PowerUse: sits under the gauges on purpose — "spend the rest of the window" is a
decision made while looking at how much window is left. Saves immediately on toggle. -->
<Border DockPanel.Dock="Top" Margin="20,12,20,0" Padding="12,10"
Background="{DynamicResource DeepBrush}" BorderBrush="{DynamicResource LineBrush}"
BorderThickness="1" CornerRadius="6">
<StackPanel Spacing="4">
<CheckBox IsChecked="{Binding PowerUseEnabled, Mode=TwoWay}"
Content="{loc:Tr modals.usageMonitor.powerUse}"/>
<TextBlock Classes="meta" TextWrapping="Wrap"
Text="{loc:Tr modals.usageMonitor.powerUseHint}"/>
</StackPanel>
</Border>
<!-- Period picker -->
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8" Margin="20,12,20,0">
<TextBlock Classes="meta" Text="{loc:Tr modals.usageMonitor.period}" VerticalAlignment="Center"/>