Ten of the twelve listed bugs/nits are fixed in the code (outcome JSON, subtask terminology, live child rows, AskUser in the detail island, Icon.Plus, gear glyph, rename display, TurnsText, conflict Continue gate, ConPTY resume) and the blocked-approve silent fail is handled by the WorkerHub throw. Adds the open verification block for the planning-resume fix.
194 lines
16 KiB
Markdown
194 lines
16 KiB
Markdown
# 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 <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.
|
||
- **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: <list>"), 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/<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.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.
|