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

6.9 KiB

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).