# ToDo-App mit autonomem Agent-Worker — Design ## Context Ziel: eine persönliche ToDo-App als Desktop-Anwendung, in der mehrere Listen verwaltet werden können. Ein Teil der Tasks soll autonom von Claude abgearbeitet werden (z.B. Recherche, Code-Aufgaben, Notizen-Verarbeitung). Die Autonomie läuft in einem getrennten Hintergrund-Prozess, damit die UI davon entkoppelt bleibt. Motivation: Aufgaben "parken" und später von einem Agenten abarbeiten lassen, ohne dafür manuell einen Chat zu öffnen. Ergebnisse landen wieder an der Task, sodass die Liste die Single-Source-of-Truth bleibt. ## Architektur-Überblick Ein Monorepo (`C:\Private\ClaudeDo`, gehostet auf `git.kuns.dev`), zwei Prozesse, gekoppelt über eine gemeinsame SQLite-Datenbank: ``` ┌─────────────────────┐ ┌──────────────────────┐ │ UI (Avalonia .NET) │ │ Worker (Node/TS) │ │ MVVM, Dialogs, │◄──────►│ Claude Agent SDK │ │ Queue-View │ SQLite │ Queue-Polling │ └─────────────────────┘ WAL └──────────────────────┘ │ │ └─────── todo.db ───────────────┘ (~/.todo-app/todo.db) ``` - **UI** (`todo-app-ui`, Avalonia MVVM): Listen & Tasks verwalten, Status ändern, Ergebnisse anzeigen. - **Worker** (`todo-app-worker`, TypeScript): pollt die DB, arbeitet `queued` Tasks ab, schreibt Ergebnisse zurück. - **SQLite im WAL-Mode** für sauberes concurrent read/write zwischen beiden Prozessen. ## Datenmodell Drei Tabellen in `todo.db`: **lists** - `id` (TEXT, uuid), `name` (TEXT), `tags` (TEXT, JSON-Array), `created_at` **tasks** - `id` (TEXT, uuid), `list_id` (FK), `title`, `description` - `tags` (JSON-Array, überschreibt/ergänzt List-Tags) - `status`: `manual` | `queued` | `running` | `done` | `failed` - `priority`: `normal` | `override` (→ läuft parallel zur Queue) - `scheduled_for` (TIMESTAMP, nullable — "nicht vor") - `result` (TEXT, Markdown), `log_path` (TEXT, Pfad zur Session-Log-Datei) - `created_at`, `started_at`, `finished_at` **worker_state** - `id` (1), `last_heartbeat`, `active_queue_task_id`, `active_override_task_id` - Dient UI als Signal, ob Worker läuft und welche Task aktiv ist. ## Tag-Modell (Startset) - Liste hat Default-Tags, Task erbt und kann ergänzen/überschreiben. - Minimal-Startset: - `manual` → Worker ignoriert, reine Notiz/Checkliste. - `agent` → Worker pickt auf, wenn Status `queued`. - Weitere Profile (`code`, `research` …) später als zusätzliche Tags + Handler im Worker. ## Queue-Semantik - **Default**: Tasks mit Tag `agent` und Status `queued` werden **sequenziell** abgearbeitet (FIFO, nach `created_at`). - **Schedule**: `scheduled_for` gesetzt → Worker überspringt, bis Zeit erreicht. - **Override**: UI-Button "Jetzt ausführen" setzt `priority = override`. Worker startet parallel zur laufenden Queue-Task. **Max. 1 Queue + 1 Override = 2 gleichzeitige Runs.** - Ein zweites Override während ein Override läuft → Meldung "Override bereits aktiv". ## Worker-Komponenten (TypeScript) - `db.ts` — better-sqlite3, Prepared Statements, WAL-Mode aktivieren. - `poller.ts` — alle 5s: nächste `queued` Task auswählen (Tag `agent`, `scheduled_for` ≤ jetzt, kein anderer Queue-Run aktiv), sowie pending `override`. - `runner.ts` — startet Agent-SDK-Run, streamt Messages in Log-Datei, speichert Ergebnis. - Input: Task-Titel + Description als User-Prompt. - Standard-Toolset: Read/Write in `~/.todo-app/sandbox//`, keine Netzwerk-Tools by default (später per Tag erweiterbar). - `state.ts` — schreibt Heartbeat alle 5s in `worker_state` (UI erkennt so, ob Worker läuft). - Konfig via `~/.todo-app/worker.config.json`: `ANTHROPIC_API_KEY`, `model`, `sandbox_root`, `poll_interval_ms`. ## UI-Komponenten (Avalonia) - **MainWindow** mit 2-Pane-Layout: links Listen, rechts Tasks der gewählten Liste. - **TaskItemView** zeigt Titel, Tags, Status (Badge), "Run Now"-Button (→ setzt `override`). - **TaskDetailPane** — erweiterbare Ansicht mit Description, Result-Markdown (AvaloniaEdit oder Markdown.Avalonia), Link zum Log. - **StatusBar** — zeigt Worker-Status aus `worker_state.last_heartbeat` (< 15s = online). - **SettingsDialog** — Default-Tags, Poll-Interval, Pfad zur todo.db. Zugriff auf DB via Microsoft.Data.Sqlite + schmaler Repository-Layer (`TaskRepository`, `ListRepository`). MVVM via CommunityToolkit.Mvvm. ## Project-Layout (Monorepo) **Repo: `ClaudeDo`** auf `git.kuns.dev`, lokal `C:\Private\ClaudeDo` ``` /ClaudeDo /ui Avalonia .NET 8 ClaudeDo.sln /src /ClaudeDo.App App.axaml, Program.cs (Entry) /ClaudeDo.Ui Views, ViewModels /ClaudeDo.Data Repositories, Models, SqliteConnectionFactory /tests /worker TypeScript / Node /src db.ts, poller.ts, runner.ts, state.ts, config.ts, index.ts /logs runtime, gitignored package.json, tsconfig.json /schema schema.sql Single source of truth für DB-Schema migrations/ (später, falls nötig) /docs README.md, architecture.md .gitignore bin/, obj/, node_modules/, logs/, *.db, worker.config.json ``` Vorteil Monorepo: gemeinsames `schema.sql`, atomische Änderungen über UI+Worker, ein Clone reicht. ## Verification 1. **Schema-Init**: Worker erstellt `todo.db` bei erstem Start mit WAL, legt Tabellen an. → `sqlite3 todo.db ".schema"` zeigt erwartete Tabellen. 2. **End-to-End Happy Path**: - UI: Liste "Test" anlegen, Task mit Tag `agent` + Status `queued` erzeugen, description: "Schreibe eine Haiku über Intralogistik". - Worker erkennt Task binnen 5s (Log: `picked up task `), startet Agent-Run, schreibt Result zurück. - UI zeigt Status `done` + Result-Markdown nach Reload/Refresh. 3. **Override-Parallelität**: Zwei `queued` Tasks anlegen → nur eine läuft. Bei zweiter "Run Now" klicken → beide laufen parallel, `worker_state` zeigt beide IDs. 4. **Schedule**: Task mit `scheduled_for = now + 2min` → Worker wartet; nach Ablauf startet sie. 5. **Worker-Offline-Erkennung**: Worker-Prozess killen → UI-StatusBar wechselt innerhalb 15s auf "offline". 6. **Unit-Tests** (Worker): `poller` Selection-Logik (Priorität Override, Schedule-Filter, Sequenzialität) mit In-Memory-SQLite. ## Offene Punkte für später (nicht Scope dieses Plans) - Zusätzliche Tag-Profile mit spezialisierten Toolsets (`code` → Bash/Git-Tools, `research` → WebFetch). - MCP-Server-Integration für externe Dienste. - Notification bei Task-fertig (Windows Toast). - Encrypted API-Key-Storage (erstmal Plaintext-JSON mit User-File-ACL).