From 94355594684662d44bca829fa0fcb0438c0c4069 Mon Sep 17 00:00:00 2001 From: Mika Kuns Date: Mon, 13 Apr 2026 09:22:58 +0200 Subject: [PATCH] initial --- docs/plan.md | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 docs/plan.md diff --git a/docs/plan.md b/docs/plan.md new file mode 100644 index 0000000..52993bf --- /dev/null +++ b/docs/plan.md @@ -0,0 +1,128 @@ +# 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).