docs(plans): grobe Task-Entwürfe je Gruppe und Test-Kommandos ergänzen

This commit is contained in:
mika kuns
2026-08-11 19:32:41 +02:00
parent 260cb5a89c
commit eca16a3506
@@ -60,6 +60,17 @@ Gilt für alle vier Gruppen:
dotnet build src/ClaudeDo.App/ClaudeDo.App.csproj -c Release
dotnet build src/ClaudeDo.Worker/ClaudeDo.Worker.csproj -c Release
```
- **Testen — pro Gruppe die relevanten Projekte:**
```
A, B dotnet test tests/ClaudeDo.Ui.Tests/ClaudeDo.Ui.Tests.csproj -c Release
dotnet test tests/ClaudeDo.Localization.Tests/... -c Release (nur wenn Keys berührt)
C Ui.Tests + ClaudeDo.Worker.Tests (Worker.Tests enthält auch UiVm-Tests)
D dotnet test tests/ClaudeDo.Worker.Tests/ClaudeDo.Worker.Tests.csproj -c Release
P0 Ui.Tests + Localization.Tests
```
Fällt ein Test innerhalb der Verify-Kette, erst die Suite **allein** laufen lassen — die
`Ui.Tests` haben eine bekannte reihenfolgen-abhängige Flakiness, die nichts mit dem Merge zu
tun hat.
- **Nie `git add -A`.** Immer explizit nach Pfad stagen und `git commit -- <pfade>` — der
`main`-Checkout ist von parallelen Sessions geteilt, ein blankes Commit fegt fremde WIP mit.
- **Nach dem Batch-Merge `main` selbst prüfen.** Approve baut und testet nicht. Neun grüne
@@ -152,6 +163,28 @@ Prozess startet, oder O(n) über unbegrenzt viele DB-Zeilen läuft. Einzelzeilen
Label und setzt die Stall-Uhr zurück. `Localization.Tests` grün. Kein VM ist umgestellt — P0
liefert nur das Werkzeug.
### Task-Entwürfe (grob)
**P0-1 · `OperationStatus` + `OperationIndicator` + `ops`-Locale-Keys**
Baue das Primitive nach dem Vertrag oben, dazu das Anzeige-Control und den neuen
Locale-Namespace `ops` in beiden Sprachdateien. Keys für Gruppe A und C vorab anlegen, für D
keine. Zeitquelle über `TimeProvider`, kein statischer Timer.
*Dateien:* `Ui/Services/OperationStatus.cs` (neu), `Ui/Views/Controls/OperationIndicator.axaml(.cs)` (neu), `Localization/locales/{en,de}.json`, `tests/ClaudeDo.Ui.Tests/`
*Fertig wenn:* Unit-Tests für Grace, Stall-ab-Report, Elapsed, Dispose-nach-Exception, Report-Reset. Localization.Tests grün. Kein ViewModel angefasst.
**P0-2 · Timing-Hook für die Messung**
Zwei Hooks: Dauer jedes Hub-Invokes in `WorkerClient`, Dauer des DB-Pfads der Islands. Ziel
sind auswertbare Zahlen, keine Anzeige. Ausgabe so, dass sie nach einem Tag Nutzung sortierbar
ist.
*Dateien:* `Ui/Services/WorkerClient.cs`, der gemeinsame DB-Zugriffspfad der Island-VMs
*Fertig wenn:* Beide Hooks aktiv, Overhead vernachlässigbar, das Format ist dokumentiert.
**P0-3 · Feedback-Regel in den CLAUDE.md-Dateien**
`src/ClaudeDo.Ui/CLAUDE.md`: jeder `IWorkerClient`-Call in einem `[RelayCommand]` läuft durch
eine `OperationStatus`, Anzeige über `OperationIndicator`. `src/ClaudeDo.Worker/CLAUDE.md`: ein
MCP-Tool, das über ~5 s laufen kann, reportet Progress.
*Fertig wenn:* Beide Regeln stehen, jeweils mit einem Satz Begründung.
---
## Gruppe A — Bild 1: UI-Stille
@@ -201,6 +234,42 @@ Zustand nach einer Exception zurückgesetzt — als Test in `ClaudeDo.Ui.Tests`.
handgebauter Spinner, immer `OperationIndicator`. **Visuelle Prüfung offen und explizit
benannt** (Grace-Periode und Layout kann kein Test bestätigen).
### Task-Entwürfe (grob)
**A1 · Detail-Pane: Approve, Submit, Reject, Park, Preview** ⚠️ *der gemeldete Fall*
Fünf Commands im Detail-Pane bekommen je eine `OperationStatus` und einen `OperationIndicator`
neben dem auslösenden Button. Approve abonniert zusätzlich `MergeProgressEvent` **nur für die
Dauer des Calls** und filtert auf die eigene TaskId, um das Label von „merging" auf „verifying"
zu schärfen. `DetailsIslandViewModel` nicht umstrukturieren.
*Dateien:* `Ui/ViewModels/Islands/DetailsIslandViewModel.cs`, `MergeSectionViewModel.cs`, `Ui/Views/Islands/Detail/*`
*Fertig wenn:* Approve zeigt während des Verify-Gates Phase und Elapsed, Button ist gesperrt, Zustand nach Fehler zurückgesetzt. Visuelle Prüfung offen.
**A2 · WorktreesOverview: Anzeige für alle fünf Aktionen**
`IsBusy` existiert, schaltet aber nur `IsEnabled`. Getrennte `OperationStatus` für Refresh,
Cleanup, Reset, ForceRemove und Batch-Merge — der Batch-Merge zusätzlich mit Zeilen-Status, weil
er N Tasks sequenziell durchläuft.
*Dateien:* `Ui/ViewModels/Modals/WorktreesOverviewModalViewModel.cs`, `Ui/Views/Modals/WorktreesOverviewModalView.axaml`
*Fertig wenn:* Jede der fünf Aktionen zeigt sichtbar, dass sie läuft; ein laufender Refresh blockiert die Cleanup-Anzeige nicht. Visuelle Prüfung offen.
**A3 · Settings-Tabs: Skill-Install, Restore-Defaults, OnlineInbox, RepoImport, Update-Check**
Fünf Flächen, bei denen `IsBusy` heute nur den Button sperrt. Der Skill-Install ist ein
`git clone` und der offensichtlichste Kandidat.
*Dateien:* `Ui/ViewModels/Modals/Settings/*`, `Ui/ViewModels/Modals/RepoImportModalViewModel.cs`, `Ui/Services/UpdateCheckService.cs`, `Ui/Views/Modals/SettingsModalView.axaml`
*Fertig wenn:* Alle fünf zeigen Aktivität; der Skill-Install zeigt zusätzlich, dass geklont wird. Visuelle Prüfung offen.
**A4 · Reports und Planning-UI**
GenerateWeekReport, RunDailyPrepNow, BuildPlanningIntegrationBranch, GetPlanningAggregate,
Finalize/QueuePlanningSubtasks. `DiffViewerViewModel.IsLoadingCombined` existiert bereits und
bleibt unangetastet.
*Dateien:* `Ui/ViewModels/Modals/WeeklyReportModalViewModel.cs`, Planning-Pfade in `DetailsIslandViewModel`/`TasksIslandViewModel`, zugehörige AXAML
*Fertig wenn:* Report-Generierung und Planning-Integration zeigen Aktivität; kein Doppel-Indikator im Combined-Diff. Visuelle Prüfung offen.
**A5 · Island-DB-Pfade nach Messdaten**
**Erst die Zahlen aus P0-2 auswerten**, dann nur die Ausreißer umstellen. Kandidaten:
`ClearCompleted`, Drag-Reorder über viele Zeilen, Laden großer Listen. Nichts auf Verdacht.
*Dateien:* nach Messergebnis
*Fertig wenn:* Die Auswertung ist im Task dokumentiert, und jede umgestellte Stelle ist durch eine Messung begründet. Wenn nichts über der Schwelle liegt: Task mit Begründung schließen, nichts bauen.
---
## Gruppe B — Bild 2: UI-Freeze
@@ -235,6 +304,31 @@ B3 ist der einzige Test im Vorhaben, der Blockade prüft: großes Diff-Fixture,
der Dispatcher weiter Nachrichten verarbeitet. Visuelle Prüfung offen (Verhalten bei großem
Diff, Indikator während des Parsens).
### Task-Entwürfe (grob)
**B1 · `UnifiedDiffParser.Parse` vom UI-Thread nehmen**
Beide Aufrufstellen im `DiffViewerViewModel` nach `Task.Run` verschieben, danach den
`OperationIndicator` setzen. Reihenfolge ist zwingend: erst auslagern, dann anzeigen — ein
Spinner auf einem blockierten Dispatcher wird nicht gezeichnet. Das Zurückschreiben in
Observable-Collections muss auf dem UI-Thread passieren.
*Dateien:* `Ui/ViewModels/Modals/DiffViewerViewModel.cs`
*Fertig wenn:* Kein synchroner Parse mehr im VM, Indikator während des Parsens sichtbar. Visuelle Prüfung mit einem großen Diff offen.
**B2 · `DiffAlignment.Build` — Grenze gegen unbegrenzte Synchron-Arbeit**
`Build` läuft in einem Control, nicht in einem VM. Der ausführende Agent entscheidet zwischen
Auslagern ab einer Zeilenzahl und inkrementellem Aufbau — die Vorgabe ist nur: **eine
sichtbare, begründete Grenze**. AvaloniaEdit-Fallen aus dem Vorgaben-Abschnitt beachten
(`TryGetResource` scheitert lautlos, `ScrollToVerticalOffset` ist ein No-op).
*Dateien:* `Ui/Views/Controls/DiffTextView.axaml.cs`, gemeinsames Boilerplate nach `DiffEditorSetup.cs`
*Fertig wenn:* Die gewählte Grenze ist im Code kommentiert und begründet; große Diffs blockieren nicht mehr unbegrenzt. Visuelle Prüfung offen.
**B3 · Guard-Test: großer Diff blockiert den Dispatcher nicht**
Headless-Test mit großem Diff-Fixture, der nachweist, dass der Dispatcher während Parse und
Build weiter Nachrichten verarbeitet. Der einzige Blockade-Test im Vorhaben — soll auch
zukünftige Regressionen fangen.
*Dateien:* `tests/ClaudeDo.Ui.Tests/`, Fixture im Testprojekt
*Fertig wenn:* Der Test fällt gegen den Stand **vor** B1/B2 und ist danach grün.
---
## Gruppe C — Bild 3: Worker-Stille
@@ -284,6 +378,42 @@ Progress-Callbacks in `ClaudeDo.Worker.Tests` mit einem Fake gezählt — keine
keine echte CLI. UI-Seite: die Anzeige beim Worker-Start ersetzt „reconnecting" durch die
laufende Recovery-Phase. Visuelle Prüfung offen.
### Task-Entwürfe (grob)
**C1 · Generischer `OperationProgress`-Kanal, `MergeProgress` darauf umstellen**
Neues Hub-Event `OperationProgress(opKey, phase, current, total)`, ohne Elapsed auf der Leitung.
Der Merge-Pfad sendet darüber. **`MergeProgressEvent` bleibt als vierzeiliger Forwarder** —
Gruppe A hängt daran und darf nicht angefasst werden. Fakes in beiden Testprojekten mitziehen.
*Dateien:* `Worker/Hub/HubBroadcaster.cs`, `Worker/Hub/WorkerHub.cs`, `Ui/Services/WorkerClient.cs`, `IWorkerClient.cs`, `tests/ClaudeDo.Ui.Tests/StubWorkerClient.cs`, UiVm-Fakes in `Worker.Tests`
*Fertig wenn:* Merge-Phasen laufen über den neuen Kanal, das UI tickt Elapsed lokal, `MergeProgressEvent` funktioniert unverändert weiter, beide Testprojekte grün.
**C2 · Worker-Startup-Recovery sichtbar machen**
Die sechs Recovery-Services beim Worker-Start melden Phase und `i/n` über den Kanal
(`opKey = "startup-recovery"`). Das UI ersetzt „reconnecting" durch die laufende Phase.
*Dateien:* `Worker/Lifecycle/*Recovery.cs`, Anzeige im `IslandsShellViewModel`-Umfeld
*Fertig wenn:* Beim Worker-Start ist sichtbar, welche Recovery läuft. Visuelle Prüfung offen.
**C3 · Worktree-Anlage beim Task-Start sichtbar machen**
**Zuerst prüfen**, ob der im 08-07-Spec gemeldete Broadcast-Gap in `WorktreeManager` inzwischen
geschlossen ist — nicht doppelt beheben. Danach die stille Lücke zwischen `Queued` und erster
Ausgabe an der Task-Zeile sichtbar machen.
*Dateien:* `Worker/Runner/WorktreeManager.cs`, Task-Row-Anzeige
*Fertig wenn:* Das Prüfergebnis steht im Task; die Anlage-Phase ist an der Zeile sichtbar. Visuelle Prüfung offen.
**C4 · Rebase-after-Merge und WorktreeMaintenance in den Kanal**
`RebaseOthersAfterMergeAsync` läuft heute innerhalb des Merge-Calls **nach** dem
Phasen-Broadcast und ist damit vollständig unsichtbar. Dazu der Hintergrunddienst über alle
Worktrees, mit `i/n`.
*Dateien:* `Worker/Lifecycle/TaskMergeService.cs` (Rebase-Abschnitt), `Worker/Worktrees/WorktreeMaintenanceService.cs`
*Fertig wenn:* Beide melden Fortschritt; ein Merge zeigt nach dem Verify-Gate die Rebase-Phase statt Stille.
**C5 · Periodische Dienste — optional, Abbruch erlaubt**
Usage, OnlineSync, Prime, Queue sollen **nur Aktivität und Fehler** melden, keinen Tick-Strom.
Der wackeligste Punkt im Design: kommt der ausführende Agent zum Schluss, dass das nur
Anzeige-Rauschen erzeugt, **weglassen und begründen** statt durchziehen.
*Dateien:* `Worker/Usage/`, `Worker/Online/`, `Worker/Prime/`, `Worker/Queue/`
*Fertig wenn:* Entweder sparsame Meldungen ohne Rauschen — oder eine begründete Absage im Task.
---
## Gruppe D — Bild 4: MCP-Stille
@@ -321,6 +451,37 @@ Für jedes umgestellte Tool ein Test in `ClaudeDo.Worker.Tests`, der mit einem F
zählt, dass Meldungen kommen — bei `batch_*` mindestens eine pro Element. Keine visuelle
Prüfung nötig, diese Gruppe hat keine UI.
### Task-Entwürfe (grob)
**D1 · `ProgressReporter` extrahieren**
`TaskMergeService.RunReportingProgressAsync` als eigenständige Klasse herauslösen, plus einen
Overload für Element-Fortschritt (`i/n`). **Extrahieren, nicht kopieren** — es soll eine
Implementierung bleiben. Dies ist die einzige Datei, die D mit C teilt; nur die Progress-Schleife
anfassen.
*Dateien:* `Worker/Lifecycle/TaskMergeService.cs`, neue Klasse im Worker-Projekt
*Fertig wenn:* Der Merge-Pfad nutzt die extrahierte Klasse, Verhalten unverändert, bestehende Merge-Tests grün.
**D2 · Die acht `batch_*`-Tools mit Element-Fortschritt**
Jedes `batch_*`-Tool reportet pro verarbeitetem Element. Grund: ohne Meldung bricht der
MCP-Client nach 300 s Stille ab, während der Worker weiterläuft — genau der Mechanismus, der
einen Merge durchlaufen lässt, den Task aber nie auf `Done` bringt.
*Dateien:* `Worker/External/BatchMcpTools.cs`
*Fertig wenn:* Pro Tool ein Test mit Fake-`IProgress`, der mindestens eine Meldung je Element zählt. Englische Klartext-Strings, keine Locale-Keys.
**D3 · Worktree- und Diff-Tools mit Progress**
`cleanup_task_worktree`, `batch_cleanup_task_worktrees`, `get_task_diff`, `preview_merge_set`.
Bereits versorgt und **nicht** anzufassen: die fünf Tools mit `IProgress` in
`ExternalMcpService`, `TaskWaitMcpTools`, `merge_task`, `review_task`.
*Dateien:* die betroffenen `Worker/External/*McpTools.cs`, `ExternalMcpService.cs`
*Fertig wenn:* Jedes der vier Tools meldet Fortschritt, mit Test.
**D4 · Restliche Long-Runner und die Regel im Worker-`CLAUDE.md`**
Verbleibende Tools durchgehen, die über ~5 s laufen können, und die Regel festschreiben: ein
MCP-Tool über ~5 s reportet Progress. Ohne die Regel wiederholt sich das Muster beim nächsten
Tool.
*Dateien:* restliche `Worker/External/*McpTools.cs`, `src/ClaudeDo.Worker/CLAUDE.md`
*Fertig wenn:* Die Regel steht mit Begründung; die durchgegangenen Tools sind im Task aufgelistet — auch die, die bewusst nichts bekommen.
---
## Was nach allen vier Gruppen offen bleibt