# 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`. --- ## 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 "). - **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. - **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). ## 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)** — build + unit tests all green, but **not visually verified**: start "Let Claude handle it" on a list, confirm exactly one new task appears in that list (`Idle`, MANUAL badge, title "List handler: "), the Mission Control tile is task-based (Submit for review button present), Submit for review flips it to `WaitingForReview`, and the detail pane's diff/merge card shows the full range of everything the run merged to main (via the new `HandlerBaseCommit`/`HandlerHeadCommit` fallback — no `WorktreeEntity` is created for this task, so the diff comes from `list.WorkingDir` directly). - **Roadblock reply field (2026-08-05)** — build + unit tests all green, but **not visually verified**: on a `Done` (or `WaitingForReview`/`Failed`/`Cancelled`) task with a reported roadblock, the ROADBLOCK card shows a reply textbox + Send button under the roadblock text. Check layout/spacing against the AskUser question card it's modeled on, Enter-to-send, the disabled state + hint text when there's no session ID to resume, and that an override-slot-busy error shows up in the footer log strip (not a modal) with the typed text still in the field. Approve should go straight to `Done` with no merge attempt. Design choice: the review range lives as two new nullable columns directly on `TaskEntity` (not a phantom `WorktreeEntity` row), specifically so `list_worktrees`/the Worktrees overview never see it. - **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//.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.StartError` → `ErrorReported`), 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) - **Visueller Pass Usage-Pill** (Footer **und** Mission-Control-Header): Text/Tooltip, Dot-Zustände normal/warn/stale/blocked, Dark/Light. - **Visueller Pass Usage-Monitor-Modal**: Gauges (dynamisch aus `limits[]`), Modell-/Task- Tabellen, Info-Bänder (stale/gate-blocked), 7d/30d-Presets + Custom-Range, Dark/Light. - **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 (`RefreshUsage` → `UsageMonitorService.RefreshNowAsync`, 10s-Cooldown). Unit-Tests grün, **offen**: - **Visueller Pass Refresh-Button** im Modal (Button + Spinner + Hinweiszeile, Dark/Light, en/de) — Teil des oben schon offenen Modal-Passes. - **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**: - [x] 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.