6.6 KiB
Move "Plan day" into the Prep-Log Window — Plan
For agentic workers: REQUIRED SUB-SKILL: superpowers:subagent-driven-development. Steps use
- [ ].
Goal: Guard daily-prep planning behind a second click. The MyDay header's full-width "Tag vorbereiten" button is removed; instead the user opens the prep-log window (list icon), sees the last run or an empty-state hint, and clicks a "Plan day" button inside that window to run the prep.
Approved flow: Header list-icon (ShowPrepLogCommand) opens the prep window → if empty, an empty-state hint shows → "Plan day" button in the window runs RunDailyPrepNowAsync().
Tech: Avalonia + CommunityToolkit.Mvvm, xUnit.
Build/test
dotnet build src/ClaudeDo.App/ClaudeDo.App.csproj -c Release
dotnet test tests/ClaudeDo.Ui.Tests/ClaudeDo.Ui.Tests.csproj -c Release
dotnet test tests/ClaudeDo.Localization.Tests/ClaudeDo.Localization.Tests.csproj -c Release
GUI not headlessly verifiable — note it; human verifies visuals.
Task: relocate planning trigger + empty-state
Files:
-
Modify:
src/ClaudeDo.Ui/ViewModels/Islands/TasksIslandViewModel.cs(remove PrepareDay) -
Modify:
src/ClaudeDo.Ui/Views/Islands/TasksIslandView.axaml(remove header button) -
Modify:
src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs(PlanDayCommand + empty-state) -
Modify:
src/ClaudeDo.Ui/Views/Islands/DetailsIslandView.axaml(prep panel toolbar + empty hint) -
Modify:
src/ClaudeDo.Localization/locales/en.json,de.json -
Test:
tests/ClaudeDo.Ui.Tests/ViewModels/DetailsIslandPrepModeTests.cs, and the existingTasksIslandDailyPrepTests.cs(remove the obsolete prepare test) -
Step 1: Write/adjust tests first.
- In
DetailsIslandPrepModeTests.csadd:[Fact] public async Task PlanDayCommand_calls_worker() { var stub = new StubWorkerClient(); var vm = NewDetailsVm(stub); await vm.PlanDayCommand.ExecuteAsync(null); Assert.Equal(1, stub.RunDailyPrepNowCalls); } [Fact] public void ShowPrepEmptyState_true_when_empty_and_not_running() { var vm = NewDetailsVm(new StubWorkerClient()); Assert.True(vm.ShowPrepEmptyState); }StubWorkerClientneeds aRunDailyPrepNowCallscounter incremented inRunDailyPrepNowAsync(add if missing; it currently likely returnsTask.FromResult(true)— keep that and bump a counter). - In
TasksIslandDailyPrepTests.csremovePrepareDayCommand_raises_PrepRequested(the command is being deleted). KeepClearDayCommand_calls_worker.
- In
-
Step 2: Run — expect FAIL/compile error.
-
Step 3:
TasksIslandViewModel— remove planning trigger.- Delete the
PrepareDayAsync[RelayCommand]entirely. - Keep the
PrepRequestedevent andShowPrepLogcommand (the list icon still raisesPrepRequestedto open the window). - Grep the VM for any remaining
PrepareDayreferences and remove them.
- Delete the
-
Step 4:
TasksIslandView.axaml— remove the header button. Delete the full-width "Prepare day"<Button … Command="{Binding PrepareDayCommand}" …>. Leave the Notes pinned-row button, and the header icon buttons (broom = ClearDay, list = ShowPrepLog) untouched. -
Step 5:
DetailsIslandViewModel— add PlanDayCommand + empty-state.- Add:
[RelayCommand] private async Task PlanDayAsync() { if (_worker is null) return; try { await _worker.RunDailyPrepNowAsync(); } catch { /* worker offline; PrepStarted/PrepLine will reconcile */ } } public bool ShowPrepEmptyState => !IsPrepRunning && PrepLog.Count == 0; - Notify
ShowPrepEmptyState: in the constructor addPrepLog.CollectionChanged += (_, _) => OnPropertyChanged(nameof(ShowPrepEmptyState));, and addpartial void OnIsPrepRunningChanged(bool value) => OnPropertyChanged(nameof(ShowPrepEmptyState));.
- Add:
-
Step 6:
DetailsIslandView.axaml— prep panel toolbar + empty hint. In the<Panel IsVisible="{Binding IsPrepMode}">, wrap the existingSessionTerminalViewin aDockPanel; dock a top toolbar row with the Plan-day button, and overlay/stack an empty-state hint:<Panel IsVisible="{Binding IsPrepMode}"> <DockPanel> <Border DockPanel.Dock="Top" Padding="12,8"> <Button Classes="btn primary" Command="{Binding PlanDayCommand}" IsEnabled="{Binding !IsPrepRunning}" Content="{loc:Tr details.planDay}"/> </Border> <Panel> <islands:SessionTerminalView Entries="{Binding PrepLog}" Label="daily-prep" IsRunning="{Binding IsPrepRunning}"/> <TextBlock IsVisible="{Binding ShowPrepEmptyState}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="{DynamicResource TextMuteBrush}" Text="{loc:Tr details.prepEmpty}"/> </Panel> </DockPanel> </Panel>(Match the surrounding view's class names/brushes; use the existing button class style seen elsewhere, e.g.
Classes="btn"— verifyprimaryexists, else plainbtn.) -
Step 7: Locales. Add
details.planDay(en "Plan day", de "Tag planen") anddetails.prepEmpty(en "No prep run today yet — click Plan day", de "Heute noch keine Vorbereitung — klick Tag planen") to both json files. Remove the now-unusedtasks.prepareDaykey from both (grep first to confirm no other reference). Keep en/de key parity. -
Step 8: Build + tests.
dotnet build src/ClaudeDo.App/ClaudeDo.App.csproj -c Release dotnet test tests/ClaudeDo.Ui.Tests/ClaudeDo.Ui.Tests.csproj -c Release dotnet test tests/ClaudeDo.Localization.Tests/ClaudeDo.Localization.Tests.csproj -c Release -
Step 9: Manual smoke (human): on MyDay there is no "Tag vorbereiten" button; the list icon opens the prep window showing the empty hint; "Plan day" runs the prep and streams; the hint disappears while running; after restart the persisted last run shows and "Plan day" is available to re-run.
-
Step 10: Commit:
git commit -m "feat(daily-prep): trigger planning from inside the prep-log window with an empty-state hint"
Notes / risks
PrepRequestedandShowPrepLogCommandstay — onlyPrepareDayCommandand its header button are removed.ShowPrepEmptyStatemust re-notify on bothPrepLogchanges andIsPrepRunningchanges, else the hint won't hide when a run starts or lines arrive.- Removing
tasks.prepareDay: confirm via grep it has no remaining references before deleting (keep locale parity or the Localization.Tests parity check fails).