From bcf5e2f51f7fb83b27f66e37d52c3a89c3676ff3 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Thu, 4 Jun 2026 11:16:18 +0200 Subject: [PATCH] docs: regenerate open.md against verified current state Audit found the backlog stale: many open items shipped, several large features (localization, weekly report, daily notes, daily-prep) were missing, and the removed tag system was still treated as live. Co-Authored-By: Claude Opus 4.7 --- docs/open.md | 338 +++++++++++++++++++++------------------------------ 1 file changed, 140 insertions(+), 198 deletions(-) diff --git a/docs/open.md b/docs/open.md index bb9615d..6062d01 100644 --- a/docs/open.md +++ b/docs/open.md @@ -1,286 +1,228 @@ # ClaudeDo — Offene Punkte -Stand: 2026-04-30. Neu erstellt nach Code-Audit gegen `plan.md`, `improvement-plan.md` und `mailbox-proposal.md`. +Stand: 2026-06-04. Neu generiert nach Code-Audit gegen den tatsächlichen Stand auf `main`. -Die alte Version dieses Dokuments war auf 2026-04-13 ("nach Slice F") datiert und ignorierte die seither gelandeten Slices (Planning Sessions, Prime Claude, Self-Update, Externe MCP-Tools, editierbare Status/Tags, BlockedBy-Chains). Diese Version trennt sauber zwischen **erledigt**, **teilweise**, **offen** — und listet das, was inzwischen gebaut wurde, explizit als „shipped" auf, damit es nicht verloren geht. +Die vorherige Version war auf 2026-04-30 datiert und inzwischen deutlich veraltet: zahlreiche als „offen" geführte Punkte sind gebaut, mehrere große Features (Localization, Weekly-Report + Daily-Notes, Daily-Prep) fehlten komplett, und das inzwischen entfernte Tag-System wurde noch als lebendig behandelt. Diese Version trennt sauber: **was seit 2026-04-30 dazukam**, **was wirklich noch offen ist**, **was inzwischen erledigt wurde** und **was fallengelassen / obsolet ist**. -Legende: ✅ DONE — 🟡 PARTIAL — ⬜ OPEN — ⛔ DROPPED +Legende: ✅ DONE — 🟡 PARTIAL — ⬜ OPEN — ⛔ DROPPED/OBSOLET --- -## 0. Was seit dem 2026-04-13 dazugekommen ist +## 0. Was seit 2026-04-30 dazugekommen ist -Diese Slices gab es im alten Dokument noch nicht (oder nur als Platzhalter). Sie sind **fertig im Code**, brauchen aber jeweils noch ein paar Polish-Punkte (siehe Sektion 2/3). +Diese Features gab es im alten Dokument noch gar nicht. Sie sind **fertig im Code**, brauchen aber teils noch manuelle Verifikation (siehe §1). -| Slice | Worker-Anker | UI-Anker | Status | -|---|---|---|---| -| **Planning Sessions** (Plan B+C) | `Planning/PlanningSessionManager`, `PlanningChainCoordinator`, `PlanningMcpService` | `Views/Planning/PlanningDiffView`, `ConflictResolutionView`, `UnfinishedPlanningModalView` | ✅ Code, manuelle Verifikation siehe §1.1 | -| **Prime Claude** (geplante Recurrence) | `Prime/PrimeScheduler`, `NextDueCalculator`, `PrimeRunner` | `ViewModels/Modals/PrimeClaudeTabViewModel`, `Views/Controls/ThemedDatePicker` | ✅ Code, manuelle Verifikation siehe §1.2 | -| **Self-Update System** (Gitea Releases) | — | `ClaudeDo.Releases` (`ReleaseClient`, `SelfUpdater`, `ChecksumVerifier`, `VersionComparer`), `ClaudeDo.Installer` (Pages/Steps/Core) | ✅ Code, manuelle Verifikation siehe §1.3 | -| **Externes MCP-Endpoint** (11 Tools für Drittsessions) | `External/ExternalMcpService` (`ListTaskLists`, `ListTasks`, `GetTask`, `AddTask`, `UpdateTask`, `UpdateTaskStatus`, `SetTaskTags`, `ListTags`, `DeleteTask`, `RunTaskNow`, `CancelTask`), `ExternalMcpAuthMiddleware` (X-ClaudeDo-Key) | — | ✅ Code, ohne Tests am Endpoint selbst | -| **Editierbare Status & Tags** (entkoppelt vom `agent`-Tag) | `WorkerHub.SetTaskStatus`, `SetTaskTags`, `UpdateTaskAgentSettings`; Queue-Picker filtert nicht mehr nach `agent`-Tag | `DetailsIslandViewModel`, Status-/Tag-Kontextmenü in `TasksIslandView` | ✅ Code | -| **BlockedBy-Chains** (sequenzielle Subtask-Ausführung) | `TaskStateService.BlockOn`/`UnblockAsync`, `QueuePicker` filter `BlockedByTaskId IS NULL`, `PlanningChainCoordinator.OnChildFinishedAsync` | Drittes Feld neben `Status` und `PlanningPhase` | ✅ Code, Migration `20260423154708_AddPlanningSupport` | -| **Worker-State-Konsolidierung** | `TaskStateService` ist alleiniger Owner von `Status`/`PlanningPhase`/`BlockedByTaskId`-Writes; `OverrideSlotService` ausgelagert; `QueueWaker` + `QueuePicker` getrennt | — | ✅ Code | -| **MarkdownView / Tabbed Settings / About-Modal / Prime-Status-Footer / Doppelklick-Edit** | — | `Views/MarkdownView`, `SettingsModalView` als `TabControl`, `AboutModalView`, transient Prime-Status in Footer, `DoubleTapped` an List/Task-Rows | ✅ Code | +| Feature | Anker | Status | +|---|---|---| +| **Localization / i18n** | Eigenes Projekt `ClaudeDo.Localization` (`Localizer`, `CultureResolver`, `LocaleStore`, nested-JSON Parser); `loc:Tr` Markup-Extension; `locales/en.json` + `locales/de.json`; Settings-Sprachwahl; Installer-Sprachwahl | ✅ Code, Localization.Tests erzwingt Key-Parität | +| **Weekly Report** | `Worker/.../WeekReportService`, `ClaudeHistoryReader` (distilliert Session-Logs), Day-Major-Prompt-Builder; `WeekReportRepository`; `WeeklyReportModalView(Model)` | ✅ Code, manuelle Verifikation siehe §1.4 | +| **Daily Notes** | `DailyNoteRepository`, `INotesApi`, `NotesEditorView(Model)` mit Tagesnavigation + Bullet-CRUD; Notes-Mode in der Details-Island; gepinnte Notes-Row in MyDay | ✅ Code | +| **Daily-Prep („Plan My Day")** | `Prime/PrimeRunner` ruft Daily-Prep über erlaubte MCP-Tools; `get_daily_prep_candidates` + `set_my_day` MCP-Tools mit Cap-Guard; `DailyPrepMaxTasks`-Setting; Live-Prep-Output-Mode in der Details-Island (`PrepStarted/PrepLine/PrepFinished`); persistierter Prep-Log; MyDay-Header-Iconreihe (Prepare, Clear-day, Prep-log) | ✅ Code, manuelle Verifikation siehe §1.5 | +| **Waiting-for-Review-State** | Eigene Status-Stufe zwischen Run-Erfolg und Done; Approve/Reject-Rerun/Reject-Park/Cancel | ✅ Code | +| **Per-User Worker-Autostart** | Startup-Ordner-Verknüpfung statt Scheduled Task / Windows-Service (siehe §4.1) | ✅ Code | +| **Worktree-Overview-Modal** | `2026-05-19-worktree-overview-modal-design` | ✅ Code | +| **External-MCP UI-Parität** | ExternalMcpService von 11 → 18 Tools (siehe §5.4) | ✅ Code | + +Weitere Specs/Plans seit 2026-04-30 (für die Historie): `planning-draft-planned-gate`, `repo-import-list-helper`, `ui-normalization`, `worker-lifecycle`, `prime-recurring-weekdays`. --- ## 1. Verification (vor allem anderen) -Der Großteil der Verification-Steps aus `plan.md` ist im Code abgedeckt — was fehlt ist die **manuelle Bestätigung mit explizit notiertem Pass-Kriterium**. Ohne falsifizierbare Observable produziert ein Manual-Run nur "sah ok aus". +Der Code ist da; was fehlt, ist die **manuelle Bestätigung mit explizit notiertem Pass-Kriterium**. Ohne falsifizierbare Observable produziert ein Manual-Run nur „sah ok aus". -### 1.0 Plan-Verification 1–13 +### 1.0 Plan-Verification — Kernpipeline (unverändert dringend) -| # | Item | Status | Pass-Kriterium (was muss konkret zu sehen sein) | +Die End-to-End-Beweise für die eigentliche Ausführungspipeline wurden **nie durchgespielt**. Das ist das größte verbleibende Risiko: alle neuen Features sitzen auf einer Pipeline, deren Happy-Path nie unter echtem `claude` verifiziert wurde. + +| # | Item | Status | Pass-Kriterium | |---|------|---|---| -| 1 | Schema-Init | ✅ | `~/.todo-app/todo.db` + `*-wal` + `*-shm` existieren; EF-Migrationsverlauf in `__EFMigrationsHistory` enthält alle 8 Migrationen; Worker-Log: „listening on …" | -| 1a | SignalR-Endpoint | ✅ | `curl http://127.0.0.1:47821/hub` → HTTP 400 (kein Handshake) | -| 1b | Hub-Roundtrip `Ping` | 🟡 | UI-Statusbar zeigt „Connected"; `WorkerClient.PingAsync()` liefert `"pong"` (UI-Test fehlt) | -| 2 | `claude --version` Preflight | ✅ | `Worker/Lifecycle/ClaudeCliPreflight.cs` + Wiring in `Program.cs`. Kaputter `claude_bin` → `LogCritical(...) + Environment.Exit(1)`. Skip via `CLAUDEDO_SKIP_CLI_PREFLIGHT=1`. Tests: `tests/.../Lifecycle/ClaudeCliPreflightTests.cs` | -| 3 | Smoke-Spawn (`claude -p` Prompt „ping") | ⬜ | `task_runs`-Row mit `session_id NOT NULL`, `result` non-empty, `output_tokens > 0` | -| 4 | E2E Happy Path (Non-Worktree) | ⬜ | Liste „Test" anlegen → Task „Schreibe ein Haiku über Intralogistik" → `tasks.status='Done'`, `tasks.result IS NOT NULL`, Logfile unter `~/.todo-app/logs/.ndjson`, UI-Row mit Done-Badge | +| 3 | Smoke-Spawn (`claude -p` „ping") | ⬜ | `task_runs`-Row mit `session_id NOT NULL`, `result` non-empty, `output_tokens > 0` | +| 4 | E2E Happy Path (Non-Worktree) | ⬜ | Liste anlegen → Task → `tasks.status='Done'`, `result IS NOT NULL`, Logfile unter `~/.todo-app/logs/.ndjson`, UI-Row mit Done-Badge | | 5 | Worktree Happy Path | ⬜ | Liste mit `working_dir` auf temp-Repo, Task mit Codeänderung → `worktrees.state='active'`, `head_commit IS NOT NULL`, `diff_stat` non-empty, Branch `claudedo/` auf Disk | -| 6 | No-Changes-Run | ⬜ | Prompt der nichts ändert → `tasks.status='Done'` aber `worktrees.head_commit IS NULL`, `diff_stat IS NULL` | -| 7 | Kein Git-Repo | ⬜ | `working_dir=C:\Temp` (kein Repo) → `tasks.status='Failed'`, **keine** `worktrees`-Row, Worker-Log enthält Git-Fehler | -| 8 | Merge-UI | 🟡 | `MergeTask`-Hub-Methode + `MergeModalView` vorhanden, manueller Run nicht durchgespielt → `worktrees.state='merged'`, im Ziel-Repo `git log` zeigt Commit, `git worktree list` ohne Branch | -| 9 | Override-Parallelität | 🟡 | `OverrideSlotService`-Tests grün; UI-E2E nicht durchgespielt → `WorkerHub.GetActive` ≥ 2 Einträge bei Run+RunNow | -| 10 | Schedule | 🟡 | `QueuePicker`-Tests grün; UI-E2E nicht → `scheduled_for=now+2min` bleibt Queued, dann automatisch Running, `started_at >= scheduled_for` | -| 11 | Worker-Offline-Erkennung | 🟡 | `WorkerClient.OnServerConnectionClosed` + Auto-Reconnect implementiert (`WithAutomaticReconnect`); visuell prüfen: nach `taskkill` der Worker-Exe wechselt Statusbar in ≤ 5s auf „Offline", `RunNow`-Buttons disabled | -| 12 | Live-Stream | 🟡 | `ClaudeProcess` streamt NDJSON via `TaskMessage`-Event, UI hat `LiveTail`; visuell prüfen: während Run laufen ndjson-Zeilen ein | -| 13 | Wake-up (`WakeQueue` nach Anlage) | 🟡 | `QueueWaker.Wake()` wird bei Enqueue aufgerufen; visuell prüfen: Task wechselt in ≤ 1s auf Running (statt nach `queue_backstop_interval_ms`=30s) | +| 6 | No-Changes-Run | ⬜ | Prompt der nichts ändert → `status='Done'`, `worktrees.head_commit IS NULL`, `diff_stat IS NULL` | +| 7 | Kein Git-Repo | ⬜ | `working_dir=C:\Temp` → `status='Failed'`, **keine** `worktrees`-Row, Git-Fehler im Log | +| 8 | Merge-UI | 🟡 | `MergeTask` + `MergeModalView` da; manueller Run offen → `worktrees.state='merged'`, Commit im Ziel-Repo, kein Branch in `git worktree list` | +| 9 | Override-Parallelität | 🟡 | `OverrideSlotService`-Tests grün; UI-E2E offen → `GetActive` ≥ 2 Einträge bei Run+RunNow | +| 10 | Schedule | 🟡 | `QueuePicker`-Tests grün; UI-E2E offen → `scheduled_for=now+2min` bleibt Queued, dann automatisch Running | +| 11 | Worker-Offline-Erkennung | 🟡 | Auto-Reconnect implementiert; visuell prüfen: nach `taskkill` Statusbar in ≤ 5s „Offline", RunNow disabled | +| 12 | Live-Stream | 🟡 | `ClaudeProcess` streamt NDJSON via `TaskMessage`; visuell: ndjson-Zeilen laufen während Run ein | +| 13 | Wake-up (`WakeQueue`) | 🟡 | `QueueWaker.Wake()` bei Enqueue; visuell: Task in ≤ 1s auf Running statt nach Backstop-Intervall | -**Empfohlener Sprint:** Steps 3–7 in einem Rutsch durchspielen (alles non-UI), parallel daneben 8–13 visuell beim normalen App-Lauf abhaken. +**Empfohlener Sprint:** Steps 3–7 in einem Rutsch (alles non-UI), 8–13 parallel beim normalen App-Lauf visuell abhaken. -### 1.1 Planning Sessions — Manual Verification (unverändert relevant) - -Bedingt durch Slice "Planning B/C". Ablauf identisch zur alten open.md: +### 1.1 Planning Sessions — Manual Verification 1. Manual-Task mit Title + TODO-Description anlegen. -2. Rechtsklick → **Open planning Session** → Windows Terminal mit Claude CLI öffnet. -3. In CLI: zwei Children via `mcp__claudedo__create_child_task` anlegen. -4. UI: Drafts erscheinen eingerückt, italic, mit `DRAFT`-Badge; Parent zeigt `PLANNING`-Badge. -5. Chevron klappt ein/aus. -6. CLI `finalize` → Children werden Queued (erste) bzw. Queued+BlockedBy (Rest); Parent flippt von `Active` auf `Finalized` (`PLANNED`-Badge); erste Child startet automatisch. -7. Neuer Planning-Task, Terminal ohne Finalize schließen → Rechtsklick öffnet Resume/Finalize-now/Discard-Modal. -8. Delete-Versuch auf Parent mit Children → freundlicher Fehlerdialog, kein Delete. - -**Bekannte Follow-ups (non-blocking):** -- ✅ `Border.badge.planned` (blau) wird jetzt bei `Finalized` angewendet — `TaskRowView` nutzt `Classes.planning`/`Classes.planned` gebunden an `IsPlanActive`/`IsPlanFinalized`; der Child-„PLANNED"-Badge nutzt direkt `planned`. -- ✅ Tote `Instance`-Statics auf `BoolToItalicConverter` und `BoolToDraftOpacityConverter` entfernt (Registrierung läuft über das Resource-Dictionary in `App.axaml`). -- ✅ `Ui.Tests` IWorkerClient-Fakes auf gemeinsame Basis `StubWorkerClient` rebased — kein Constructor-Drift mehr; die drei Fakes überschreiben nur ihre relevanten Member. +2. Rechtsklick → **Open planning Session** → Terminal mit Claude CLI öffnet. +3. In CLI zwei Children via `mcp__claudedo__create_child_task` anlegen. +4. UI: Drafts eingerückt, italic, `DRAFT`-Badge; Parent `PLANNING`-Badge; Chevron klappt. +5. CLI `finalize` → Children Queued bzw. Queued+BlockedBy; Parent `Finalized` (`PLANNED`-Badge, blau); erste Child startet automatisch. +6. Terminal ohne Finalize schließen → Rechtsklick öffnet Resume/Finalize-now/Discard-Modal. +7. Delete auf Parent mit Children → freundlicher Fehlerdialog, kein Delete. ### 1.2 Prime Claude — Manual Verification -Slice "Prime" (Recurrence-Scheduler). - -1. Settings → Prime-Claude-Tab → Schedule mit `at: 09:00`, `every: workday`, `task_template: "Daily Standup"` anlegen. -2. Test mit verschobenem `IPrimeClock` (oder Schedule mit `at: now+1min`) → bei Trigger erscheint Toast/Footer-Notification „Prime fired", neuer Task entsteht in der Ziel-Liste. -3. Worker-Restart innerhalb des Schedule-Fensters → Catch-up läuft genau einmal (kein Doppelfeuer). -4. Schedule editieren → `next_due_at` wird neu berechnet; UI-Anzeige aktualisiert. +1. Settings → Prime-Claude-Tab → Schedule mit Uhrzeit + Wochentag-Toggles anlegen. +2. Trigger (ggf. verschobener `IPrimeClock`) → Footer-Notification, neuer Task in Ziel-Liste. +3. Worker-Restart im Schedule-Fenster → Catch-up genau einmal (kein Doppelfeuer). +4. Schedule editieren → `next_due_at` neu berechnet, UI aktualisiert. 5. Schedule löschen → keine weiteren Trigger, keine ghost-Tasks. -### 1.3 Self-Update — Manual Verification (aus alter open.md, weiterhin gültig) +### 1.3 Self-Update — Manual Verification -Voraussetzung: funktionierendes Gitea-Release unter `git.kuns.dev/releases/ClaudeDo` mit drei Assets — `ClaudeDo--win-x64.zip`, `ClaudeDo.Installer-.exe`, `checksums.txt`. +Voraussetzung: Gitea-Release unter `git.kuns.dev/releases/ClaudeDo` mit `ClaudeDo--win-x64.zip`, `ClaudeDo.Installer-.exe`, `checksums.txt`. -1. Baseline-Version (z.B. `0.2.x`) normal installieren. -2. Neues Release `v0.3.0` mit frischem Installer + App-Zip + Checksums veröffentlichen. -3. App starten → Banner erscheint: `Update available: v0.2.x → v0.3.0`. -4. **Update now** klicken → App schließt, Installer öffnet im Update-Mode, läuft, restartet Worker. -5. App neu starten → Banner weg; `Help → Check for updates` zeigt kurz „You're up to date (v0.3.0)". -6. `v0.2.x`-Installer manuell starten → bietet Self-Update auf v0.3.0 an. **Update** → laufende Exe wird ersetzt, Wizard öffnet auf neuer Version. -7. Schritt 6 mit **Continue anyway** → Wizard öffnet ohne Self-Update. -8. Schritt 6 mit **Cancel** → Installer beendet ohne Aktion. -9. Network-Kill in App und Installer beim Start → silent fallback (kein Error, kein Banner). +1. Baseline (z.B. `0.2.x`) installieren. +2. Neues Release `v0.3.0` veröffentlichen. +3. App starten → Banner `Update available: v0.2.x → v0.3.0`. +4. **Update now** → App schließt, Installer im Update-Mode, restartet Worker. +5. App neu starten → Banner weg; `Help → Check for updates` → „You're up to date". +6. Alten Installer manuell starten → bietet Self-Update an. **Update** / **Continue anyway** / **Cancel** je einmal durchspielen. +7. Network-Kill beim Start in App und Installer → silent fallback (kein Error, kein Banner). + +### 1.4 Weekly Report — Manual Verification (NEU) + +1. Menü → Weekly Report öffnen → Default-Range stimmt (Standup-Wochentag berücksichtigt). +2. Generate → Report-Body entsteht aus Session-History; Multi-Repo-Zuordnung korrekt; Standup-Wochentag-Sentinel greift. +3. Excluded-Paths in Settings → entsprechende Repos fehlen im Report. +4. Report wird persistiert (`WeekReportRepository`) und beim erneuten Öffnen geladen. + +### 1.5 Daily-Prep — Manual Verification (NEU) + +1. `DailyPrepMaxTasks` in Prime-Settings setzen. +2. MyDay-Header → **Prepare day** (oder geplanter Prime-Trigger) → Live-Prep-Output läuft in der Details-Island. +3. Claude wählt ≤ Cap Tasks aus, `set_my_day` schreibt sie in MyDay; Cap-Guard verhindert Überschreitung. +4. **Prep-log** öffnet den persistierten letzten Lauf im Terminal-View; **Clear-day** leert MyDay. +5. Re-Open des Prep-Windows lädt den persistierten Log; Empty-State-Hinweis startet Planung aus dem Fenster. --- -## 2. UI-Polish +## 2. UI — Offene Punkte -### 2.1 Folder-Picker für `Working Directory` ⬜ -- **Datei:** `Views/ListSettingsModalView.axaml` + zugehöriges VM -- **Aktuell:** plain `TextBox` — Pfad muss getippt werden. -- **Soll:** Button „…" daneben → öffnet `IStorageProvider.OpenFolderPickerAsync`, schreibt Pfad ins Feld. -- **Aufwand:** klein. +### 2.1 Status-Bar Live-Update 🟡 (durch Refactor verschoben) +- `StatusBarViewModel` existiert **nicht mehr** als Datei — Connection-Status lebt jetzt in `IslandsShellViewModel` + `WorkerConnectionModalViewModel` (Islands-Architektur). Die Footer-Connection-Pill ist gebaut und farbcodiert. +- **Verbleibendes Risiko:** Ob `RunNow`-Enable/Disable pro Task-Row bei Connection-Change sauber re-evaluiert wird, ist nicht verifiziert. Gegen die aktuelle Architektur neu bewerten statt das alte `WeakReferenceMessenger`-Rezept blind umzusetzen. +- **Aufwand:** klein (erst messen, dann ggf. fixen). -### 2.2 Delete-Confirmation ⬜ -- **Aktuell:** Listen/Tasks-Delete läuft direkt ohne Rückfrage. Datenverlust-Risiko. -- **Soll:** generischer `ConfirmDialog` (1× bauen, mehrfach nutzen), Mini-Dialog „Wirklich löschen?". -- **Aufwand:** klein. - -### 2.3 Markdown-Rendering Result + Description ✅ -- `Views/MarkdownView.axaml` + Detail-Pane verwenden Markdown.Avalonia. - -### 2.4 Live-Log Auto-Scroll ⬜ -- **Datei:** `Views/DetailsIslandView.axaml(.cs)` (Live-Tail-Section) -- **Aktuell:** ndjson-Zeilen werden angehängt, Scrollposition bleibt stehen. -- **Soll:** Sticky-Bottom-Pattern — bei jeder neuen Zeile `ScrollToEnd()`, solange User nicht manuell hochgescrollt hat. Attached-Behavior reicht. - -### 2.5 Diff-Viewer 🟡 -- `DiffModalView.axaml` + `PlanningDiffView` existieren; integriert für Planning-Merges. -- **Offen:** Task-Level-Diff (Worktree vs. main) noch nicht im Modal-Flow geprüft. Verwenden statt `Process.Start("cmd /k git diff …")`. - -### 2.6 Status-Bar Active-Tasks Live-Update ⬜ -- **Datei:** `ViewModels/StatusBarViewModel` -- **Risiko:** `RunNowCommand.NotifyCanExecuteChanged` triggert nicht pro Item bei Connection-Change. -- **Soll:** `WeakReferenceMessenger`-Connection-Change-Message; alle `TaskRowViewModel` lauschen. -- **Aufwand:** klein, muss sauber gemacht werden. - -### 2.7 Settings-Dialog ✅ -- `SettingsModalView` als `TabControl`, Tabs: General, Prime Claude, etc. Persistiert in `~/.todo-app/ui.config.json` und `worker.config.json`. - -### 2.8 (NEU) Planning-Phase Badge-Farbe für `Finalized` ✅ -`Finalized` zeigt jetzt den blauen `planned`-Badge (Class-Binding in `TaskRowView`). - -### 2.9 (NEU) Tote Converter-Statics entfernen ✅ -`BoolToItalicConverter.Instance`, `BoolToDraftOpacityConverter.Instance` entfernt. +> Erledigt seit letztem Backlog: Folder-Picker (§alt 2.1), Delete-Confirmation (§alt 2.2), Markdown-Rendering, Live-Log Auto-Scroll (§alt 2.4), Task-Level-Diff-Viewer (§alt 2.5, kein `cmd /k git diff` mehr), Settings-Dialog, Planning-Badge-Farben, tote Converter-Statics — siehe §6. --- ## 3. Worker-Robustheit -### 3.1 CLI-Preflight beim Worker-Start ✅ -- `src/ClaudeDo.Worker/Lifecycle/ClaudeCliPreflight.cs` + Wiring in `Program.cs`. Tests: `tests/.../Lifecycle/ClaudeCliPreflightTests.cs`. Skippable via `CLAUDEDO_SKIP_CLI_PREFLIGHT=1`. - -### 3.2 Worktree-Cleanup beim Anlege-Failed ⬜ -- **Datei:** `src/ClaudeDo.Worker/Runner/WorktreeManager.cs` -- **Soll:** try/finally — bei Fehler zwischen `git worktree add` und DB-Insert `git worktree remove --force` als Best-Effort-Cleanup. +### 3.1 Worktree-Cleanup bei Anlage-Failed 🟡 +- `WorktreeManager.cs:64-92` heilt eine „branch already exists"-Kollision (remove + prune + delete + retry). +- **Offen:** Es gibt **kein** `try/finally`, das `git worktree remove --force` ausführt, wenn `WorktreeAddAsync` erfolgreich war, aber der anschließende DB-Insert (`:95-109`) wirft. Genau dieser Crash-Pfad ist weiterhin ungeschützt. - **Aufwand:** klein. -### 3.3 Logging über file-Sink ⬜ -- ILogger ist überall verdrahtet, aber kein File-Sink konfiguriert. -- **Soll:** Serilog oder `Karambolage.Extensions.Logging.File` — für Service-Modus zwingend, console-only ist im SCM-Fenster verloren. -- **Aufwand:** klein. +### 3.2 CLI-Preflight beim Worker-Start ✅ +- `Worker/Lifecycle/ClaudeCliPreflight.cs` + Wiring in `Program.cs`; skippable via `CLAUDEDO_SKIP_CLI_PREFLIGHT=1`; Tests vorhanden. -### 3.4 Tag-Negation / Exclusion ⬜ -- Tags sind weiterhin rein additiv (`list_tags ∪ task_tags`). Nach Slice „Editierbare Tags" weniger dringend, aber nicht gelöst. -- **Soll:** entweder neue Tabelle `task_tag_exclusions` oder Prefix `!tag` im task_tags-Eintrag. -- **Aufwand:** mittel — Schema + Repo + Tests + UI. +### 3.3 File-Sink-Logging ✅ +- `Program.cs:34-40`: `UseSerilog` + `WriteTo.File("~/.todo-app/logs/worker-.log", rollingInterval: Day, retainedFileCountLimit: 7)`. --- ## 4. Service-Deployment ### 4.1 Worker-Autostart via Startup-Shortcut ✅ (ersetzt Scheduled Task + Windows-Service) -- Der Worker läuft als `WinExe` (kein Konsolenfenster) + Serilog-File-Sink (`~/.todo-app/logs/worker-*.log`) + Single-Instance-Mutex. -- Autostart über eine **Startup-Ordner-Verknüpfung** `ClaudeDo Worker.lnk` (`%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\`), die der Installer via `AutostartShortcut`/`ShortcutFactory` COM-Helper anlegt. Kein Scheduled Task, kein Windows-Service. -- `StartWorkerStep` startet den Worker per `Process.Start`; `StopWorkerStep` beendet ihn per prozessbasiertem Kill. -- Die App (`IslandsShellViewModel`) startet den Worker nicht selbst. Bei offline-Worker ~12s nach App-Start: einmaliges `WorkerConnectionModal` (Start Worker / Rerun Installer / Dismiss); Connection-Status-Pill in der Fußzeile ist ein Button zum erneuten Öffnen des Modals. -- `UninstallRunner` löscht die Startup-`.lnk`; migriert ältere Installs durch best-effort-Löschen des Legacy-Scheduled-Tasks „ClaudeDoWorker" und des Legacy-Windows-Service. +- Worker als `WinExe` + Serilog-File-Sink + Single-Instance-Mutex. +- Autostart über Startup-Ordner-Verknüpfung `ClaudeDo Worker.lnk`, vom Installer via `AutostartShortcut`/`ShortcutFactory` angelegt. Kein Scheduled Task, kein Windows-Service. +- `UninstallRunner` löscht die `.lnk` und migriert Legacy-Installs (best-effort Löschen des alten Scheduled-Tasks + Windows-Service). - **Manuelle E2E-Verifikation am Gerät ausstehend** (Logoff/Logon-Autostart, Update-Pfad, Uninstall). ### 4.2 Pfad-Auflösung absolut ✅ -- `WorkerConfig.Load` expandiert `~`/`%USERPROFILE%` für alle Pfad-Felder. +- `WorkerConfig.Load` expandiert `~`/`%USERPROFILE%`. -### 4.3 Install-Skripte / Doku ⬜ -- **Datei (neu):** `docs/install-service.md` ODER `scripts/install-service.cmd` -- **Inhalt:** `dotnet publish` + `sc.exe create` + `sc.exe failure` + Hinweis auf `obj=` (User-Account) wegen Claude-CLI-Session. -- **Aufwand:** klein. - -### 4.4 Installer-Projekt ✅ -- `ClaudeDo.Installer` (WPF) + `ClaudeDo.Releases` mit Pages/Steps/Core/Theme — Self-Update funktioniert (siehe §1.3). +### 4.3 Installer-Projekt ✅ +- `ClaudeDo.Installer` (WPF) + `ClaudeDo.Releases` — Self-Update funktioniert (siehe §1.3). --- ## 5. Tests / CI ### 5.1 CI-Pipeline (Gitea Actions) ⬜ -- **Datei (neu):** `.gitea/workflows/ci.yml` -- **Inhalt:** `dotnet restore` → `dotnet build` (csproj-weise wegen `.slnx`-Bug auf .NET 8) → `dotnet test`. Auf Push + PR. -- **Achtung:** Pipeline darf NICHT die `.slnx` als Build-Target nehmen — explizite csproj-Liste in einem checked-in Build-Skript. +- Vorhanden: `.gitea/workflows/release.yml` (nur Release). +- **Fehlt:** Build/Test-Pipeline (`ci.yml`) auf Push + PR. Muss csproj-weise bauen (`.slnx`-Bug auf .NET 8) — explizite csproj-Liste in checked-in Build-Skript. - **Aufwand:** klein. ### 5.2 SignalR-Hub-Tests ✅ -- `tests/ClaudeDo.Worker.Tests/Hub/PlanningHubTests.cs`, `AgentSettingsHubTests.cs` testen Hub-Methoden via Fakes (kein realer SignalR-Roundtrip, aber alle Code-Pfade abgedeckt). -- **Optional verbleibt:** echter Roundtrip-Test mit `WebApplicationFactory` + `HubConnectionBuilder` für End-to-End-Validierung der SignalR-Pipeline. Niedriger Mehrwert solange Fakes alle Methoden treffen. +- `Hub/PlanningHubTests.cs`, `AgentSettingsHubTests.cs` decken Hub-Methoden via Fakes ab. +- **Optional:** echter Roundtrip mit `WebApplicationFactory` + `HubConnectionBuilder` — niedriger Mehrwert. ### 5.3 Smoke-Test gegen echten `claude` ⬜ -- **Datei (neu):** `tests/ClaudeDo.Worker.Tests/Runner/ClaudeProcessSmokeTest.cs` -- **Soll:** Real-CLI-Test mit `[Fact(Skip="...")]` ausgegraut, nur lokal aktiviert wenn `CLAUDE_AUTHENTICATED=1` Env-Var gesetzt ist. +- `tests/.../Runner/ClaudeProcessSmokeTest.cs` existiert nicht. Real-CLI-Test als `[Fact(Skip=...)]`, nur lokal bei `CLAUDE_AUTHENTICATED=1`. - **Aufwand:** klein. -### 5.4 (NEU) ExternalMcpService-Tests ⬜ -- `External/ExternalMcpService` hat 11 Tools, aber nur partielle Coverage in `tests/.../External/ExternalMcpServiceTests.cs`. Für jedes Tool mindestens einen Happy-Path + einen Error-Pfad ergänzen. +### 5.4 ExternalMcpService-Tests 🟡 +- Service exponiert jetzt **18 Tools** (war 11): `ListTaskLists`, `ListTasks`, `GetTask`, `AddTask`, `UpdateTask`, `UpdateTaskStatus`, `ReviewTask`, `RunTaskNow`, `CancelTask`, `DeleteTask`, `GetTaskStatusValues`, `GetTaskWorktree`, `GetTaskDiff`, `MergeTask`, `ListWorktrees`, `CleanupTaskWorktree`, `GetDailyPrepCandidates`, `SetMyDay`. +- `ExternalMcpServiceTests.cs` hat 14 Tests, plus 4 Sibling-Dateien (`ConfigMcpToolsTests`, `LifecycleMcpToolsTests`, `ListMcpToolsTests`, `RunHistoryMcpToolsTests`). +- **Ungetestet im External-Ordner:** `GetTaskWorktree`, `GetTaskDiff`, `MergeTask`, `ListWorktrees`, `CleanupTaskWorktree` — je Happy-Path + Error-Pfad ergänzen. --- ## 6. Dokumentation -### 6.1 README.md ⬜ -- Komplett fehlt. Mind. 1× kurz: was ist es, wie starten (Worker + UI), wo Config, wie Self-Update. +### 6.1 README.md ✅ +- Existiert mit Inhalt (Projektbeschreibung, Architektur, Zwei-Prozess-SignalR-Modell). -### 6.2 docs/architecture.md 🟡 -- In `plan.md` enthalten — entweder konsolidieren oder explizit ausgliedern. CLAUDE.md-Dateien pro Projekt sind aktuell de-facto-Architecture-Doc. +### 6.2 docs/architecture.md ⬜ +- Existiert nicht. Architektur lebt verstreut in `plan.md`, README und den Projekt-CLAUDE.md-Dateien. Entweder konsolidieren oder bewusst nicht ausgliedern. ### 6.3 ADRs ⬜ -- Vorschläge: „SignalR vs. SQLite-Polling für IPC", „Worktree pro Task", „TaskStateService als alleiniger State-Owner", „BlockedByTaskId statt Status='Waiting'", „External MCP als zweite WebApplication". +- Kein `docs/adr/` o.ä. Vorschläge: „SignalR vs. SQLite-Polling für IPC", „Worktree pro Task", „TaskStateService als alleiniger State-Owner", „BlockedByTaskId statt Status='Waiting'", „External MCP als zweite WebApplication". - **Aufwand:** klein, hilfreich für später. -### 6.4 (NEU) Mailbox-Proposal ⬜ -- `docs/mailbox-proposal.md` ist als Vorschlag vorhanden, nicht implementiert. Entscheidung: bauen, droppen oder parken? Wenn droppen → Datei entfernen, sonst klare Roadmap. +### 6.4 Mailbox-Proposal ⬜ (Entscheidung offen) +- `docs/mailbox-proposal.md` existiert weiter; **keine** Implementierung in `src/` (Grep nach „mailbox" → 0 Treffer). Entscheiden: bauen, droppen oder parken. Wenn droppen → Datei entfernen. --- -## 7. Bekannte Code-Schulden / Smells +## 7. Erledigt seit dem letzten Backlog (Beweis-geführt) + +Diese Punkte standen 2026-04-30 noch als offen/partial und sind verifiziert fertig: + +| Item | Beleg | +|---|---| +| Folder-Picker (Working Directory) | `ListSettingsModalView.axaml.cs:73` `OpenFolderPickerAsync` | +| Delete-Confirmation (Listen + Tasks) | `ConfirmAsync(...)` in `ListSettingsModalViewModel.cs:98`, `DetailsIslandViewModel.cs:939`, `TasksIslandViewModel.cs:785` | +| Live-Log Auto-Scroll | `SessionTerminalView.axaml.cs:45` `ScrollToEnd()` | +| Task-Level Diff-Viewer | `DiffModalView` via `DetailsIslandViewModel.cs:845`; kein `cmd /k git diff` mehr | +| File-Sink-Logging | `Program.cs:34` Serilog | +| README.md | vorhanden | +| `.gitattributes` | vorhanden, `* text=auto eol=lf` | +| `WorkerHub.GetActive` → `ActiveTaskDto` | `WorkerHub.cs:21` Record statt anonymem Typ | +| TODO in `DetailsIslandViewModel` (SendPromptAsync) | entfernt — kein TODO mehr in der Datei | + +--- + +## 8. Fallengelassen / Obsolet + +| Item | Begründung | +|---|---| +| ⛔ Tag-Negation / Exclusion (alt §3.4) | Tag-System wurde entfernt — `TaskEntity` hat keine `Tags`-Property mehr, Queue-Picker filtert nicht mehr nach Tags. | +| ⛔ Tag Multi-Select Control (alt IP-4) | Dito — kein Tag-Control existiert, kein Bedarf mehr. | +| ⛔ Install-Service-Skript (alt §4.3) | App nutzt Startup-Ordner-Shortcut statt Windows-Service → ein Service-Install-Skript ist architektonisch obsolet. | +| ⛔ Notes-Mode `lists.kind`-Switch (alt IP-2) | Ursprüngliche Rahmung überholt: Daily-Notes + Notes-Mode in der Details-Island sind separat gebaut; ein List-Kind-Feld auf der Entity ist nicht nötig. | + +--- + +## 9. Bekannte Code-Schulden / Smells | Stelle | Issue | Status | |---|---|---| -| `WorkerHub.GetActive` returnt `IReadOnlyList` mit anonymen Typen | Sollte expliziter `ActiveTaskDto` sein, den Worker UND UI teilen | ✅ (gibt bereits `IReadOnlyList` zurück) | -| `TaskRunner` führt eine `if (list.WorkingDir != null)`-Verzweigung mitten in der Methode | Strategy-Pattern wenn die Methode wächst, aktuell noch klein genug | ⬜ | -| `App.Services` als public static `ServiceProvider` | Service-Locator-Antipattern, toleriert weil nur in `App.OnFrameworkInitializationCompleted` | ⬜ | -| Embedded `schema.sql` ohne Versionierung | Durch EF-Core-Migrationen ersetzt | ✅ | -| CRLF-Warnings beim Commit | `.gitattributes` mit `* text=auto eol=lf` (oder explizit pro Sprache) wäre sauberer | ✅ (`.gitattributes` angelegt) | -| Tote Converter-Instances (`BoolToItalicConverter.Instance`, `BoolToDraftOpacityConverter.Instance`) | Per Resource-Dictionary registriert, Statics ungenutzt | ✅ (entfernt) | -| 1 unausgeführter `// TODO` in `DetailsIslandViewModel` (`SendPromptAsync` ohne Hub-Methode) | Entweder Hub-Methode bauen oder TODO entfernen | ✅ (im Main-Code nicht mehr vorhanden) | +| `TaskRunner.cs:70` `if (list.WorkingDir is not null)` | Inline-Verzweigung Worktree vs. Non-Worktree; Strategy-Pattern erst wenn die Methode wächst | ⬜ | +| `App.axaml.cs:13` `public static ServiceProvider Services` | Service-Locator-Antipattern, toleriert weil nur in `OnFrameworkInitializationCompleted` genutzt | ⬜ | --- -## 8. Improvement Plan (improvement-plan.md, Stand 2026-04-13) +## 10. Empfohlene Reihenfolge -| ID | Item | Status | Bemerkung | -|---|---|---|---| -| IP-1 | UI ↔ Worker Auto-Reconnect | ✅ | `WorkerClient` mit `WithAutomaticReconnect()` + Reconnect-Handler | -| IP-2 | Listen-Modus „Notes" (non-autonomous) | ⬜ | Nach Slice „editierbare Status/Tags" weniger dringend (man kann jetzt einen Task ohne `agent`-Tag idle lassen), aber `lists.kind` als sauberer Mode-Switch fehlt. | -| IP-3 | Doppelklick öffnet Edit-Dialog | ✅ | `DoubleTapped`-Handler in `ListsIslandView`, `TasksIslandView` | -| IP-4 | Tag Multi-Select Control | ⬜ | Tags sind via Picker im Detail-Pane editierbar, aber kein dediziertes Multi-Select-Control mit Auto-Vervollständigung in Editor-Dialogen. | -| IP-5 | Rechtsklick-Kontextmenü | ✅ | Listen + Tasks haben Context-Menüs (Edit, Delete, Run Now, Show Diff, Merge, Cancel, Status, Tags) | -| IP-6 | Schema-Migration-Mechanismus | ✅ | EF-Core-Migrations + `__EFMigrationsHistory` | -| IP-7 | Status-Bar Reconnect-States | ✅ | `connected`/`connecting`/`reconnecting`/`offline` farbcodiert | -| IP-8 | Tag-Repository `GetAllKnownTagsAsync` | ✅ | `TagRepository.GetAllAsync` + `WorkerClient.GetAllTagsAsync` | +**Block 1 — Kernpipeline beweisen** (kein neuer Code, nur Beweis): §1.0 Steps 3–7 manuell durchspielen. Das ist das größte ungedeckte Risiko. ---- +**Block 2 — Neue Features verifizieren:** §1.4 Weekly-Report, §1.5 Daily-Prep, dazu §1.1/§1.2 Walkthroughs. -## 9. Empfohlene Reihenfolge für die nächsten Sessions +**Block 3 — Robustheit & Sicherheitsnetz:** §3.1 Worktree-Cleanup-`finally`, §5.1 CI-Pipeline (csproj-weise), §5.3 Real-`claude`-Smoke-Test, §5.4 fehlende ExternalMcp-Tools testen. -**Block 1 — Verification durchspielen** (kein neuer Code, nur Beweis): -1. §1.0 Steps 3–7 manuell (Smoke + E2E + Worktree + No-Changes + Kein-Repo) — ist die Pipeline wirklich lebendig? -2. §1.1 Planning-Walkthrough — nach den uncommitted Coordinator-Änderungen einmal durchspielen. -3. §1.2 Prime-Walkthrough — Schedule-Trigger einmal beobachten. - -**Block 2 — Niedrig hängende UI-Polish** (eine Session): -4. §2.1 Folder-Picker -5. §2.2 Delete-Confirmation -6. §2.4 Live-Log Auto-Scroll -7. §2.6 Status-Bar Live-Update -8. §2.8 Planning-Badge-Farbe + §2.9 tote Converter weg - -**Block 3 — Robustheit & Service-Deployment**: -9. §3.2 Worktree-Cleanup -10. §3.3 File-Sink-Logging -11. §4.3 Install-Skripte/Doku - -**Block 4 — Sicherheitsnetz**: -12. §5.1 Gitea-Actions CI-Pipeline (csproj-weise) -13. §5.3 Smoke-Test gegen echten claude -14. §5.4 ExternalMcpService-Tests vervollständigen - -**Block 5 — Dokumentation & Aufräumen**: -15. §6.1 README -16. §6.3 ADRs (mind. die fünf wichtigsten) -17. §6.4 Mailbox-Proposal: bauen/droppen entscheiden -18. §7 Smells: `ActiveTaskDto`, `.gitattributes`, TODO-Comment - -**Block 6 — Optional / wenn Bedarf konkret wird**: -19. §3.4 Tag-Negation -20. §IP-2 Notes-Modus -21. §IP-4 Tag Multi-Select Control +**Block 4 — Doku & Aufräumen:** §6.2 architecture.md (oder bewusst verwerfen), §6.3 ADRs, §6.4 Mailbox-Entscheidung, §2.1 Status-Bar-Risiko prüfen, §9 Smells. \ No newline at end of file