Files
ClaudeDo/docs/open.md
T
mika kuns 730ecb1abc docs(open): mark the usage-monitor pass done and drop the light-theme checks
The app is dark-only (App.axaml pins RequestedThemeVariant="Dark", Tokens.axaml
has no light variant), so every "Dark/Light" line was unverifiable by
construction. Adds the roadblock-reply session-id finding from the same pass.
2026-08-06 10:02:14 +02:00

25 KiB
Raw Blame History

ClaudeDo — Offene Punkte

Stand: 2026-08-06. Der Findings-Block von 2026-07-24 wurde am 2026-08-06 gegen den Code nachverifiziert (statisch, nicht in der laufenden App); alles, was inzwischen gefixt ist, ist hier entfernt — Erledigtes steht in den Commits/im Code, nicht hier. Die alte Verifikations- Checkliste lebt in docs/verification-handoff.md.


Bugs (offen)

  • Settings-Modal: Leeren eines NumericUpDown wirft InvalidCastException (gefunden bei der Sichtprüfung 2026-08-06). NumericUpDown.Value ist decimal?; sobald das Textfeld leer ist (der normale Weg, einen Wert zu ändern: alten Wert löschen, neuen tippen) schreibt die TwoWay-Bindung null in eine nicht-nullbare Ziel-Property. Betrifft acht Felder: ModelPresetRowViewModel.MaxTurns (decimal), General.MaxTurnsCeiling, General.MaxParallelExecutions, General.UsageGateFiveHourPct, General.UsageGateSevenDayPct, Worktrees.WorktreeAutoCleanupDays, Prime.DailyPrepMaxTasks, OnlineInbox.PollIntervalSeconds (alle int). Nur AgentConfigEditorViewModel.MaxTurns ist decimal? und deshalb heil. Fix-Optionen: (a) die Properties nullable machen (wie im Agent-Editor) und an den Verwendungsstellen coercen, ODER (b) ein kleiner IValueConverter, der beim ConvertBack null auf BindingOperations.DoNothing abbildet — eine Klasse plus acht Binding-Änderungen, keine DTO-/Validate-Umbauten.

  • Roadblock-Reply (und Continue) bleiben tot, wenn der Task während des Laufs offen war (Sichtprüfung 2026-08-06). LatestRunSessionId wird ausschließlich im Auswahl-Ladepfad gesetzt (DetailsIslandViewModel.cs:619). Hat man den Task schon offen, während er läuft und in den Roadblock läuft, war die Session-Id beim Auswählen noch null, und kein Live-Refresh holt sie nach: RefreshBoundTaskAsync (804) aktualisiert nur die Task-Zeile, RefreshWorktreeAsync (821) nur Worktree/Diff, der TaskFinished-Handler (364-369) ruft nur diese beiden. Ergebnis: Antwortfeld deaktiviert samt „keine Session"-Hinweis, obwohl es eine Session gibt — nach erneutem Öffnen des Tasks funktioniert es. Derselbe Gate hängt an CanContinue (1053), der Continue-Button ist also gleichzeitig tot. Fix: LatestRunSessionId beim Run-Ende mitziehen (TaskRunRepository.GetLatestByTaskIdAsync im TaskFinished-Pfad).

  • Verify-Gate wird für worktree-lose Tasks komplett übersprungen (Sichtprüfung 2026-08-06). TaskMergeService.ApproveAndMergeAsync (Zeile 537-543): hat ein Task keinen aktiven WorktreeEntity, geht der Pfad direkt auf _state.ApproveReviewAsyncDone und meldet merged — der Gate läuft nie, das verifyCommand aus LoadMergeContextAsync wird auf Zeile 532 sogar explizit verworfen (var (task, list, wt, _)). Betroffen sind genau die List-Handler-Tasks (per Design worktree-los, arbeiten via HandlerBaseCommit/HandlerHeadCommit direkt in list.WorkingDir) und Sandbox-Runs — also ausgerechnet der Lauf, der am meisten auf einmal nach main bringt. Reproduziert: bei gesetztem VerifyCommand = cmd /c exit 1 hat „Approve & Merge" den Handler-Task kommentarlos auf Done gesetzt. Fix: den Gate auch in diesem Zweig laufen lassen (Arbeitsverzeichnis ist list.WorkingDir), bevor ApproveReviewAsync gerufen wird.

  • Verify-Gate ist nur an einem von drei Merge-Einstiegspunkten verdrahtet (Sichtprüfung 2026-08-06, reproduziert mit VerifyCommand = cmd /c exit 1). Der Gate greift funktional korrekt (Merge landet, Task bleibt aus Done), aber nur DetailsIslandViewModel.ApproveReviewAsync (Zeile 1125) kennt verify_failed und zeigt result.ErrorMessage. MergeModalViewModel (Zeile 113-115) fällt in den default-Zweig und zeigt wörtlich „Unknown status: verify_failed" — der Output-Tail des Verify-Kommandos wird verworfen. WorktreesOverviewModalViewModel (Zeile 405) mappt ihn auf generisches BatchMergeOutcome.Failed, der Grund geht ebenfalls verloren. Fix: beide Stellen um einen verify_failed-Zweig ergänzen, der result.ErrorMessage durchreicht (Text existiert schon als vm.detailsIsland.verifyFailed).

  • List-Handler-Handoff lässt eine leere Geister-Pane zurück (Sichtprüfung 2026-08-06). Nach handoff_list_handler öffnet MissionControlViewModel.OpenMergeHelperHandoffConPtySessionAsync (Zeile 255) bewusst eine zweite Pane für dieselbe Task-Id und lässt die erste stehen — laut Kommentar (Zeile 250-254), damit Mika die letzte Nachricht der alten Session noch lesen kann. In der Praxis ist die alte Pane nach dem Prozessende aber komplett leer, es gibt also nichts mehr zu lesen; es bleibt nur ein toter Kachel-Platzhalter, den man von Hand schließen muss. Fix-Optionen: (a) die alte Pane beim Handoff automatisch schließen, ODER (b) ihren letzten Output erhalten und sie sichtbar als „beendet" markieren — die aktuelle Zwischenlösung erfüllt ihren Zweck nicht.

  • Worktree-Cleanup loggt „schon erledigt" als WARN (Sichtprüfung 2026-08-06). WorktreeMaintenanceService.TryRemoveAsync (Zeilen 132-198) behandelt zwei völlig normale Ausgänge wie Fehlschläge: git worktree removefatal: '<path>' is not a working tree (git kennt den Worktree längst nicht mehr) und git branch -Derror: branch '…' not found (nach dem Merge schon gelöscht). Pro DB-Zeile also zweimal LogWarning inkl. Stacktrace; BroadcastLogSink spiegelt jedes Warn in den Footer-Strip → beim Abräumen von ~20 veralteten Zeilen sieht es aus wie ein Dauerfehler, obwohl der Cleanup korrekt durchläuft. Fix: diese beiden bekannten Meldungen auf LogDebug, WARN nur für echte Fehler.

  • Verwaiste git-Worktrees sind für die App unsichtbar (gefunden 2026-08-06). In C:\Private\ClaudeDo waren nach dem Cleanup 22 git-registrierte Worktrees + 26 claudedo/*-Branches vorhanden, die ClaudeDo-DB kannte davon nur zwei. Die Worktrees-Übersicht listet ausschließlich Zeilen aus worktrees, also kann der Nutzer diese Reste nicht über die App entfernen — und es gibt keinen Sweep dafür (OrphanRecovery räumt nur Task-Zeilen auf, keine Worktrees). Wunsch: entweder ein Startup-Abgleich git worktree list ↔ DB, der Unbekannte als „untracked" in die Übersicht aufnimmt, oder mindestens eine Warnung mit Anzahl.

UX / Nits (offen)

  • Planning-aktiver Parent zeigt weiter „Idle": Parent in planning_phase=active hat Status=Idle (korrekt im Modell), aber TaskRowViewModel.StatusLabel (Zeile 132) kennt nur HasInteractiveSession/IsParked als Overrides — der PlanningBadge ersetzt den Chip nicht sichtbar → liest sich wie ein normaler Idle-Task. Wunsch: klarer „Planning/Draft aktiv"-Zustand, der Idle überschreibt. (Kinder zeigen korrekt „Draft".)
  • Blocked-by-Kette nicht sichtbar: Nach Finalize ist die sequentielle Kette korrekt gesetzt (child[i] blocked-by child[i-1]), aber die UI stellt Reihenfolge/Abhängigkeit nicht dar — es gibt nur den „waiting"-Chip. Wunsch: Kette visualisieren (z.B. „wartet auf <Vorgänger>").
  • Dequeue-„X" fehlt auf wartenden (blockierten) Kettengliedern: CanRemoveFromQueue = IsQueued || HasQueuedSubtasks (TaskRowViewModel.cs:99), IsQueued verlangt leeres blocked_by. Ein gequeuetes, aber blockiertes Kind (IsWaiting) bekommt daher kein Remove-from-queue-X — nur Parent + erstes (entsperrtes) Kind.
  • Session-Skills-Tab hat keinen Empty-State: Bei 0 installierten Skills zeigt der Skills-Tab (Settings) nur eine nackte leere Fläche unter der Install-Zeile — kein erklärender Hinweis (z.B. „Noch keine Skills installiert — GitHub-URL oben einfügen"). Im sessionSkillsTab-Locale-Namespace (en.json:674) gibt es keinen empty-Key.
  • Modal-Bodies sind unten abgeschnitten (Sichtprüfung 2026-08-06, beobachtet in den Listen-Settings: der Hinweistext unter „Verify command" ist mitten in der Zeile vom Footer weggeschnitten und lässt sich nicht herunterscrollen; laut Mika „fast überall" in den Settings-Modals). Gemeinsames Muster: <ScrollViewer Padding="20,16"> als Modal-Body — in ListSettingsModalView:36, MergeModalView:33, WorktreesOverviewModalView:131, AboutModalView:20, MergeHelperSelectionModal:47, RepoImportModalView:45, LogVisualizerView:45 sowie WorkConsole:295/395. Vermutete Ursache (nicht verifiziert): das untere Padding des ScrollViewers zählt nicht zum scrollbaren Extent, die letzten Pixel sind also unerreichbar. Erst am echten Fall nachmessen, dann ggf. einheitlich das Padding vom ScrollViewer auf ein Margin des inneren Inhalts umziehen.
  • Usage-Monitor-Modal: Analyse-Tabellen ausbaufähig (Sichtprüfung 2026-08-06; Gauges, Info-Bänder, Presets/Custom-Range und Refresh-Button sind in Ordnung). Models-Tab: die Spaltenköpfe „OTHER CACHE" und „SHARE" kollidieren zu OTHER CACHISHARE; claude-haiku-4-5-20251001 läuft in die IN-Spalte; alle Zahlen linksbündig und ohne Tausendertrenner (506830708). Tasks-Tab: Task-Titel wird ohne Ellipse hart an der LIST-Spalte abgeschnitten, der LIST-Text ebenfalls; MODEL ist bei Runs von vor der task_runs.model-Spalte leer (besser „—"). Wunsch: Zahlen rechtsbündig + #,##0 (oder k/M), Spaltenbreiten/Truncation fixen.
  • Conflict-Resolver: mehrere Konfliktdateien schlecht erkennbar: Beim 2-Datei-Konflikt schwer zu sehen, dass zwei Dateien betroffen sind (File-Switcher/Anzahl zu unauffällig). Prominentere Datei-Liste / „x von y Dateien".
  • Attachments: erster Drag&Drop der Session schlug einmalig fehl („An error occurred"): Beim allerersten Drop-to-attach einer UI-Session zeigte die DropStatus-Zeile inline einen generischen Fehler und es wurde nichts persistiert (kein File, keine DB-Row); alle folgenden Drops derselben Session + der „Add file…"-Picker + Remove funktionierten fehlerfrei. Nicht reproduzierbar nach dem ersten Mal. Kandidaten: transiente SQLite-Contention (der UI-Prozess schreibt todo.db direkt via new TaskAttachmentRepository, während der Worker dieselbe DB hält) ODER ein Fehler im Drop-Stream-Pfad (IStorageFile.OpenReadAsync im Code-Behind, außerhalb des try in AddFilesAsync). Falls es erneut auftritt: AddFilesAsync/OnDrop mit robusterem Error-Logging versehen.

Feature-Wünsche

  • Conflict-Resolver: farbliches Hervorheben eingefügter Zeilen im Result-Pane (grüner „flow" der übernommenen Zeilen).
  • Die Handler-Session soll „Submit for review" selbst auslösen können (Sichtprüfung 2026-08-06). Aktuell ist der Abschluss eines List-Handler-Laufs ein reiner Handgriff über die Schaltfläche in der Mission-Control-Kachel — die Session selbst hat kein Werkzeug dafür, obwohl sie am besten weiß, wann sie fertig ist. Wunsch: ein MCP-Tool auf der In-Task-Oberfläche, das denselben Pfad wie der Button nimmt.
  • Handoff-Kachel besser beschriften (Sichtprüfung 2026-08-06). Die zweite Kachel heißt Merge Helper — <Liste> (Handoff) bzw. „(Übergabe)" (missionControl.mergeHelperHandoffTitleSuffix, en.json/de.json:297). „Handoff" ist internes Vokabular und sagt nicht, was die Session tut. Besser etwas, das die Rolle nennt (Ausführen + Mergen der verbliebenen Tasks, Phasen 3-5).

Design-Entscheidungen (27.07.-Batch, Sichtprüfung am 2026-08-06 abgeschlossen)

Der Sichtprüfungs-Block dieses Batches (Ctrl+K/#, Titel-Edit, ConPTY-/Refine-Spinner, Interactive-Chip, Diff-Viewer-Abstände, Manual-Tasks, Vorgaben-pro-Modell-Tabelle) ist von Mika verifiziert und deshalb hier entfernt. Es bleiben die Entscheidungen, die daran hängen:

  • Interaktive ConPTY-Sessions bekommen --effort, aber kein --model — die Session läuft weiter unter dem Modell aus Mikas Claude-Config, der Effort kommt aus dem Preset des Modells, das ClaudeDo für die Task auflösen würde. Falls ClaudeDo auch interaktiv das Modell erzwingen soll, ist das ein Folge-Task.
  • AppSettings.DefaultMaxTurns ist jetzt tatsächlich verdrahtet (ModelPresets.For(..., global.DefaultMaxTurns) in TaskRunner.ResolveConfigAsync): reiner Fallback für ein Modell, das auch nach ModelRegistry.TryNormalizeAlias auf keine Preset-Zeile trifft — vorher war das Feld tot (hartkodierte 30). Hat weiterhin keinen eigenen Editor mehr (nur die Preset-Tabelle pro Modell); Spalte könnte später entfallen, falls das nie zutrifft.

Beobachtung (offen — Entscheidung Mika)

  • --permission-mode auto + Modell haiku → Writes werden denied: Kontrolliert verifiziert (CLI 2.1.207): unter dem Default-Mode auto bekommt sonnet Writes auto-approved (permission_denials:[]), haiku wird denied (permission_denials:[Write], keine Datei) — eine haiku-Task macht unter auto still nichts und landet ohne Änderung in WaitingForReview. Normalbetrieb (Default = sonnet) nicht betroffen. KEINE CLI-Regression, sondern modellabhängiges auto-Verhalten. Optionen falls es nervt: haiku aus der Auswahl nehmen, ODER Runner auf acceptEdits/bypassPermissions (modell-unabhängig). Mika: erstmal beobachten. Siehe Memory auto_permission_haiku_footgun.
  • QueueServiceTests.UsageGate_TransitionLogging_FiresOncePerChange ist zeitbasiert flaky, unabhängig von dieser Session: Schlägt reproduzierbar fehl (Expected 1, Actual 0 Warn-Log-Aufrufe), sowohl solo (--filter) als auch im Vollauf, auf einem sauberen git worktree add gegen main (bdee731) — also kein durch diese Abschluss-Session verursachter Regress (die Session hat keine .cs-Datei angefasst). Ursache: der Test verlässt sich auf einen festen Task.Delay(200), um mehrere 50-ms-Backstop-Ticks abzuwarten (Kommentar im Test: „Several backstop ticks (50ms interval) all observe the same blocked state"); auf einer stark ausgelasteten Maschine (hier: viele parallele ClaudeDo-Worktrees/Builds) reicht das Fenster nicht immer. Zum Vergleich: derselbe Test lief in einer zweiten, isolierten Verifikation (Scratch-Merge für den Environment-Checks-Task) sauber durch (876/876). Fix wäre ein Poll-basiertes Warten statt fixem Sleep — aber außerhalb des Scopes dieser Doku/Verifikations-Session (keine Code-Änderung angefasst).

Offene Verifikation (2026-07-27)

  • List handler (2026-07-27) — visual pass: the Broom button is gone from the lists footer, the context-menu item appears only on lists with a working dir, and the selection dialog has no LIST column. (Der real-Claude-Smoke-Run der fünf Phasen ist am 2026-07-29 gelaufen — 6/6 sauber gemerged; nur die Sichtprüfung ist noch offen.)

Offene Verifikation (2026-08-05)

  • List handler owns a task (2026-08-05)visuell verifiziert am 2026-08-06 (Lauf über die Liste ClaudeDoTests mit 4 Tasks, davon 2 absichtliche Dubletten): genau ein neuer Task, Mission- Control-Tile task-basiert mit „Submit for review", Dedupe hat die Dublette erkannt, Beschreibungen wurden angereichert, Submit → WaitingForReview, und die Diff-Karte zeigte alle drei Dateien des Laufs. Korrektur zur Erwartung oben: der Task-Chip liest sich „Interactive", nicht Idle — das ist korrekt so (HasInteractiveSession überschreibt den Status-Chip, solange die ConPTY-Session läuft). Die drei dabei gefundenen Punkte stehen unter „Bugs" bzw. „Feature-Wünsche".

  • Roadblock reply field (2026-08-05)Kernfunktion am 2026-08-06 verifiziert: auf einem Task mit gemeldetem Roadblock erscheint das Antwortfeld unter dem Roadblock-Text, die Antwort setzt die Session fort, und der Task landet danach sauber auf WaitingForReview. Dabei ist der Bug oben aufgefallen (Feld deaktiviert, solange der Task seit vor dem Lauf offen ist). Layout der Roadblock-Karte ist in Ordnung. Noch offen: Enter-zum-Senden, und dass ein „Override-Slot besetzt"-Fehler im Footer-Strip landet (nicht als Modal) mit dem getippten Text weiterhin im Feld. Design-Entscheidung dazu: der Review-Bereich lebt als zwei nullable Spalten direkt auf TaskEntity (kein Phantom-WorktreeEntity), damit list_worktrees/die Worktrees-Übersicht ihn nie sehen.

  • Post-merge verify gate (2026-08-05) — build + unit tests all green (incl. real-process VerifyCommandRunner exit-code/output/timeout tests and TaskMergeService success/failure/ timeout paths via a fake runner), but not visually verified: open a list's Settings modal, confirm the new "VERIFICATION" section renders below Agent with a settable/clearable VerifyCommand field; approve a task on a list with a failing command configured and confirm the footer/error surfacing (ShowErrorAsync) actually shows the verify failure message instead of silently looking like nothing happened. Also no real-build smoke test (a real dotnet build/ dotnet test invocation as the configured command) — only fast synthetic commands (exit N, ping for timeout) were exercised.

Offene Verifikation (2026-08-06, Resume planning session)

planning_session_id wurde nie befüllt (der Setter hatte keinen Aufrufer), weil die interaktive Planning-Session ihre claude-Session-Id nie zurückmeldet — Resume konnte deshalb nie funktionieren. PlanningSessionManager.ResumeAsync liest die Id jetzt beim ersten Resume aus dem Transkript, das Claude Code unter ~/.claude/projects/<encodiertes cwd>/<sessionId>.jsonl für den Planning-Worktree ablegt (PlanningTranscriptLocator), und persistiert sie. Unit-Tests grün, nicht visuell verifiziert:

  • Planning-Session starten, Fenster/Pane schließen, Task erneut öffnen → „Resume" muss die ConPTY-Pane mit der fortgesetzten Unterhaltung öffnen (nicht mit leerem Verlauf).
  • Ohne Transkript (z. B. Session nie wirklich gestartet): Fehlermeldung „No Claude session transcript found…" landet sichtbar im Footer-Error-Strip (Terminal.StartErrorErrorReported), nicht still.
  • Risiko: das Verzeichnis-Encoding (~/.claude/projects/, jedes Nicht-Alphanumerische wird -) ist undokumentiertes CLI-Verhalten — ändert es sich, findet der Locator nichts und Resume meldet sauber „cannot resume" (fail-safe, kein falscher Resume).

Offene Verifikation (2026-08-05, Usage Monitor)

Kein Light-Theme. App.axaml:6 setzt RequestedThemeVariant="Dark" fest, es gibt keinen Umschalter und Tokens.axaml kennt keine Light-Variante. „Dark/Light"-Checks sind deshalb überall aus dieser Datei entfernt — sie waren nie erfüllbar.

  • Visueller Pass Usage-Pill (Footer und Mission-Control-Header) — am 2026-08-06 verifiziert: Text/Tooltip lesbar, Dot-Zustände plausibel, Pill in Footer und Mission-Control-Header identisch.
  • Visueller Pass Usage-Monitor-Modalam 2026-08-06 verifiziert: Gauges (dynamisch aus limits[]), Info-Bänder (der Throttle-Hinweis „Queue throttled: 1/3 slots (7d)" stand real an), 7d/30d-Presets + Custom-Range. Die Analyse-Tabellen sind ausbaufähig → siehe „UX / Nits".
  • E2E Gate: das Gate greift real, sobald ein Bucket (five_hour/seven_day) die konfigurierte Schwelle reißt — Queue-Nachschub pausiert, laufende Runs/RunNow/ConPTY/ Planning/Prime bleiben unberührt — und die Queue nimmt nach dem Reset selbstständig wieder auf (30s-Backstop, kein persistenter Pause-Zustand).
  • Risiko: der Usage-Endpoint (GET https://api.anthropic.com/api/oauth/usage) ist undokumentiert und kann sich ändern; bei Ausfall/Formatänderung ist das Gate wirkungslos (fail-open by design — kein Blocker, aber der Schutz fällt dann aus, ohne dass es auffällt).

Nachtrag 2026-08-05: 429-Fix (Poll-Kadenz + Refresh-Button)

Der 60s-Poll lief in 429s. Neu: aktivitätsabhängige Kadenz (5 Min. solange ein Task Running ist, sonst 15 Min.), 429-Backoff mit Retry-After, und ein „Jetzt aktualisieren"-Button im Usage-Monitor-Modal (RefreshUsageUsageMonitorService.RefreshNowAsync, 10s-Cooldown). Unit-Tests grün, offen:

  • Visueller Pass Refresh-Button im Modal — am 2026-08-06 verifiziert (Button, Hinweiszeile „Polled every 5 min while a task runs, otherwise every 15 min.").
  • E2E: über ≥20 Min. mit und ohne laufenden Task beobachten, dass keine 429s mehr im Worker-Log auftauchen und die Pill trotzdem aktuell bleibt.
  • Beachten: die Pill wird jetzt erst nach 3× 15 Min. als stale markiert — ein echter Endpoint-Ausfall fällt vorher nur über LastError auf (der IsStale sofort setzt).

Offene Verifikation (2026-08-05, Max-Turns-Ceiling)

Build + unit tests grün (ResolveMaxTurns-Klemmung, Repository-Backfill von model_presets, Migration AddMaxTurnsCeiling gegen eine Scratch-DB angewendet), aber nicht visuell verifiziert:

  • Agent-Settings-Editor (Task und Liste): Max-Turns-Feld auf einen Wert über der Ceiling (Default 80) setzen, Hinweistext unter dem NumericUpDown erscheint ("Runs are capped at {N} turns…").
  • Settings → Allgemein → Vorgaben pro Modell: eine Zeile über 80 setzen, derselbe Hinweistext erscheint unter der Zeile.
  • MaxTurnsCeiling ist seit 2975f90 selbst editierbar (Settings → Allgemein, SettingsModalView.axaml) — Feld prüfen: Wert ändern, speichern, Hinweistexte oben ziehen mit.

Offene Verifikation (2026-08-05, Environment Checks / SystemCheckPage)

Checks + SystemCheckPage (claudedo/06aca9b3…) und das ExecutableResolver-Wiring im Worker (claudedo/40272c0b…) sind seit 2026-08-06 auf main gemerged; die frühere „erst mergen"- Voraussetzung ist erledigt. Details → installer-preflight in docs/explore-notes/README.md und der Abschnitt „Environment Checks" in src/ClaudeDo.Installer/CLAUDE.md.

Update (2026-08-06): beide Folge-Features sind jetzt implementiert und auf main.

  • Diagnose-Sektion (Config-Modus/SettingsWindow): Pages/DiagnosePage/ + geteilte Checks/CheckListViewModel.cs/Checks/CheckListView.xaml (auch von SystemCheckPage genutzt, keine zweite Implementierung). Unit-getestet (tests/ClaudeDo.Installer.Tests/Pages/DiagnosePage/DiagnosePageViewModelTests.cs).
  • „Claude Help Me"-Button: Core/ClaudeHelpLauncher.cs + SystemCheckPageViewModel/-View, unit-getestet (tests/ClaudeDo.Installer.Tests/Core/ClaudeHelpLauncherTests.cs).

Beides nicht visuell verifiziert:

  • Help-Me-Button ist deaktiviert, wenn claude-cli nicht Ok ist oder claude-auth Failed ist (bleibt aktiv bei Unknown), mit erklärendem Tooltip — unit-getestet.
  • „Claude Help Me" öffnet tatsächlich ein Terminal mit laufender Claude-Session, und die Session hat den Diagnose-Report gelesen — nicht verifiziert (der eigentliche Terminal-Start/wt.exe-Zusammenspiel und die Session-Qualität sind nur über die injizierte IProcessLauncher-Fake getestet, nie mit einem echten Terminal/CLI).
  • Platzierung des Help-Me-Buttons: er sitzt seit dem Merge der Diagnose-Sektion in einer eigenen Zeile unter dem geteilten Check-Listen-Footer (der reservierte Slot im Footer entfiel mit der Extraktion nach CheckListView.xaml). Optisch prüfen, ob das so bleiben soll oder ob der Button in den geteilten Footer gehört.
  • Diagnose-Sektion im Config-Modus: Öffnen von SettingsWindow löst keinen Prüflauf aus, Klick auf „Erneut prüfen" schon; zeigt die echten installierten Pfade/Ports (nicht die InstallContext-Defaults), und der laufende Worker auf dem konfigurierten SignalR-Port gilt nicht als Konflikt — unit-verifiziert, visueller Durchlauf noch offen.

Weitere Punkte, gebaut + unit-getestet auf main, aber nicht visuell verifiziert:

  • SystemCheckPage: Layout, Icon-/Farbwirkung der vier Status (Ok grün / Warnung orange / Fehler rot / Unbekannt grau — StatusGreenBrush/StatusOrangeBrush/StatusRedBrush/ StatusGrayBrush), Lesbarkeit der Hint-Texte, DE und EN.
  • Weiter-Button gesperrt bei einem echten blockierenden Fehler (z. B. claude nicht im PATH → claude-cli Error/Failed), und der Grund ist in der Zusammenfassungszeile sichtbar (nennt den/die blockierenden Check(s) namentlich).
  • „Erneut prüfen" wechselt einen Status live (z. B. git-Identity setzen → Warnung verschwindet), ohne dass ein zweiter paralleler Lauf startet, wenn währenddessen erneut geklickt wird.
  • Update-Modus zeigt die SystemCheckPage nicht (Wizard bleibt Welcome + Install).
  • Auf einem Rechner mit npm-installiertem claude.cmd: claude-cli-Check findet es (Detail-Text „Resolved via a shim…"), und ein Task läuft im Worker durch (bestätigt, dass ClaudeProcess/ClaudeCliPreflight den Shim über cmd.exe /c tatsächlich startet, nicht nur, dass der Check ihn findet).

Bewusst verworfen (nicht erneut vorschlagen)

  • CI-Build/Test-Pipeline — push-to-main + release-on-push deckt das ab; Tests laufen am Ende jeder Session.
  • Real-claude-Smoke-Test als xUnit-Test — kein Claude in dotnet test; bleibt manueller Check. Tests nutzen FakeClaudeProcess.
  • architecture.md / ADRs — die per-Projekt-CLAUDE.md-Dateien sind die lebende Doku.
  • Task-Mailbox-Integration — geparkt; das generische mcp__mailbox__*-Plugin reicht (mailbox-proposal.md).
  • Tag-Negation, Tag-Multi-Select, Notes-lists.kind-Switch, Install-Service-Skript — durch die aktuelle Architektur überholt.