Files
ClaudeDo/docs/open.md
T
Mika Kuns 24f999facd
Changelog / changelog (push) Successful in 2s
Release / release (push) Successful in 38s
docs: record the manual-task, effort-preset and chip/spinner changes
2026-07-27 15:02:51 +02:00

14 KiB
Raw Blame History

ClaudeDo — Offene Punkte

Stand: 2026-07-24. Diese Datei listet die aktiv verifizierten Findings aus der Verifikations-Session vom 2026-07-24. Die laufende Verifikations-Checkliste (Pass/Fail je Abschnitt, inkl. noch offener Abschnitte §7–§11 und Kanten) lebt in docs/verification-handoff.md. Erledigtes steht in den Commits/im Code, nicht hier.


Bugs (verifiziert 2026-07-24)

  • OUTCOME-Karte rendert rohes Structured-Output-JSON: TaskMonitorViewModel.ApplyOutcome (ClaudeDo.Ui) setzt bei Tasks ohne Roadblock-Marker SessionOutcome = result wörtlich (Zeile ~261). Der Worker legt in task.Result das rohe {"summary":…,"files_changed":[…]} ab (die lesbare Fassung steht in task_runs.resultMarkdown), also zeigt die Detail-Insel OUTCOME als JSON-Blob statt als Text. Fix: (a) UI parst ein JSON-Result und zeigt summary, oder (b) Worker schreibt summary/resultMarkdown statt des JSON in task.Result. Verifiziert am Task verif §1 diff matrix. Deckt sich mit Memory worker_testing_findings.
  • Approve & Merge schluckt einen „blocked"-Merge still: DetailsIslandViewModel.ApproveReviewAsync reagiert nur auf result.Status == "conflict" (öffnet den Resolver); bei "blocked" (z.B. Ziel-Working-Tree hat uncommittete getrackte Änderungen) und anderen Nicht-merged/Nicht-conflict-Status passiert nichts — kein Footer-Fehler, kein Dialog (der catch greift nur bei Exceptions, „blocked" ist aber ein normaler Rückgabewert mit ErrorMessage). User sieht „Klick tut nichts". Doppelt verifiziert (Konflikt-Approve UND sauberer additiver Approve verif §1b, beide bei dirty main-Checkout still). Fix: bei blocked/unerwartetem Status result.ErrorMessage via ShowErrorAsync/FlashFooterError surfacen. Verstößt gegen feedback_ui_error_surfacing. (Der Konflikt-Resolver + 3-Pane-Editor funktionieren, sobald der Ziel-Tree sauber ist.)
  • „Waiting for Improvements" für Planning-Parents (Terminologie): taskStatus.waitingForChildren = „Waiting for Improvements" (en.json:504), agentStatus.children dito (503), childOutcomesLabel = „IMPROVEMENTS" (191). Seit dem unified-parent-Modell gilt WaitingForChildren für Planning und Improvement-Parents — „Improvements" ist für einen Planning-Parent falsch. Auf neutrales „Waiting for Subtasks"/„Subtasks" umstellen (en und de — Localization.Tests-Parität). Verifiziert §3.
  • Kind-Rows aktualisieren nach Parent-Planning-Transitionen nicht live: Parent-getriebene Änderungen propagieren nicht auf die Kind-TaskRowViewModels ohne Listen-Reload. (a) Nach „Finalize planning" bleiben Kind-Rows auf „Draft" (IsDraft) statt „Planned" (IsPlanned) — der geänderte ParentFinalized kommt nicht über das Parent-TaskUpdated-Broadcast an. (b) Nach „Discard" bleiben die (in der DB gelöschten) Draft-Kind-Rows sichtbar, bis die Liste neu geladen wird. Gemeinsame Ursache: die Kinderliste/-zustände werden bei Parent-Transitionen nicht live neu aufgelöst. Doppelt verifiziert §3 (Finalize und Discard, 2026-07-24).
  • AskUser-Frage erscheint NUR in Mission Control, nicht in der Task-Detail-Insel: Der ask_user-Banner (Frage + Antwort-Eingabe) lebt ausschließlich in MonitorPaneView (Mission Control). Die Detail-Insel (DetailsIslandView) streamt zwar den Live-Log eines laufenden Tasks, zeigt aber kein Frage-Banner — ein Nutzer, der nur die Detailansicht offen hat, sieht nicht, dass der Run auf eine Antwort wartet, und läuft nach 3 min in den Timeout-Fallback. Verifiziert §7 (User schaute Detailansicht, Frage war unsichtbar; erst in Mission Control sichtbar). Fix: Frage-Banner + Inline-Antwort auch in der Detail-Insel für den gebundenen laufenden Task surfacen (VM-Zustand liegt bereits in TaskMonitorViewModel, müsste für die Detail-Insel repliziert/geteilt werden). Von Mika bei der §7-Verifikation ausdrücklich gewünscht („vermisse diese Interaktion in der Detail-Ansicht"). §7.
  • „New session"-Button (Mission Control) unsichtbar — Icon.Plus ist Strich-Only: Icon.Plus = M12 5v14M5 12h14 (IslandStyles.axaml:61) ist reine Linien-Geometrie ohne Fläche; im <PathIcon> (MissionControlView.axaml:38, füllt Geometrie) rendert sie unsichtbar → der Ad-hoc-„New session"-Button erscheint leer und ist nicht auffindbar (Feature + VM OpenAdHocConPtySessionAsync + Tests funktionieren, nur das Icon fehlt sichtbar). Fix: Icon.Plus als gefüllte Geometrie authoren ODER als gestricheltes Path rendern (Icon-Gotcha in CLAUDE.md). Andere Icon.Plus-Verwendungen mitprüfen. Verifiziert §5.

UX / Nits (verifiziert 2026-07-24)

  • „Resume planning session" ist grundsätzlich kaputt (Session-Id wird nie erfasst) + Fehler wird verschluckt: Im UnfinishedPlanning-Modal macht Resume nichts. Ursache: PlanningSessionManager.ResumeAsync (PlanningSessionManager.cs:238) bricht mit InvalidOperationException("No Claude session ID captured yet; cannot resume.") ab, wenn task.PlanningSessionId leer ist — und der Setter TaskRepository.UpdatePlanningSessionIdAsync (TaskRepository.cs:322) hat keinen einzigen Aufrufer im Worker, d.h. planning_session_id wird nie befüllt (verifiziert an verif §3 resume-discard: planning_session_id=NULL, Token gesetzt, Drafts angelegt). Resume kann also nie erfolgreich sein. Zusätzlich verschluckt TasksIslandViewModel.ResumePlanningSessionAsync den ganzen Block in einem leeren catch { } (~Zeile 870) → der Button ist ein stummer No-op, kein Footer-Fehler, kein Dialog (verstößt gegen feedback_ui_error_surfacing). Hintergrund: die wt-Planning-Session ist interaktiv; ClaudeDo erfasst die claude-Session-Id dort nicht (analog zur bewusst nicht persistierten ConPTY-Session-Id, §5). Fix-Optionen: (a) beim Planning-Start/-Lauf die claude-Session-Id erfassen und via UpdatePlanningSessionIdAsync persistieren, damit Resume echt resumen kann; ODER (b) Resume entfernen/deaktivieren, wenn keine Session-Id vorliegt; in JEDEM Fall den Fehler statt des leeren catch surfacen. Verifiziert §3. §3.

  • 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 (App-Neustart nötig, um die „erster-Drop"-Bedingung wiederherzustellen). 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 (die genaue Exception-Message fehlt, weil DropStatus nur {fileName}: {ex.Message} zeigt). Verifiziert §9 (einmalig beobachtet). §9.

  • Agent-Settings-Gear weicht vom übrigen Settings-Icon ab: Der Agent-Settings-Flyout-Button (TaskHeaderBar.axaml:68) rendert ein Unicode-Glyph (<TextBlock Text="⚙">), während die Listen-Nav (ListsIslandView.axaml:56) und die Listen-Settings (TasksIslandView.axaml:47) das gefüllte Icon.Settings-PathIcon (Gear-StreamGeometry, IslandStyles.axaml:110) nutzen → optisch ein anderes Zahnrad. Angleichen: den -TextBlock durch <PathIcon Data="{StaticResource Icon.Settings}" .../> ersetzen. Verifiziert §8 (User-Sichtprüfung). §8.

  • 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"). Verifiziert §8 (frischer Zustand vor ponytail-Install). Kleiner Empty-State-Text ergänzen.

  • Diff-Viewer: reiner Rename schwach dargestellt: Rename korrekt erkannt (UnifiedDiffParserDiffFileStatus.Renamed, Badge StatusCode="R"), aber der File-Tree zeigt nur den neuen Namen + „+0 0" ohne „alt → neu"-Pfad; liest sich wie „keine Änderung". Optional: alten Pfad + „renamed"-Label anzeigen. §1.

  • Header-TurnsText zeigt 0/max für abgeschlossene Runs: TurnsText => {Turns}/{EffectiveMaxTurns}Turns wird beim Laden eines terminalen Tasks nicht aus task_runs.turnCount restauriert (nur live gefüllt). Kosmetisch. §1.

  • Conflict-Resolver: Continue/Merge-Button klickbar trotz offener Konflikte: Gate greift funktional (merged erst wenn alle Konflikte in allen Dateien gelöst), aber der Button ist nicht disabled/gegraut → früher Klick ist ein stummer No-op. Besser: disabled bis AllResolved, oder Hinweis „N Konflikte in M Dateien offen". §4.

  • 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". §4.

  • Planning-aktiver Parent zeigt weiter „Idle": Parent in planning_phase=active hat Status=Idle (korrekt im Modell), aber der Row-Status-Chip zeigt „Idle"; der PlanningBadge ersetzt das nicht sichtbar → liest sich wie ein normaler Idle-Task. Wunsch: klarer „Planning/Draft aktiv"-Zustand, der Idle überschreibt. (Kinder zeigen korrekt „Draft".) §3.

  • Blocked-by-Kette nicht sichtbar: Nach Finalize ist die sequentielle Kette korrekt gesetzt (child[i] blocked-by child[i-1]), aber die UI stellt die Reihenfolge/Abhängigkeit nicht dar. Wunsch: Kette visualisieren (z.B. „wartet auf <Vorgänger>"), nicht nur der „waiting"-Chip nach dem Queueen. §3.

  • Dequeue-„X" fehlt auf wartenden (blockierten) Kettengliedern: CanRemoveFromQueue = IsQueued || HasQueuedSubtasks, IsQueued verlangt leeres blocked_by. Ein gequeuetes, aber blockiertes Kind (IsWaiting) bekommt daher kein Remove-from-queue-X — nur Parent + erstes (entsperrtes) Kind. §3.

  • „Open ConPTY session" erneut = Prompt wird neu gesendet, kein Resume: Da die ConPTY-Session-Id bewusst nicht persistiert wird, startet ein erneutes „Open ConPTY session" auf demselben Task eine frische Session und sendet den Task-Prompt erneut (re-runt die Arbeit im selben Worktree) statt zu resumen. So designt, aber UX-Falle — evtl. „Resume"-Affordance oder Re-Open-Warnung. §5.

Feature-Wünsche (aus der Session)

  • Conflict-Resolver: farbliches Hervorheben eingefügter Zeilen im Result-Pane (grüner „flow" der übernommenen Zeilen). §4.
  • Als ClaudeDo-Tasks in Liste „Claude do" erfasst: Approve erzwingt Diff/Review vor Merge (koppelt den blocked-Merge-Silent-Fail-Fix) und interaktive Planning-Session über embedded ConPTY statt externem wt-Fenster (koppelt den Planning-Permission-Prompt).

Sichtprüfung offen (2026-07-27, Batch „Claude do"-Liste)

Alles gebaut + unit-getestet, aber nicht visuell verifiziert — Mika prüft:

  • Ctrl+K fokussiert die Suche, # ist wieder tippbar (Binding war OemQuestion = # auf DE-Layout).
  • Titel-Edit in der Detail-Insel persistiert (400 ms debounced, wie die Beschreibung); Row-Titel + Merge-Kontext ziehen mit.
  • Spinner beim ConPTY-Start: Tile erscheint sofort mit „Sitzung wird gestartet…" und deckt Launch-Spec-Roundtrip + Spawn ab. Nicht abgedeckt: die Sekunden, die die claude-TUI danach zum ersten Frame braucht (dafür bräuchte es einen Hook auf TerminalControl.DataReceived). Bei Launch-Fehler bleibt das Tile jetzt mit Inline-Banner stehen statt zu verschwinden.
  • Spinner beim Refine ersetzt den Refine-Button in der Row, solange der Run läuft.
  • Interactive-Chip statt „Parked" auf Tasks mit offener ConPTY-Session; Klick öffnet Mission Control und fokussiert die Pane. Accent-Tint (bewusst dieselbe „live"-Familie wie Running, klar unterschieden vom slate-blauen Parked).
  • Diff-Viewer: rechter Abstand der +n n-Zahlen im File-Tree.
  • Manual-Tasks: MANUAL-Badge, Kontextmenü-Toggle, Listen-Checkbox „Manuelle Liste"; Queue/Refine/Planning ausgeblendet, ConPTY bleibt.
  • Settings → Allgemein: Tabelle „Vorgaben pro Modell" (Effort + Max. Durchläufe je haiku/sonnet/opus/fable). Ersetzt das einzelne globale „Max. Durchläufe"-Feld.

Offene Entscheidungen dazu:

  • 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 nur noch Fallback für ein Modell ohne Preset-Zeile und hat keinen Editor mehr. Spalte könnte später entfallen.

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.

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. Plus a real-Claude smoke run of the five phases (dedupe questions, enhancements landing in task descriptions, queued execution, merges).

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.