From eca16a35062b602ff30cf368764d9d205999a46a Mon Sep 17 00:00:00 2001 From: mika kuns Date: Tue, 11 Aug 2026 19:32:41 +0200 Subject: [PATCH] =?UTF-8?q?docs(plans):=20grobe=20Task-Entw=C3=BCrfe=20je?= =?UTF-8?q?=20Gruppe=20und=20Test-Kommandos=20erg=C3=A4nzen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plans/2026-08-11-operation-feedback.md | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/docs/superpowers/plans/2026-08-11-operation-feedback.md b/docs/superpowers/plans/2026-08-11-operation-feedback.md index 59515a94..e083aa6e 100644 --- a/docs/superpowers/plans/2026-08-11-operation-feedback.md +++ b/docs/superpowers/plans/2026-08-11-operation-feedback.md @@ -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 -- ` — 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