Files
ClaudeDo/docs/plan.md
Mika Kuns 9435559468 initial
2026-04-13 09:22:58 +02:00

129 lines
6.9 KiB
Markdown

# 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/<task-id>/`, 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 <id>`), 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).