diff --git a/docs/Agentenkommunikation-Konzept.md b/docs/Agentenkommunikation-Konzept.md index 77824b5..57fe3f5 100644 --- a/docs/Agentenkommunikation-Konzept.md +++ b/docs/Agentenkommunikation-Konzept.md @@ -1,5 +1,9 @@ # Agentenkommunikation — Erfassung, Ansicht, Auswertung +> **Bauplan — noch nicht gebaut.** Die fünf Phasen sind in der [Roadmap](Roadmap.md) 3.3 +> einzeln eingeordnet; die Tiefenbegrenzung (B8) ist dort Punkt 4 der Reihenfolge. +> Die Ansicht aus Phase 4 steht bereits und wartet auf den Speicher aus Phase 2. + Ziel: Die **gesamte** Kommunikation zwischen Agenten wird erfasst, ist im WhatsApp-Stil paarweise nachlesbar und lässt sich von einem Agenten automatisiert auswerten — um zu finden, wo die Zusammenarbeit klemmt. diff --git a/docs/Audit-Konzept.md b/docs/Audit-Konzept.md index a8ba239..3054350 100644 --- a/docs/Audit-Konzept.md +++ b/docs/Audit-Konzept.md @@ -1,5 +1,8 @@ # Audit-Log & Receipts — Nachvollziehbarkeit +> **Bauplan zu einem gebauten System.** Umgesetzt; der Stand steht in der +> [Roadmap](Roadmap.md) 3.1. + Setzt A3 aus der [Roadmap](Roadmap.md) um (F-A2). Zwei zusammengehörige Dinge: - **Audit-Log** — ein Eintrag je Tool-Aufruf: wer, wann, welches Tool, mit welchem diff --git a/docs/Deploymentcenter-Integration.md b/docs/Deploymentcenter-Integration.md index b213983..01abcc1 100644 --- a/docs/Deploymentcenter-Integration.md +++ b/docs/Deploymentcenter-Integration.md @@ -1,5 +1,8 @@ # Deploymentcenter-Integration +> **Beschreibung der Verdrahtung** (Heartbeat, Fehler-Stream, Bugtracker, Updates). +> Offene Punkte dazu stehen in der [Roadmap](Roadmap.md) 3.5, nicht hier. + Stand: 2026-08-08, Deploymentcenter **2.1**. Ersetzt den früheren `Integrationsplan-WatchDog-LicenseLabrador.md`. @@ -179,7 +182,7 @@ Die frühere Fassung führte einen Ed25519-Public-Key als „Vertrauensanker". I Deploymentcenter gibt es dazu keine Gegenseite — der Client liest ausschließlich das Feld `status`. Ein Schlüssel, der nichts prüft, ist schlimmer als keiner: Er lässt Schutz vermuten, wo keiner ist. Details in -[Deploymentcenter-Anbindung-Review](Deploymentcenter-Anbindung-Review.md), Abschnitt 2.1. +[Deploymentcenter-Anbindung-Review](archiv/Deploymentcenter-Anbindung-Review.md), Abschnitt 2.1. ### Der Projekt-Slug ist `clawddotnet` diff --git a/docs/Memory-Konzept.md b/docs/Memory-Konzept.md index 67b3ce1..9bcb817 100644 --- a/docs/Memory-Konzept.md +++ b/docs/Memory-Konzept.md @@ -1,6 +1,9 @@ # Memory — Langzeitgedächtnis für Agenten -Löst K1 aus der [Bestandsaufnahme](Bestandsaufnahme-2026-07.md): Geplante Agenten +> **Bauplan zu einem gebauten System.** Umgesetzt; der Stand steht in der +> [Roadmap](Roadmap.md) 3.2. Die drei Punkte unter „Offen" laufen dort weiter. + +Löst K1 aus der [Bestandsaufnahme](archiv/Bestandsaufnahme-2026-07.md): Geplante Agenten begannen bei jedem Cron-Lauf bei null. Ein Agent, der alle 30 Minuten lief, wusste nichts von seinem letzten Durchgang — er rief dieselben Quellen ab, zog dieselben Schlüsse und konnte keine Entwicklung über Zeit verfolgen. diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 069f376..67e157c 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -1,355 +1,345 @@ -# Roadmap +# ClawdDotNet — Roadmap -**Stand: 2026-08-23** (Frühjahrsputz). Was seither gilt: +**Dies ist die einzige Vorhabenliste.** Vor dem 2026-08-23 lag der Stand über eine +Bestandsaufnahme, drei Konzeptpapiere, vier Umsetzungspläne und zwei +Deploymentcenter-Dokumente verteilt — jedes mit eigener Reihenfolge, teils +widersprüchlich. Alles davon ist hier zusammengeführt. -| Bereich | Stand | -|---|---| -| A1 Taskboard | **erledigt** — Dateiformat, Scanner mit Claiming, `task_*`-Tool, Migration, Tests | -| A3 Audit-Log | **erledigt** — append-only auf SQLite, Engine stempelt die Herkunft | -| A2 Staging | **halb** — Gate, Policy, Ablage und Dienst stehen und greifen; **die Freigabe-Ansicht fehlt.** Bis sie da ist, legt ein Agent Vorschläge ab, die niemand freigeben kann | -| Oberfläche | **portiert** — neun Bereiche nativ in Avalonia, Entwurf aus `Mockup/` umgesetzt. Die WinForms-Fassung ist entfernt (Tag `vor-fruehjahrsputz-2026-08`) | -| Rocket.Chat | Tool umgesetzt und registriert. **Damit steht A5 zur Entscheidung an** — siehe unten | -| Pakete | keine bekannten Sicherheitslücken mehr; `SharpCompress` und `SQLitePCLRaw.bundle_e_sqlite3` sind als Anhebung direkt verwiesen | - -Die vier [Umsetzungspläne](umsetzungsplaene/) vom 2026-08-05 sind **alle noch offen**: -FileRW-Papierkorb, AgentInspector, AgentEditor-Härtung, WebSearch. Ihre Reihenfolge -steht in den Dokumenten selbst; sie sind hier nicht doppelt eingeordnet. +Gepflegt wird nur noch dieses Dokument. Was aus den alten Papieren wurde, steht in +[Abschnitt 7](#7--woher-das-hier-kommt). --- -Zentrale Liste aller offenen Vorhaben. Sie löst die beiden „Vorgeschlagene -Reihenfolge"-Abschnitte in der [Bestandsaufnahme](Bestandsaufnahme-2026-07.md) und im -[Konzepte-Dokument](Konzepte-Backup-Finanz-Analyse.md) ab — die bleiben als Befund bzw. -Konzept bestehen, gepflegt wird nur noch hier. +## Wie das hier zu lesen ist -Kürzel (S4, K2, T4, F-A1, …) verweisen auf die Bestandsaufnahme. +| Zeichen | Bedeutung | +|---|---| +| ✅ | erledigt | +| 📋 | **beschlossen**, noch nicht gebaut — kann jederzeit angefasst werden | +| ❓ | **Entscheidung nötig**, bevor gebaut werden kann | +| ❄️ | zurückgestellt — wartet auf eine Entscheidung oder ein anderes Vorhaben | +| 💭 | **Idee**, nicht beschlossen — bewusst geparkt, damit sie nicht verlorengeht | + +Die **Herkunft**-Spalte trägt das alte Kürzel (S4, K2, B9, T4, F-A1, C1, DC1 …). Damit +bleiben die archivierten Papiere auffindbar, ohne dass man sie lesen muss. + +**Bauplan** heißt: Es gibt ein Dokument, das die Umsetzung im Detail beschreibt. Wer den +Punkt anfasst, liest es zuerst. --- -## A — Beschlossen (aus dem OpenAlice-Vergleich, Juli 2026) +## 0 — Stand -Hintergrund: Konzeptvergleich mit [OpenAlice](https://github.com/TraderAlice/OpenAlice) -(AGPL-3.0 — Konzepte übernehmen ja, Code nein). Übernommen werden Taskboard, -Staging-Freigabe, Audit-Log und das Skill-Modell. Die Inbox-Idee entfällt zugunsten -der geplanten Matrix-Migration (A5). +Der Kern trägt. Engine, Taskboard, Audit, Gedächtnis, Budget, Sicherung und die +Oberfläche sind gebaut und getestet (585 Tests grün, Build fehlerfrei, keine bekannten +Sicherheitslücken in den Paketen). Die Sicherheitsbefunde S1–S7 und die Bugs B1–B5, +B11, B12 aus der Bestandsaufnahme sind abgearbeitet. -### A1 — Taskboard — **erledigt** +Drei Dinge stehen im Weg: -Aufgaben als Markdown-Dateien mit YAML-Frontmatter im `SharedWorkspace`: -`title`, `status` (`backlog | todo | in_progress | done | canceled`), `priority`, -`assignee`, optional `when` (`at` | `every` | `cron` **mit Zeitzone**). - -- **Scanner statt Delay-Schleifen**: Ein Takt (~60 s) prüft, was fällig ist. - Persistiert werden nur Last-Fired-Marker — ein fehlgeschlagener Lauf bleibt der - einzige Versuch für diesen Termin, kein automatischer Retry-Sturm. -- **Assignee bestimmt die Ausführung**: `@new` = frischer Lauf ohne Historie, - `@` = bestehender Agent mit seinem Kontext, `@human` = wartet auf uns. - Das ersetzt das implizite `UseChatContext`-Flag (T7) durch eine explizite Angabe - am Auftrag. -- **Agenten-Tool**: `task_create`, `task_list`, `task_update`, `task_comment`. - Agent-zu-Agent-Delegation läuft künftig über Tasks statt über rekursives - `send_message`. -- **Migration**: Die improvisierten `coordination/*.md`-Dateien der Agenten - (task_*, status_*, broadcast) gehen im Taskboard auf. - -**Detailbauplan** (aus dem Fünf-Repo-Vergleich, Juli 2026 beschlossen): - -- Status zusätzlich mit **`in_review`**; im Frontmatter **`require_approval`** - (Task gilt erst nach Review als done) und **`acceptance`** (Abnahmekriterien, - gegen die das Ergebnis geprüft wird). -- **Task-Typen `approval` und `human_input`** — ein Mensch ist einfach ein - Assignee; seine Antwort ist das Task-Ergebnis und Input für Folgetasks. -- **Atomares Claiming**: Die DB verhindert, dass zwei Läufe denselben Task - ziehen. Der Scanner arbeitet mit **Claim-before-run** (at-most-once — ein - doppelter Tick findet den Claim bereits vergeben) und - **Startup-Reconciliation**: Beim Start wird Soll (Frontmatter) gegen Ist - (Marker/Claims) abgeglichen, verpasste Läufe werden erkannt statt still - übersprungen. -- **`blocked_by`-Abhängigkeiten** mit Auto-Dispatch: Wird der letzte Blocker - fertig, wird der wartende Task automatisch angestoßen. Meldet ein Agent einen - Blocker, fällt der Task und der Zuständige (Lead/Benutzer) wird benachrichtigt - (**Blocker-Eskalation**). -- **Reopen-/Feedback-Semantik**: Ergebnis + Kritik gehen per `task_comment` an - denselben Agenten zur Nachbesserung zurück, statt einen neuen Task von vorn - zu beginnen. - -Damit erledigt oder aufgegangen: - -| Punkt | Warum | -|---|---| -| F-A5 Task-Queue | das Taskboard **ist** die Queue | -| F-A4 Run-Historie | Läufe werden am Task verknüpft und persistiert | -| B8 Rekursion `send_message` | Delegation über Tasks ist strukturell zyklenfrei | -| B6 `Task.Delay`-Überlauf | Scanner-Modell kennt keine langen Delays | -| B7 Cron in Lokalzeit | Frontmatter-`when` ist zeitzonen-explizit | -| T7 `RunAsync` vs. `ChatAsync` | Assignee-Semantik beantwortet die Frage | - -Verzahnung: Das Marktkalender-Flag (`onlyWhenMarketOpen`, siehe C1) gehört ins -Frontmatter, nicht in einen eigenen Mechanismus. - -Konzept-Doc: [Taskboard-Konzept](Taskboard-Konzept.md) (Dateiformat, -Wahrheitsaufteilung Datei/DB, Scanner-Verhalten, Invarianten, Migration). - -### A2 — Staging-Freigabe für irreversible Aktionen (F-A1 + S4) — **Kern erledigt, Ansicht offen** - -> **Der offene Rest ist die Freigabe-Ansicht.** `StagingService` bietet -> `ListPendingAsync`, `ApproveAsync` und `RejectAsync`, `AppHost.Staging` reicht ihn -> an die Oberfläche durch — aber kein Ansichtsmodell ruft sie auf. Ein gestagter -> Aufruf liegt damit unbegrenzt in der Ablage. Solange das so ist, ist jede Aktion -> auf `Approve` faktisch eine Aktion auf `Deny`, nur ohne Rückmeldung an den Agenten. - -Konzept-Doc: [Staging-Konzept](Staging-Konzept.md). - -Irreversible Aktionen (Mail senden, X posten, DB-Schreibzugriff, Datei löschen, -perspektivisch Orders) werden **gestaged statt ausgeführt**: Vorschlag → Review im -Hauptfenster → Freigabe/Ablehnung. Pro Tool/Aktion konfigurierbar: -`auto | approve | deny`. - -Das bisher wirkungslose `PermissionGate` (S4) wird dabei zum zentralen -Durchsetzungspunkt ausgebaut: Policy-Prüfung, Staging-Entscheidung und Audit-Hook -(A3) an einer Stelle statt ad-hoc in jedem Tool. S4 wird nicht separat bearbeitet, -sondern geht hier auf. - -Ergänzungen (Juli 2026 beschlossen): - -- **Plan-Freeze**: Freigegeben wird ein eingefrorener, konkreter Aufruf — Tool, - Aktion und exakte Argumente zum Zeitpunkt des Stagings. Ausgeführt wird genau - das Eingefrorene; jede nachträgliche Änderung ist eine neue Freigabe. -- **Approval-Records**: Jede Entscheidung (Freigabe wie Ablehnung) wird als - Datensatz im Audit-Log (A3) verankert — wer, wann, was, mit welchem Ergebnis. - -Sicherheitswirkung: Eine Prompt-Injection (K2) kann dann nur noch einen Vorschlag -erzeugen, keine Ausführung. - -### A3 — Audit-Log (F-A2) — **erledigt** - -Konzept-Doc: [Audit-Konzept](Audit-Konzept.md). - -Jeder Tool-Aufruf wird protokolliert: Agent, Lauf/Session, Zeitstempel, Argumente, -Ergebnis-Status. Append-only (JSONL oder SQLite-Tabelle auf dem vorhandenen -`SqliteStorage`). - -Designregeln (aus dem OpenAlice-Provenance-Konzept): - -- Herkunft wird **von der Engine gestempelt**, nie vom Agenten behauptet. -- Einträge sind unveränderlich; Korrekturen sind neue Einträge. -- Unbekannte Herkunft wird als unbekannt markiert, nicht geraten. -- Worker-Typ (Modell/Engine) und verantwortliche Session sind getrennte Begriffe. - -Ergänzung (Juli 2026 beschlossen) — **Receipts**: Jeder abgeschlossene Task/Lauf -erhält einen Abschluss-Beleg mit Ergebnis-Verweis, Schritten, Tokens und Kosten -(Verknüpfung `RunUsage` ↔ Task). Damit fällt C7 („Kosten pro Ergebnis") -weitgehend als Abfallprodukt ab. - -Das Audit-Log ist zugleich das Fundament für das Ergebnisregister (C7) und die -Tool-Fehlerquote aus der Leistungsanalyse. - -### A4 — Skill-/Toolset-Modell (ersetzt T6) - -Dreischichtig statt „alles immer im System-Prompt": - -1. **Dauerhafter Kern** — Identity, Soul, unveränderliche Regeln. Schlank, damit der - Prompt-Cache (T1) stabil bleibt. -2. **Nachladbare Skills/Toolsets** — fachliche Abläufe und selten genutzte Tools - werden erst auf Anforderung geladen (`list_toolsets` → `load_toolset`). -3. **Selbstkorrigierende Tool-Fehler** — Fehlermeldungen nennen die gültigen - Parameter/Aktionen, statt das Modell raten zu lassen. - -Mechanik (Juli 2026 beschlossen, nach GoClaw-Vorbild): Skills liegen als -`SKILL.md` mit Frontmatter (`name`, `description`) im Instanz- bzw. -Agenten-Verzeichnis. Bei wenigen Skills werden die Kurzbeschreibungen inline in -den Prompt eingebettet, bei vielen gibt es stattdessen ein `skill_search`-Tool. -Änderungen an Skill-Dateien werden per Hot-Reload übernommen. - -Dazu Hermes' Selbstverbesserungs-Idee: **Agenten dürfen Skills aus Erfahrung -selbst schreiben** (das AgentEditor-Tool ist die Vorstufe). Wichtig: Ein Skill -ist Prompt-Input — agentengeschriebene Skills werden erst nach Freigabe (A2) -aktiv, sonst wäre das ein Injection-Kanal in künftige Läufe. - -### A5 — Matrix/Element-Migration - -Beschlossene Richtung: Die Kommunikation (Benachrichtigungen, Berichte, Chat mit -Agenten) wird auf Element/Matrix umgestellt. - -- Ersetzt die im OpenAlice-Vergleich erwogene Inbox — Berichte landen in - Matrix-Räumen. -- Der Tool-Kandidat **Notify** entfällt und geht hierin auf. -- Betroffen: Telegram-Tool (Rolle klären), WebView-Chat (bleibt er Haupt-UI?), - Streaming K4 (Matrix streamt nicht — nach dieser Entscheidung neu bewerten). - -Scope ist noch unbestimmt — braucht ein eigenes Konzept-Doc, bevor es in die -Reihenfolge eingeordnet wird. - -**Kollision, seit Rocket.Chat steht (August 2026):** Das -[Rocket.Chat-Tool](../src/ClawdDotNet.Tools.RocketChat/) ist umgesetzt und im -`AppHost` registriert — es bedient genau den Zweck, für den A5 Matrix vorsah. -Entweder A5 entfällt und Rocket.Chat wird der Weg, oder wir betreiben zwei -Chat-Wege nebeneinander. Das ist **die nächste offene Grundsatzentscheidung**; -siehe [RocketChat-Nextcloud-Konzept](RocketChat-Nextcloud-Konzept.md). - -### A6 — MySQL-Replikations-Spiegel (optional) - -Beschlossen Juli 2026. **SQLite bleibt die einzige Wahrheit** — gearbeitet wird -ausschließlich auf der Instanz-DB. MySQL ist ein reiner, nachgelagerter Spiegel: -Er empfängt nur INSERT/UPDATE/DELETE vom Replikator; die App liest im Betrieb -**nie** daraus. Einziger Lesezweck: Wiederherstellung, falls die SQLite korrupt -ist — daneben steht der Spiegel externen Auswertungen (Dashboards, Ad-hoc-SQL) -offen, ohne die Agenten-Maschine zu berühren. - -Leitplanken: - -- **Outbox-Muster** an der vorhandenen Schreib-Warteschlange von `SqliteStorage`: - Replikations-Einträge lokal puffern, idempotente Upserts nach MySQL. - Nie blockierend — ist MySQL nicht erreichbar, staut die Outbox und holt auf. -- Mehrere Instanzen replizieren in denselben Spiegel; Zeilen tragen `instance_id`. -- **Restore-Pfad (Spiegel → frische SQLite) muss existieren und getestet sein** — - gleiche Regel wie beim Backup: ein ungeprüftes Restore ist eine Vermutung. -- Kein Koordinationspunkt: Claiming, Locks, Taskboard-Zustand bleiben lokal. - Die Regel „nur der Replikator schreibt, niemand liest im Betrieb" gehört ins - Konzept-Doc. -- Sicherheit: TLS zur Datenbank, Zugangsdaten über `SecretProtector`; - Output-Scrubbing der Tool-Ergebnisse wird wichtiger, weil Kontext-Daten - künftig auch im Spiegel liegen. -- Ergänzt das ZIP-Backup, ersetzt es nicht — Identity/Soul, Settings, Workspace - und Telegram-Session bleiben Sache des Instanz-Backups. - -**Voraussetzung — Historie-Umzug:** `ChatHistory.json` zieht in die Instanz-DB um -(aktive Tabelle + Archiv-Tabelle mit FTS5-Volltextindex und `history_search`-Tool, -siehe K6 in Abschnitt B). Das löst -nebenbei B10 (O(n²)-Schreiblast) und gibt K6 seine Form; erst danach schützt der -Spiegel auch die Historie. Zeitlich passt A6 zu dem Server, der ggf. mit A5 -(Matrix) ohnehin dazukommt. +1. **Die Freigabe-Ansicht fehlt.** Staging ist gebaut und greift — aber niemand kann + freigeben. Damit ist der unbeaufsichtigte Betrieb, für den das ganze A2-Vorhaben da + war, nicht möglich. +2. **A5 ist unentschieden.** Rocket.Chat ist gebaut und bedient denselben Zweck, für den + Matrix vorgesehen war. Solange das offen ist, hängen Streaming (K4), der + Notfallkanal und ein Teil von A6 in der Luft. +3. **Agenten können sich gegenseitig verklemmen.** `AgentComm.send_message` hat keine + Tiefenbegrenzung; A→B→A blockiert bis zum Timeout. Bekannt seit Juli, unverändert. --- -## B — Offen aus der Bestandsaufnahme +## 1 — Reihenfolge -| Punkt | Was | Stand | -|---|---|---| -| T4 | Proaktiv statt reaktiv kompaktieren | offen, unverändert | -| K2-Rest | Untrusted Content als Daten rahmen (``) | A2 nimmt die Schärfe; die Rahmung selbst bleibt nötig | -| K4 | Streaming | **zurückgestellt** bis A5 entschieden ist | -| K6 | Historie **archivieren + durchsuchbar machen** (FTS5-Index, `history_search`-Tool) statt nur rotieren | beschlossen; Teil des Historie-Umzugs (Voraussetzung von A6) | -| Memory-Flush vor Compaction | Bevor der ContextCompactor zusammenfasst, bekommt der Agent ein eng begrenztes Fenster, Dauerhaftes per `memory_store` zu sichern — sonst wirft die Compaction Wissen weg | beschlossen (GoClaw-Muster) | -| Memory-Auto-Injection | Relevante Memory-Abstracts werden automatisch eingeblendet (Relevanzschwelle, Deckel ~200 Tokens), **in die Nutzernachricht, nie in den System-Prompt** (Prompt-Cache T1) | beschlossen; löst den offenen Punkt „Automatische Einblendung" im [Memory-Konzept](Memory-Konzept.md) | -| Output-Scrubbing | Bekannte Secret-Werte (Register des `SecretProtector`) werden zentral aus **allen** Tool-Ergebnissen maskiert, bevor sie in Kontext, Historie oder Spiegel (A6) gelangen | beschlossen; schließt die Lücke, die S3 nur für URLs schloss | -| Hygiene-Paket | B9 (`index_Count`-Race), B13 (`instanceId`-Inkonsistenz), F-A6-Rest (UI zum Setzen/Rotieren der Secrets) | Kleinbugs, in einem Aufwasch. B11/T8 (`max_tokens`) ist erledigt — `AgentEngine` setzt es aus `LoopGuard.MaxResponseTokens`. B10 geht im Historie-Umzug (A6) auf | +Was als Nächstes ansteht, mit Begründung. Alles darunter in Abschnitt 3. -Erledigt seit der letzten Fortschreibung: B4 vollständig (Preise kommen live vom -`/models`-Endpunkt, unbekannte Modelle werden sichtbar gemeldet). Beim Frühjahrsputz -dazugekommen: die automatische Sicherung lief ins Leere — die Oberfläche bot sie an -und schrieb die Uhrzeit weg, aber der `BackupScheduler` wurde nie gestartet. Jetzt -verdrahtet. +| # | Vorhaben | Warum an dieser Stelle | Bereich | +|---|---|---|---| +| **1** | **Freigabe-Ansicht** (Rest von A2) | Der einzige Punkt, der echten Betrieb blockiert. Die Dienst-API steht vollständig; es fehlt eine Seite mit Liste und zwei Schaltflächen | [3.1](#31--kontrolle-und-sicherheit) | +| **2** | **A5 entscheiden**: Matrix oder Rocket.Chat | Kostet keine Umsetzung, löst aber drei blockierte Punkte auf einmal. Deshalb früh | [2](#2--offene-entscheidungen) | +| **3** | **FileRW-Papierkorb** | Kleinster Eingriff mit realer Wirkung: `delete` ist heute endgültig, ein Aufruf mit `path: "."` räumt einen Workspace ab. Danach kann `FileRW.delete` von `approve` auf `auto` — das entlastet die Freigabe-Ansicht sofort | [3.2](#32--agenten-fähigkeiten) | +| **4** | **Delegationstiefe begrenzen** (B8) | Behebt eine echte Verklemmung. Kleiner Eingriff, aber am Agent-Gate — mit Test A13 aus der [Teststrategie](Teststrategie.md) | [3.3](#33--kommunikation-zwischen-agenten) | +| **5** | **Output-Scrubbing** | Muss **vor** allem stehen, was Tool-Ergebnisse dauerhaft speichert (Agentenkommunikation Phase 2, MySQL-Spiegel). Sonst legen wir einen Speicher an, der nachträglich bereinigt werden müsste | [3.1](#31--kontrolle-und-sicherheit) | +| **6** | **C1 Marktkalender** | Spart ab dem ersten Tag Geld: Ein `*/30`-Cron läuft heute auch Sonntag um 3 Uhr. Der Haken im Scanner ist schon da (`IMarketCalendar`) | [3.6](#36--finanz-und-analyse) | +| **7** | **A4 Skills/Toolsets** | Größter Token-Hebel nach dem Caching, und Voraussetzung dafür, dass Agenten viele Tools haben können, ohne dass jeder Schritt teuer wird | [3.2](#32--agenten-fähigkeiten) | +| **8** | **Historie-Umzug in die Instanz-DB** | Löst B10 (O(n²)-Schreiblast) und K6 (unbegrenzte Historie) in einem Zug und ist Voraussetzung für A6 | [3.4](#34--daten-und-speicher) | +| — | **DC1 „Fehler melden"** | Zwischendurch; der Client steht, es fehlt die Schaltfläche | [3.5](#35--betrieb-und-auslieferung) | +| — | **Hygiene-Paket** | Zwischendurch, unabhängig von allem | [3.7](#37--hygiene) | -Neu aufgenommen (aus der Ideensammlung, die dabei aufgelöst wurde): +Leitlinie: **erst Bremsen, dann PS.** Ein Agent, der unbeaufsichtigt läuft, braucht +Nachvollziehbarkeit und Kontrolle, bevor er mehr können soll. Deshalb stehen Freigabe, +Papierkorb, Tiefenbegrenzung und Scrubbing vor den Fähigkeiten. -| Punkt | Was | -|---|---| -| Werkzeugwunsch | Agenten bekommen in den Kern-Prompt den Hinweis, sich zu melden, wenn ihnen ein Werkzeug fehlt, das es noch nicht gibt. Der Weg dafür ist da — ein Task an `@human` (A1). Gehört zum Prompt-Kern von A4 | +--- -### B-DC — Deploymentcenter-Anbindung +## 2 — Offene Entscheidungen + +Diese Punkte kann niemand bauen, bevor sie entschieden sind. Sie kosten kein +Entwicklungsbudget, nur eine Festlegung. + +| # | Frage | Was daran hängt | Empfehlung aus dem Konzept | +|---|---|---|---| +| **E1** ❓ | **Matrix oder Rocket.Chat?** Rocket.Chat ist gebaut und bedient A5. Bleibt Matrix Ziel, oder entfällt A5? | K4 (Streaming), ob der `ChannelRouter` Pflicht oder Kür ist, wo A6 wohnt | Keine — bewusst offengelassen ([RocketChat-Konzept §4](RocketChat-Nextcloud-Konzept.md)) | +| **E2** ❓ | **Nextcloud-Identität**: ein Dienstkonto mit Ordnern je Agent, oder je Agent ein eigener Benutzer? | Zuschnitt des Nextcloud-Tools | Dienstkonto | +| **E3** ❓ | **Öffentliche Freigabe-Links** grundsätzlich erlauben (mit Freigabe) oder hart sperren? | Voreinstellung `allowPublicShares` | offen | +| **E4** ❓ | **`ask_agent` behalten** (eng gefasst, Tiefe 1) oder ersatzlos streichen und alles über Tasks? | Zuschnitt von Phase 3 der Agentenkommunikation | behalten, eng gefasst | +| **E5** ❓ | **Notfallkanal-Reihenfolge** instanzweit oder je Agent einstellbar? | Kleinigkeit am `ChannelRouter` | instanzweit | +| **E6** ❓ | **`catchUp: true\|false`** je Task abschaltbar machen? | Verhalten des Scanners bei verpassten Terminen | offen | +| **E7** ❓ | **Priorität bei mehreren fälligen Tasks**: strikt oder gewichtet? | Reihenfolge im Scanner | offen | +| **E8** ❓ | **Aufbewahrungsdauer** der Agentenkommunikation | Vorgabewert im Speicher | unbegrenzt, bis A6 steht; dann 180 Tage lokal | +| **E9** ❓ | **Automatische Orderausführung** — überhaupt? | Der gesamte Handels-Zweig. Broker-API, Teilausführungen, rechtlicher Rahmen — eigene Kategorie, kein Nebenprodukt der Analyse-Agenten | bewusst **nicht** vorgesehen | + +--- + +## 3 — Beschlossen und offen + +### 3.1 — Kontrolle und Sicherheit + +Bauplan: [Staging-Konzept](Staging-Konzept.md), [Audit-Konzept](Audit-Konzept.md). + +| Punkt | Herkunft | Stand | Was | +|---|---|---|---| +| Audit-Log + Receipts | F-A2, A3 | ✅ | Append-only auf SQLite. Herkunft wird von der Engine gestempelt, nie vom Agenten behauptet. Einträge unveränderlich, Korrekturen sind neue Einträge. Receipts verknüpfen Lauf ↔ Task mit Schritten, Tokens, Kosten | +| Staging-Kern | F-A1, S4, A2 | ✅ | `PermissionGate` ist zum Durchsetzungspunkt ausgebaut. Policy `auto\|approve\|deny` je Tool/Aktion, Plan-Freeze (der eingefrorene Aufruf wird ausgeführt, nicht ein neu formulierter), atomarer Übergang `pending → approved`, Fortsetzung über Folge-Task statt pausiertem Lauf | +| **Freigabe-Ansicht** | A2 | 📋 **#1** | Seite in `src/ClawdDotNet.Desktop`: offene Vorschläge listen, freigeben, ablehnen (mit Grund). `StagingService.ListPendingAsync/ApproveAsync/RejectAsync` steht bereit, `AppHost.Staging` reicht ihn durch. **Ohne sie liegt jeder gestagte Aufruf unbeantwortet** | +| **Output-Scrubbing** | — | 📋 **#5** | Bekannte Secret-Werte aus dem Register des `SecretProtector` werden zentral aus **allen** Tool-Ergebnissen maskiert, bevor sie in Kontext, Historie, Audit-`Arguments` oder Spiegel gelangen. Ein Filter an `ExecuteToolCallAsync`. Schließt die Lücke, die S3 nur für URLs schloss | +| Untrusted Content rahmen | K2-Rest | 📋 | Tool-Ergebnisse als Daten rahmen (``) und im Kern-Prompt verankern, dass daraus keine Anweisungen befolgt werden. Staging nimmt die Schärfe, die Rahmung bleibt nötig — Finanzinhalte auf X und in Newslettern sind genau der Ort, an dem gezielt manipuliert wird | +| Secret-UI | F-A6-Rest | 📋 | Oberfläche zum Setzen und Rotieren der Zugangsdaten. Die Verschlüsselung (S7, DPAPI) steht | +| Audit-Export | — | 💭 | JSONL-Export für externe Auswertung. Passt zum A6-Spiegel | + +### 3.2 — Agenten-Fähigkeiten + +| Punkt | Herkunft | Stand | Was | +|---|---|---|---| +| Taskboard | A1, F-A5, F-A4 | ✅ | Markdown + YAML-Frontmatter im `SharedWorkspace`, Zustand in der DB. Scanner im 60-s-Takt statt Delay-Schleifen, atomares Claiming (at-most-once), Startup-Reconciliation, `blocked_by` mit Auto-Dispatch, Blocker-Eskalation, Reopen über `task_comment`. Assignee entscheidet: `@new`, `@`, `@human`. Bauplan: [Taskboard-Konzept](Taskboard-Konzept.md) | +| Langzeitgedächtnis | K1 | ✅ | Typisierte Tabelle statt JSON im State-Store. Scope `agent`/`shared`, optionaler `Key` (erneutes Merken aktualisiert statt anzulegen), Wichtigkeit steuert die Reihenfolge bei Kappung. Bauplan: [Memory-Konzept](Memory-Konzept.md) | +| **FileRW-Papierkorb** | — | 📋 **#3** | `delete` verschiebt in einen Papierkorb je Workspace statt endgültig zu löschen; ein Cron-Task räumt nach X Tagen auf. Danach kann `FileRW.delete` im Staging von `approve` auf `auto`. Bauplan: [Umsetzungsplan](umsetzungsplaene/UMSETZUNGSPLAN-FileRW-Papierkorb-Cleanup.md) | +| **A4 Skills/Toolsets** | T6 | 📋 **#7** | Dreischichtig statt „alles immer im System-Prompt": schlanker Dauerkern (hält den Prompt-Cache stabil), nachladbare Skills als `SKILL.md` mit Frontmatter (`list_toolsets` → `load_toolset`, bei vielen Skills stattdessen `skill_search`), Hot-Reload über `FileSystemWatcher` mit Debounce. Tool-Fehlermeldungen nennen die gültigen Parameter, statt das Modell raten zu lassen. **Agenten dürfen Skills aus Erfahrung selbst schreiben — aber erst nach Freigabe (A2) aktiv**, sonst ist es ein Injection-Kanal in künftige Läufe | +| Memory-Flush vor Compaction | — | 📋 | Bevor der `ContextCompactor` zusammenfasst, bekommt der Agent ein eng begrenztes Fenster, Dauerhaftes per `memory_store` zu sichern — sonst wirft die Compaction Wissen weg. Harte Grenzen: max. 3–5 Schritte, einziges Tool `memory_store`, Timeout, günstiges Modell, höchstens einmal je Zyklus | +| Memory-Auto-Injection | — | 📋 | Relevante Abstracts automatisch einblenden (Relevanzschwelle, Deckel ~200 Tokens). **In die Nutzernachricht, nie in den System-Prompt** — sonst verfällt der Prompt-Cache | +| Proaktive Compaction | T4 | 📋 | `CompactIfNeededAsync` läuft heute **nach** dem API-Aufruf und nutzt die `promptTokens` der gerade bezahlten Anfrage — der überfüllte Prompt wurde also schon bezahlt. Vor dem Senden prüfen (`EstimateTokens` gibt es), gemessene Werte zur Kalibrierung | +| AgentEditor härten | — | 📋 | Änderungen an `Identity.md`/`Soul.md` bleiben im laufenden Betrieb möglich, werden aber freigabepflichtig, nachvollziehbar und rücknehmbar. **Reihenfolge: nach AgentInspector.** Bauplan: [Umsetzungsplan](umsetzungsplaene/UMSETZUNGSPLAN-AgentEditor-Haertung.md) | +| AgentInspector | — | 📋 | Ein Supervisor-Agent kann beurteilen, ob die anderen tun, was sie sollen — über Audit-Log, Taskboard und lesenden Zugriff auf fremde Workspaces. Heute geht nur die Selbstauskunft, und die ist als Kontrollinstrument wertlos. Bauplan: [Umsetzungsplan](umsetzungsplaene/UMSETZUNGSPLAN-AgentInspector-Supervisor.md) | +| Memory-Verfall | — | 💭 | Alte, unwichtige Beobachtungen nach einer Frist entfallen lassen | +| Task-Archivierung | — | 💭 | `done`/`canceled` nach einer Frist archivieren, damit `tasks/` nicht zuwächst | +| Werkzeugwunsch | — | 💭 | Agenten bekommen in den Kern-Prompt den Hinweis, sich zu melden, wenn ihnen ein Werkzeug fehlt. Der Weg ist da — ein Task an `@human`. Gehört zum Prompt-Kern von A4 | + +### 3.3 — Kommunikation zwischen Agenten + +Bauplan: [Agentenkommunikation-Konzept](Agentenkommunikation-Konzept.md). **Nichts davon +ist gebaut** — mit einer Ausnahme: Die Ansicht (Phase 4) steht bereits als +`AgentChatsPageView` und wartet nur auf den Datenbestand aus Phase 2. + +| Punkt | Herkunft | Stand | Was | +|---|---|---|---| +| **Delegationstiefe begrenzen** | B8 | 📋 **#4** | `AgentComm.send_message` ist ein synchroner Aufruf ohne Tiefenbegrenzung. A→B→A verklemmt echt: A hält sein Gate, während es auf B wartet — ruft B nun A, wartet B auf As Gate. Löst nur der Timeout auf. Test A13 der [Teststrategie](Teststrategie.md) deckt genau das ab und **fehlt bis heute** | +| Phase 1 — Korrelation | — | 📋 | `ParentRunId` + `RootRunId` in Audit-Log und Receipts, von der Engine gestempelt. Eine Delegationskette wird damit zu einer Abfrage. Voraussetzung für alles Weitere | +| Phase 2 — Nachrichtenspeicher | — | 📋 | Tabelle `AgentMessages` + FTS5, alle Wege gleich behandelt, beide Richtungen festgehalten. **Erst nach dem Output-Scrubbing** (#5) | +| Phase 3 — `ask_agent` | — | ❄️ | Tiefe 1 mit Zyklusprüfung, Rückbau von `AgentComm`/`AgentSpawn`. Wartet auf E4 | +| Phase 4 — Paar-Ansicht | — | ✅/❄️ | Auswahl, Filterung und Darstellung sind fertig; es fehlt genau eine Abfrage (`AgentChatsPageViewModel.LoadMessages`), sobald Phase 2 steht | +| Phase 5 — `AgentCommAnalysis` | — | 📋 | Analyse-Tool, das findet, wo die Zusammenarbeit klemmt. Wer es bekommt, ist offen | +| `@human`-Tasks mitschreiben | — | 💭 | Gäbe die Paar-Ansicht auch für Mensch↔Agent, fast ohne Zusatzaufwand. Vorschlag: ja, aber nach Phase 4 | + +### 3.4 — Daten und Speicher + +| Punkt | Herkunft | Stand | Was | +|---|---|---|---| +| Atomares Schreiben | — | ✅ | `File.Replace`-Muster. Es war bereits eine `TokenUsage.json` beschädigt worden | +| Speicher-Fundament | — | ✅ | WAL, `busy_timeout`, Pooling, Schreib-Warteschlange im Prozess. Vorher gab es `database is locked` — das sah nach einer SQLite-Grenze aus, war aber fehlende Konfiguration | +| Sicherung + Wiederherstellung | — | ✅ | ZIP mit Manifest und Prüfsummen, `VACUUM INTO` für die DB, Secrets wahlweise auf Passphrase umgeschlüsselt (PBKDF2 + AES-GCM) oder ausgelassen — DPAPI allein überlebt den Rechnerwechsel nicht, und genau dann braucht man das Backup. Rotation, Restore mit Vorschau, Zeitplan | +| **Historie-Umzug** | K6, B10 | 📋 **#8** | `ChatHistory.json` zieht in die Instanz-DB: aktive Tabelle + Archiv-Tabelle mit FTS5 und `history_search`-Tool. Löst zugleich B10 — heute wird bei **jedem** Chat-Eintrag die vollständige Historie und der vollständige Kontext als eingerücktes JSON neu geschrieben (O(n²); bei 500 Nachrichten mehrere MB pro Nachricht). Migration nur nach frischem Backup, alte JSON erst nach verifiziertem Import löschen | +| A6 MySQL-Spiegel | — | ❄️ | **SQLite bleibt die einzige Wahrheit.** MySQL ist reiner nachgelagerter Spiegel: empfängt nur vom Replikator, die App liest im Betrieb **nie** daraus. Outbox-Muster an der vorhandenen Schreib-Warteschlange, idempotente Upserts, nie blockierend. Zeilen tragen `instance_id`. **Der Restore-Pfad Spiegel → frische SQLite muss existieren und getestet sein** — gleiche Regel wie beim Backup. Wartet auf den Historie-Umzug und auf E1 (der Server kommt ggf. mit A5) | +| MySQL-Gedächtnis | — | 💭 | Zweite `IMemoryRepository`-Implementierung, wenn mehrere Rechner dazukommen | + +### 3.5 — Betrieb und Auslieferung WatchDog und LicenseLabrador sind durch das [Deploymentcenter](Deploymentcenter-Integration.md) ersetzt: eine Adresse, ein Token, -und dazu Update-Prüfung, Fehler-Stream und Bugtracker. Watchdog läuft wieder pro -Instanz (ein Monitor je Instanz, mit Gesundheitsprüfungen und angekündigtem Ende). +dazu Update-Prüfung, Fehler-Stream und Bugtracker. Watchdog läuft pro Instanz. -Offen: +| Punkt | Herkunft | Stand | Was | +|---|---|---|---| +| Zugangsschutz | DC-2.4 | ✅ | Lizenzschlüssel als Basic-Auth-Zugang zur Release-Ablage. Benutzername wird als `lic_` abgeleitet — **die Ableitung muss auf beiden Seiten zeichengenau übereinstimmen, wer eine Seite ändert, sperrt die gesamte Installationsbasis aus** | +| Update anwenden | DC6 | ✅ | Agent liegt im Paket (Prüfsumme geprüft), Rückfrage in der Oberfläche, geordnetes Herunterfahren vor dem Agentenstart, `maintenance` an den Watchdog | +| Erstinstallation | DC7 | ✅ | `--action install` + `setup.json`, live durchgespielt (Login, Katalog, Token mit Rechteschranke) | +| Release-Strecke | DC3 | ✅/📋 | Erledigt für `win-x64`/`dev` ([`deploy/publish.py`](../deploy/publish.py)). **Offen:** `linux-x64` — die Portierung, auf die das wartete, ist durch — und `prod` | +| **DC1 „Fehler melden"** | DC1 | 📋 | Der Client steht, es fehlt die Schaltfläche in der Oberfläche | +| DC2 Bugtracker-Tool | DC2 | 📋 | Agenten-Tool, das den Claim/Lease-Workflow des Deploymentcenters nutzbar macht | +| DC4 SDK als Submodul | DC4 | 📋 | Heute ein Cross-Repo-Pfad (`..\..\..\Deploymentcenter\…` in `ClawdDotNet.App.csproj`) — auf einem anderen Rechner baut das nicht. Als Git-Submodul unter `external/`. Betrifft auch die CI | +| DC5 Evaluator-Cron | DC5 | 📋 | Betreiberaufgabe: Cron einrichten, Token ausstellen, `parent_source` pflegen. **Ohne den Cron ist die Überwachung wertlos** | +| DC8 Signaturpflicht | DC8 | ❄️ | Schlüssel steht, ab 0.1.2 wird signiert, Prüfung beidseitig getestet. **Blockiert:** `--require-signature` gibt es nur als Kommandozeilenschalter; `UpdateClient.LaunchUpdateAgent` — der empfohlene Weg — reicht ihn nicht durch. Selbst nachbauen hieße `--restart`, `--wait-for-pid` und `--wait-timeout` verlieren. Gemeldet | +| Release-Guard beim Upload | — | 📋 | Veröffentlichen löst `regenerateForProject` nicht aus; ein frisches Produktverzeichnis steht bis zum nächsten Sechs-Stunden-Turnus ohne `.htaccess` da. Ein Aufruf am Ende von `publish` würde das Fenster schließen. **Betreiberseite** | +| Linux-Betrieb | — | 📋 | Der Kern ist portabel: alle Bibliotheks- und Testprojekte auf `net10.0`, kein `DllImport`, keine Registry, kein `System.Drawing`. Windows steckt noch an drei Stellen — DPAPI, Groß-/Kleinschreibung bei Pfadvergleichen, Zeitzonen-IDs. Der teure Teil (8.900 Zeilen WinForms) ist mit der Avalonia-Portierung entfallen | +| systemd-Dienst | — | 💭 | Kopfloser Betrieb. `ClawdDotNet.App` läuft bereits ohne Fenster — der Schichtschnitt ist genau dafür da. `NonInteractiveLicensePrompt` und `ConsoleLicensePrompt` liegen ungenutzt bereit | -| Punkt | Was | Bemerkung | +### 3.6 — Finanz und Analyse + +Dieser Block ist bewusst **nachgelagert**: ClawdDotNet soll zuerst als allgemeiner +Agenten-Client felsenfest sein, die handelsspezifischen Werkzeuge kommen danach. + +| Punkt | Herkunft | Stand | Was | +|---|---|---|---| +| **C1 Marktkalender** | C1 | 📋 **#6** | Zwei Bausteine: `onlyWhenMarketOpen: "NYSE"` im Task-Frontmatter (der Lauf wird schlicht übersprungen, wirkt ohne Zutun des Modells) und ein `MarketCalendar`-Tool für Fragen des Agenten. Handelskalender ändern sich selten — eine gepflegte Datei reicht, keine externe Abhängigkeit. Der Haken im Scanner ist da | +| C2 Indicators | C2 | 📋 | Gleitende Durchschnitte, RSI, ATR, Volatilität, Korrelation, Drawdown, Positionsgröße nach Risiko — **im Code gerechnet**. Sprachmodelle rechnen unzuverlässig, und die Zahlenkolonnen müssen dafür durch den Kontext. Spart Tokens *und* verbessert die Qualität | +| C3 Datenaktualität | C3 | 📋 | `DirectAPI` liefert `dataAsOf` mit, aber nichts wertet es aus — ein Agent kann ungehindert auf drei Tage alten Kursen argumentieren. `maxAgeSeconds` je Tool: ablehnen oder unübersehbar kennzeichnen, nicht stillschweigend durchreichen | +| C4 Termine und Fundamentaldaten | C4 | 📋 | Earnings, Dividenden, Splits, SEC EDGAR (8-K, 10-Q, 13F — frei und gut strukturiert), Wirtschaftstermine. Für „Finanznachrichten" ist der Kalender oft wichtiger als der Kurs | +| C5 Bestandsregister | C5 | 📋 | `stock_add` ist eine Wissenssammlung, kein Bestand. Eigene Tabelle mit Positionen, auch rein zur Beobachtung. Grundlage für C7/C8 | +| C6 Nachrichten-Entdopplung | C6 | 📋 | Dieselbe Meldung läuft über zehn Quellen — man zahlt zehnmal, und der Agent hält es für zehn unabhängige Signale. Das verzerrt die Einschätzung systematisch. `SeenItems` mit Prüfsumme über den normalisierten Titel plus Ähnlichkeitsabgleich | +| C7 Ergebnisregister | C7 | 📋 | Tabelle `AgentOutput` am Lauf: Art, Betreff, Verweis. Macht aus „Kosten pro Lauf" die nützlichere Größe **Kosten pro Ergebnis**. Fällt weitgehend aus den A3-Receipts ab | +| C8 Falsifizierbare Aussagen | C8 | 📋 | Das eigentliche Leistungsmaß. Der Agent legt sich fest (Subjekt, Aussage, Horizont, Konfidenz); ein Auflösungs-Task prüft gegen die tatsächlichen Kurse — kein Mensch muss bewerten. Daraus Trefferquote, **Brier-Score** (misst, ob die Konfidenz ehrlich war — ein Agent, der bei 0,9 nur in 60 % recht hat, ist überheblich, das bleibt bei reiner Trefferquote unsichtbar) und Vergleich gegen eine Nulllinie. **Unter 30 aufgelösten Aussagen keine Rangliste, nur Rohzahlen** — sonst optimiert man Rauschen. Braucht C5 und C7 | +| Leerlaufquote | — | 📋 | Die wirksamste einfache Kennzahl: Läufe ohne greifbares Ergebnis. 40 % Leerlauf heißt meist Zeitplan-Problem — genau das, was C1 löst. Aus vorhandenen Daten | +| `stock_add` herauslösen | T6 | 📋 | Fachfremdes Feature, das das `FileRW`-Schema für alle aufbläht, auch für Agenten, die es nie nutzen | +| Orderausführung | — | 💭 | Siehe E9. Eigene Kategorie, ausdrücklich kein Nebenprodukt | + +### 3.7 — Hygiene + +Kleinbugs, in einem Aufwasch zu erledigen. + +| Punkt | Herkunft | Stand | Was | +|---|---|---|---| +| `index_Count`-Race | B9 | 📋 | `FileRWTool` ruft `index_Count` auf, nachdem das Lock freigegeben ist — Race mit parallelen `stock_add`, plus ein überflüssiges vollständiges Parsen. Der Zähler ist innerhalb des Locks ohnehin bekannt | +| `instanceId`-Inkonsistenz | B13 | 📋 | `RunAsync`/`ChatAsync` bekommen `instanceId` als Parameter, `SendMessageAsync`/`SpawnAgentAsync` nutzen das Feld `_instanceId`, das nur bei `SetAgentConfigProvider` gesetzt wird — sonst leer. In Produktion unkritisch | +| DST-Randfall | — | 📋 | Eine bei der Zeitumstellung nicht existierende Ortszeit („02:30" im Frühjahr) wird übersprungen statt verschoben. Tests R4/R5 der [Teststrategie](Teststrategie.md) | +| Nullable-Warnungen | — | 📋 | 45 Build-Warnungen, Schwerpunkt `Mail` (basisnah) und `WebFetch`/`DirectAPI` (handelsnah) | +| Paket-Anhebungen | — | ✅ | `SQLitePCLRaw.bundle_e_sqlite3` 2.1.13 und `SharpCompress` 0.48.0 stehen als **direkte Verweise, obwohl kein Code sie aufruft** — sie heben verwundbare transitive Fassungen an. Sehen aus wie toter Ballast und sind es nicht | + +### 3.8 — Tests + +Grundlage: [Teststrategie](Teststrategie.md). Stand: 585 grün, 6 übersprungen. + +| Punkt | Stand | Was | |---|---|---| -| DC1 | Oberfläche „Fehler melden" | Client vorhanden, Schaltfläche fehlt | -| DC2 | Agenten-Tool für den Bugtracker | macht den Claim/Lease-Workflow des Deploymentcenters nutzbar | -| DC3 | Release-Strecke | **erledigt für win-x64/dev** ([`deploy/publish.py`](../deploy/publish.py), 0.1.1 veröffentlicht). Offen: `linux-x64` — die Portierung, auf die das wartete, ist durch — und `prod` | -| DC4 | SDK als Git-Submodul unter `external/` statt Cross-Repo-Pfad | betrifft auch die CI | -| DC5 | Betreiber: Evaluator-Cron einrichten, Token ausstellen, `parent_source` pflegen | **ohne den Cron ist die Überwachung wertlos** | -| DC6 | Update anwenden statt nur melden | **erledigt.** Agent liegt im Paket (Prüfsumme geprüft), Rückfrage in der Oberfläche, geordnetes Herunterfahren vor dem Agentenstart, `maintenance` an den Watchdog | -| DC7 | Erstinstallation über `--action install` + `setup.json` | **erledigt.** Setup-Kette live durchgespielt (Login, Katalog, Token mit Rechteschranke), Round-Trip SDK-Writer → SettingsManager trägt. `fileWindows`/`fileLinux` gesetzt | -| DC8 | Signaturpflicht (`--require-signature`) | Schlüssel steht, ab 0.1.2 wird signiert, Prüfung beidseitig getestet. **Blockiert:** `LaunchUpdateAgent` reicht den Schalter nicht durch — aus der Anwendung heraus nicht erzwingbar (gemeldet) | - -Details: [Deploymentcenter 2.2–2.4 Integrationsplan](Deploymentcenter-2.4-Integrationsplan.md). -Der Zugangsschutz aus 2.4 (Lizenzschlüssel als Basic-Auth-Zugang zur Release-Ablage) ist -bereits umgesetzt — er muss im **ersten** veröffentlichten Release enthalten sein. +| **A13** | 📋 | `send_message` A→B→A wird nach `maxDelegationDepth` abgebrochen statt zu verklemmen. Gehört zwingend zu Reihenfolge-Punkt #4 | +| R4/R5 | 📋 | Zeitumstellung Oktober (feuert genau einmal) und März (wird nicht übersprungen) | +| Oberfläche | — | Hat **keine** Testabdeckung. Die leisen Fehler (Fäden, unbegrenzt wachsende Listen, nicht behandeltes Fenster-Schließen) fallen ausschließlich beim Laufen auf — Abschnitt 4 des [Oberflächen-Leitfadens](Oberflaechen-Leitfaden.md) ist deshalb Pflichtlektüre vor jeder Abgabe | --- -## C — Offen aus dem Finanz-/Analyse-Konzept +## 4 — Ideenspeicher -Punkte 1–2 von dort (atomares Schreiben, Backup/Restore inkl. UI) sind umgesetzt. +Nicht beschlossen. Steht hier, damit es nicht verlorengeht — nicht, weil es demnächst +gebaut wird. -| # | Was | Bemerkung | +### Tool-Kandidaten + +| Tool | 💭 Nutzen | Bemerkung | |---|---|---| -| C1 | Marktkalender (`onlyWhenMarketOpen` + `MarketCalendar`-Tool) | Scheduler-Teil gehört ins Taskboard-Frontmatter (A1) | -| C2 | `Indicators`-Tool — deterministische Berechnung | Qualität hoch, Tokens runter | -| C3 | Datenaktualität erzwingen (`maxAgeSeconds`) | | -| C4 | Termine & Fundamentaldaten (Earnings, EDGAR, Wirtschaftskalender) | | -| C5 | Bestandsregister (Positionen) | Grundlage für C7/C8 | -| C6 | Nachrichten-Entdopplung (`SeenItems`) | | -| C7 | Ergebnisregister (Stufe 2, „Kosten pro Ergebnis") | fällt weitgehend aus den A3-Receipts ab | -| C8 | Falsifizierbare Aussagen + Auflösung, Brier-Score (Stufe 3) | braucht C5, C7 und einen Auflösungs-Task (A1) | +| **WebSearch** | Agenten können heute nur bekannte Domains abrufen, aber nichts *finden*. Brave/Tavily/SearXNG | Bauplan liegt vor: [Umsetzungsplan](umsetzungsplaene/UMSETZUNGSPLAN-WebSearch-Tool.md). **Ausdrücklich zuletzt** — größter Sicherheitshebel, deshalb erst nach Papierkorb, Inspector und AgentEditor-Härtung | +| **Nextcloud** | Ort, an dem Agenten Ergebnisse ablegen. Datei lokal erzeugen → hochladen → Link zurück in den Chat | Nextcloud hat keine API, die Inhalte *erzeugt*. Für PDF/XLSX kann Collabora als Konverter dienen. Bauplan: [RocketChat-Nextcloud-Konzept §5](RocketChat-Nextcloud-Konzept.md). Lohnt sich unabhängig vom Ausgang von E1 | +| **Http** | Generisches REST-Tool mit Allowlist je Agent | `DirectAPI` ist fest auf Finanz-Provider verdrahtet — jede neue API erfordert heute Code | +| **Shell** | Sandboxed, mit Kommando-Allowlist | Ersetzt die hartcodierten yt-dlp/ffmpeg-Aufrufe | +| **Git** | Für den „Senior Developer"-Agenten | | +| **Vision** | Charts und Screenshots analysieren | | +| ~~Notify~~ | — | **Gestrichen**, geht in A5 auf | + +### Weitere Ideen + +| Idee | 💭 | +|---|---| +| Rocket.Chat Realtime/DDP statt Polling | Antwortzeit ~1 s statt ~30 s. Optional, Phase 6 | +| Collabora-Konvertierung | Berichte in Büroformaten. Hängt an E-Frage 5 (ist der `convert-to`-Endpunkt freigebbar?) | +| `ChannelRouter` + Eskalation | Erkennt den Ausfall des Chat-Kanals und weicht auf Telegram aus. **Kein Nice-to-have**, sobald der Chat der Hauptweg ist — sonst ist er ein Einzelpunkt, dessen Ausfall niemand meldet. Hängt an E1 | +| K4 Streaming | ❄️ Zurückgestellt bis E1 entschieden ist — Matrix streamt nicht | --- -## D — Toolkandidaten (unbeschlossen) +## 5 — Erledigt -WebSearch, Http (generisch mit Allowlist), Shell (sandboxed), Git, Vision. -Notify ist gestrichen — geht in A5 auf. +Damit die Chronik nicht mit den alten Papieren verschwindet. + +**Sicherheit:** S1 `SqlGuard` statt Teilzeichenketten-Prüfung · S2 `YouTubeUrl` + +`ArgumentList` gegen Options-Injection · S3 `UrlSanitizer` gegen API-Key-Leak ins Modell · +S4 `PermissionGate` zum Durchsetzungspunkt ausgebaut (in A2 aufgegangen) · S5 `UrlGuard`, +Redirects einzeln geprüft · S6 `WorkspacePath` auf Verzeichnisgrenzen · S7 +`SecretProtector` (DPAPI). + +**Bugs:** B1/B14 Compaction — sicherer Schnittpunkt, kein doppelter System-Prompt · +B2 Chat-Läufe je Agent serialisiert · B3/T5 `maxCumulativeTokens` von `maxContextTokens` +getrennt · B4 Prompt/Completion getrennt erfasst, Preise live vom `/models`-Endpunkt · +B5/T2 Tool-Ergebnisse zentral gekappt · B6/B7 gegenstandslos, seit der Scanner die +Delay-Schleifen ersetzt · B11/T8 `max_tokens` aus `LoopGuard.MaxResponseTokens` · +B12 Retry mit Backoff für 429/5xx. + +**Konzepte:** K1 Gedächtnis · K3 Testfundament · K5 Budget-Guard (F-A3) · A1 Taskboard +(mit F-A4, F-A5) · A3 Audit-Log (F-A2) · A2-Kern. + +**Token:** T1/T9 Prompt-Caching mit Breakpoints, `cached_tokens` gemessen · T3 günstiges +Modell für die Zusammenfassung · T7 durch die Assignee-Semantik des Taskboards +beantwortet. + +**Betrieb:** Alt-Scheduler abgelöst — `AgentScheduler`, `ToolJobScheduler` und +`SchedulerDelay` gelöscht, alles ist ein Task · Atomares Schreiben · Backup und Restore +inkl. Oberfläche · Deploymentcenter statt WatchDog und LicenseLabrador · DC3 (win-x64), +DC6, DC7, Zugangsschutz 2.4 · Avalonia-Portierung, WinForms entfernt. + +**Frühjahrsputz 2026-08-23:** automatische Sicherung war nie gestartet · doppelte +Sicherungs-Einstellungen auf der Einstellungsseite überschrieben die der Sicherungsseite · +NU1903 und NU1902 geschlossen. --- -## Vorgeschlagene Reihenfolge +## 6 — Modell-Einstufung -| # | Vorhaben | Begründung | +Die Entwicklung läuft mit Opus 4.6. Die meisten Vorhaben sind damit gut machbar, sofern +die hier notierten Vorgaben mitgegeben werden. Die zwei ursprünglich für Opus 5 / Fable +markierten Stellen sind inzwischen gebaut — die Begründung bleibt stehen, weil sie +erklärt, *warum* es so gebaut ist. + +| Vorhaben | Einstufung | Vorgabe | |---|---|---| -| ✅ | A1 Taskboard | Fundament; löste sechs bestehende Punkte auf einmal | -| ✅ | A3 Audit-Log | klein, sofort nützlich; musste vor A2 da sein, damit Freigaben protokolliert werden | -| **1** | **A2 — Freigabe-Ansicht** | Der Rest von A2 und das einzige Stück, das jetzt wirklich blockiert: Ohne sie liegen gestagte Aufrufe unbeantwortet. Kleiner Umfang, große Wirkung | -| 2 | FileRW-Papierkorb | [eigener Plan](umsetzungsplaene/UMSETZUNGSPLAN-FileRW-Papierkorb-Cleanup.md); kleinster Eingriff, entschärft ein reales Risiko und erlaubt, `FileRW.delete` von `Approve` auf `Auto` zu senken | -| 3 | A5 entscheiden: Matrix oder Rocket.Chat | Blockiert K4 (Streaming) und färbt auf A6 ab. Entscheidung, keine Umsetzung — deshalb früh | -| 4 | C1 Marktkalender | spart sofort Kosten; nutzt A1-Frontmatter | -| 5 | A4 Skills/Toolsets | Token-Hebel, Cache-stabil | -| 6 | C2 Indicators | Qualität + Kosten | -| 7 | C7 + C8 Ergebnisregister, Aussagen | das eigentliche Leistungsmaß; braucht A3 | -| — | DC1 „Fehler melden"-Schaltfläche | zwischendurch; der Client steht, es fehlt der Knopf | -| — | Hygiene-Paket (B) | zwischendurch, unabhängig | -| — | Historie-Umzug in die Instanz-DB | löst B10 + K6; Voraussetzung für A6 | -| — | A6 MySQL-Spiegel | nach dem Historie-Umzug; natürliches Zuhause auf dem A5-Server | -| — | A5 umsetzen | erst nach der Entscheidung aus Zeile 3; der gewählte Weg bekommt dann sein Konzept-Doc | +| ✅ A1 Scanner-Kern | war ⚠️ Opus 5 / Fable | At-most-once, Claim-CAS, Zusammenspiel mit den serialisierten Chat-Läufen — genau die Fehlerklasse, die hier schon einmal schiefging. Gebaut mit Property-Tests für die Invarianten | +| ✅ A2 Fortsetzung nach Freigabe | 4.6 mit Vorgabe | **Kein pausierter, im Speicher gehaltener Lauf.** Der Lauf endet beim Staging regulär, die Freigabe erzeugt einen Folge-Task mit dem eingefrorenen Aufruf. Echtes Suspend/Resume wäre Fable-Terrain — und ist damit unnötig | +| Freigabe-Ansicht | 4.6 | Reine Oberflächenarbeit gegen eine fertige API | +| Delegationstiefe (B8) | ⚠️ **mit Vorsicht** | Fasst das Agent-Gate an, an dem schon ein Deadlock lauerte. Erst Invarianten festlegen, dann bauen, Test A13 zwingend | +| Output-Scrubbing | 4.6 | Ein zentraler Filter an `ExecuteToolCallAsync`, Werte aus dem Secret-Register | +| A4 Skills | 4.6 | `FileSystemWatcher` mit Debounce (~500 ms); agentengeschriebene Skills erst nach Freigabe aktiv | +| Memory-Flush vor Compaction | 4.6 mit Anleitung | Der `ContextCompactor` hatte B1/B14 — die bestehenden Paarungs-Tests müssen unverändert grün bleiben | +| Historie-Umzug + FTS5 | 4.6 | Migration nur nach frischem Backup; alte JSON erst nach verifiziertem Import löschen | +| A6 MySQL-Spiegel | 4.6 mit Anleitung | Outbox mit Wasserzeichen, idempotente Upserts, nie blockieren. **Der getestete Restore-Pfad ist Teil der Definition of Done** | +| C1, C2 | 4.6 | Reine Fachlogik, deterministisch testbar | -Leitlinie der Reihung: erst Nachvollziehbarkeit und Kontrolle (Audit, Staging), -dann Fähigkeiten — ein Agent, der unbeaufsichtigt läuft, braucht zuerst Bremsen, -dann PS. +Generell: Neue Subsysteme kommen mit Tests nach der [Teststrategie](Teststrategie.md). +Bei den markierten Punkten sind die Invarianten-Tests kein Nice-to-have, sondern die +Absicherung dafür, dass ein schwächeres Modell sie umsetzen darf. --- -## Umsetzung mit Opus 4.6 — Einstufung +## 7 — Woher das hier kommt -Die Entwicklung erfolgt mit Opus 4.6. Die meisten Vorhaben sind damit gut -machbar, sofern die hier notierten Vorgaben mitgegeben werden. +### Weiter gültig — Baupläne -> Die beiden hier markierten Stellen sind inzwischen gebaut: Der **Scanner-Kern** -> (A1) steht samt Claiming und Reconciliation, die **Fortsetzung nach Freigabe** -> (A2) folgt der Vorgabe unten — der Lauf endet beim Staging regulär, kein Suspend. -> Die Tabelle bleibt als Begründung stehen, warum es so gebaut wurde. Zwei Stellen -berühren Nebenläufigkeits-Invarianten bzw. Engine-Querschnitte — sie sind für -Opus 5 / Fable markiert oder durch eine Architektur-Vorgabe entschärft. +Aus der Roadmap verlinkt. Wer einen Punkt anfasst, liest das zugehörige Dokument. -| Vorhaben | Einstufung | Vorgabe / Begründung | -|---|---|---| -| A1: Dateiformat, Frontmatter-Parsing, `task_*`-Tool, Migration | 4.6 | klar spezifizierbar, gut testbar | -| A1: **Scanner-Kern** (atomares Claiming, Auto-Dispatch, Reconciliation) | ⚠️ **Opus 5 / Fable** | At-most-once-Semantik, Claim-CAS und das Zusammenspiel mit den seit B2 serialisierten Chat-Läufen sind genau die Fehlerklasse, die hier schon einmal schiefging. Falls doch 4.6: erst Konzept-Doc, Umsetzung strikt dagegen, Property-Tests für die Invarianten („nie zwei Claims auf einen Task", „kein Dispatch bei offenem Blocker", „doppelter Tick = ein Lauf") | -| A2: Gate, Policy, Staging-Queue, Review-UI, Approval-Records | 4.6 | mit der folgenden Architektur-Vorgabe | -| A2: **Fortsetzung nach Freigabe** | 4.6 nur mit Vorgabe | **Kein pausierter, im Speicher gehaltener Lauf.** Vorgabe: Der Lauf endet beim Staging regulär — das Tool liefert „zur Freigabe vorgelegt" als Ergebnis, der Agent schließt ab. Die Freigabe erzeugt einen Folge-Task (A1), der den Agenten mit dem **eingefrorenen** Aufruf weckt. Echtes Suspend/Resume eines laufenden `ChatAsync` wäre Fable-Terrain — und ist mit dieser Vereinfachung unnötig | -| A3: Audit-Log + Receipts | 4.6 | append-only, klares Schema, keine Nebenläufigkeitsfallen | -| A4: Skills | 4.6 | `FileSystemWatcher` mit Debounce (~500 ms); agentengeschriebene Skills erst nach Freigabe aktiv (siehe A4) | -| Memory-Flush vor Compaction | 4.6 mit Anleitung | Harte Grenzen: max. 3–5 Schritte, einziges Tool `memory_store`, Timeout, günstiges Modell (wie T3), höchstens einmal je Compaction-Zyklus. Vorsicht: Der ContextCompactor hatte B1/B14 — die bestehenden Paarungs-Tests müssen unverändert grün bleiben | -| Memory-Auto-Injection | 4.6 | in die Nutzernachricht, nie in den System-Prompt (sonst verfällt der Prompt-Cache T1); Deckel ~200 Tokens | -| Output-Scrubbing | 4.6 | ein zentraler Filter an der Stelle, wo Tool-Ergebnisse in den Kontext gelangen (`ExecuteToolCallAsync`); Werte aus dem Secret-Register | -| Historie-Umzug + FTS5 + `history_search` | 4.6 | Migration nur nach frischem Backup; alte JSON-Dateien erst nach verifiziertem Import löschen | -| A6: MySQL-Spiegel | 4.6 mit Anleitung | Outbox mit Wasserzeichen, idempotente Upserts, nie blockieren; der getestete Restore-Pfad ist Teil der Definition of Done | -| C1 Marktkalender, C2 Indicators | 4.6 | reine Fachlogik, deterministisch testbar | +| Dokument | Wofür | +|---|---| +| [Taskboard-Konzept](Taskboard-Konzept.md) | Dateiformat, Wahrheitsaufteilung Datei/DB, Scanner-Verhalten, Invarianten | +| [Audit-Konzept](Audit-Konzept.md) | Schema, Provenance-Regeln, Receipts | +| [Staging-Konzept](Staging-Konzept.md) | Policy-Auflösung, Plan-Freeze, Fortsetzung nach Freigabe — **Bauplan für Punkt #1** | +| [Memory-Konzept](Memory-Konzept.md) | Modell, Schlüssel-Semantik, Abrufreihenfolge | +| [Agentenkommunikation-Konzept](Agentenkommunikation-Konzept.md) | Fünf Phasen, Korrelation, Nachrichtenspeicher | +| [RocketChat-Nextcloud-Konzept](RocketChat-Nextcloud-Konzept.md) | Rocket.Chat gebaut; Nextcloud, Rückweg und `ChannelRouter` offen. Enthält die Messung gegen die echte Instanz | +| [Deploymentcenter-Integration](Deploymentcenter-Integration.md) | Wie Heartbeat, Fehler-Stream, Bugtracker und Updates verdrahtet sind | +| [umsetzungsplaene/](umsetzungsplaene/) | Vier Detailpläne: FileRW-Papierkorb, AgentInspector, AgentEditor-Härtung, WebSearch | -Generell: Neue Subsysteme (Scanner, Staging, Audit, Replikator) kommen mit Tests -nach der [Teststrategie](Teststrategie.md) — die Invarianten-Tests sind bei den -markierten Punkten kein Nice-to-have, sondern die Absicherung dafür, dass ein -schwächeres Modell sie umsetzen darf. +### Weiter gültig — Handbücher + +| Dokument | Wofür | +|---|---| +| [Oberflaechen-Leitfaden](Oberflaechen-Leitfaden.md) | Arbeiten an `ClawdDotNet.Desktop`: Schichtschnitt, Fäden, Avalonia-12-Fallen, Prüfliste | +| [ToolDevelopmentGuide](ToolDevelopmentGuide.md) | Ein neues Agenten-Tool bauen | +| [InstanceSetupGuide](InstanceSetupGuide.md) | Eine Instanz einrichten | +| [Teststrategie](Teststrategie.md) | Was wie getestet wird, Fallkatalog | + +### Archiviert + +Vollständig in dieses Dokument überführt. Sie bleiben als Begründung und Herkunft +lesbar, werden aber **nicht mehr fortgeschrieben** — siehe [docs/archiv/](archiv/). + +| Dokument | Was daraus wurde | +|---|---| +| `Bestandsaufnahme-2026-07.md` | S1–S7, B1–B14, K1–K6, T1–T9, F-A1…F-A7 — erledigte in Abschnitt 5, offene in 3.1/3.2/3.7 | +| `Konzepte-Backup-Finanz-Analyse.md` | Backup ✅; Finanzteil als C1–C6; Leistungsanalyse als C7/C8 und Leerlaufquote | +| `Linux-Portierung-Analyse.md` | Die drei Kernstellen und das `linux-x64`-Release in 3.5. Der teure Teil (WinForms) ist entfallen | +| `Lizenz-HardwareId-v2-Implementierungsvorschlag.md` | **Gegenstandslos** — LicenseLabrador ist durch das Deploymentcenter ersetzt | +| `Deploymentcenter-Anbindung-Review.md` | Befunde behoben, in 3.5 aufgegangen | +| `Deploymentcenter-2.4-Integrationsplan.md` | DC-Punkte in 3.5, inklusive der blockierten Signaturpflicht und der Betreiber-Restpunkte | +| `ClawdDotNet_StartPrompt.md` und die drei Prompt-Anhänge | Entwicklungs-Prompts der Anfangszeit. Eine Regel gilt weiter: die Pflichtfelder `fetchedAt`/`dataAsOf`/`source` der Internet-Tools | diff --git a/docs/Taskboard-Konzept.md b/docs/Taskboard-Konzept.md index a8c8776..dbd6bd7 100644 --- a/docs/Taskboard-Konzept.md +++ b/docs/Taskboard-Konzept.md @@ -1,5 +1,10 @@ # Taskboard — Aufgaben statt Delay-Schleifen +> **Bauplan zu einem gebauten System.** Dateiformat, Wahrheitsaufteilung Datei/DB, +> Scanner-Verhalten und Invarianten. Umgesetzt; der Stand steht in der +> [Roadmap](Roadmap.md) 3.2. Die Abschnitte im Präsens beschreiben teils den Zustand +> *vor* der Umsetzung — sie begründen den Entwurf. + Setzt A1 aus der [Roadmap](Roadmap.md) um. Das Taskboard ist das Fundament, auf dem Audit (A3), Staging (A2), Marktkalender (C1) und das Ergebnisregister (C7/C8) aufsetzen. Es löst zugleich sechs Altpunkte auf einmal (F-A5 Queue, F-A4 Run-Historie, @@ -15,8 +20,8 @@ Invarianten, Migration. Heute gibt es zwei getrennte, je für sich unzureichende Wege, einen Agenten Arbeit tun zu lassen: -- **Der Cron-Scheduler** ([`AgentScheduler`](../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs), - [`ToolJobScheduler`](../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs)) hängt starr +- **Der Cron-Scheduler** (`AgentScheduler`, `ToolJobScheduler` — beide inzwischen + gelöscht, siehe unten) hing starr am Agenten: eine Cron-Zeile je Agent, ausgeführt über ein `Task.Delay` bis zum nächsten Termin. Ein jährlicher Termin bedeutet ein `Task.Delay` über Monate (B6). Cron läuft in Lokalzeit ohne explizite Zone (B7). Ob mit oder ohne Kontext gelaufen diff --git a/docs/Teststrategie.md b/docs/Teststrategie.md index 37d895d..ec03950 100644 --- a/docs/Teststrategie.md +++ b/docs/Teststrategie.md @@ -1,6 +1,6 @@ # ClawdDotNet — Teststrategie -Ergänzung zur [Bestandsaufnahme](Bestandsaufnahme-2026-07.md). +Ergänzung zur [Bestandsaufnahme](archiv/Bestandsaufnahme-2026-07.md). Ziel: Fehlerklassen wie B1 (Compaction zerstört tool_call-Paarung) und B2 (Race Condition) strukturell unmöglich machen, statt sie im Betrieb zu entdecken. @@ -61,9 +61,10 @@ internal sealed class FakeChatClient : IChatCompletionClient ### R2 — `TimeProvider` statt `DateTime.Now` .NET 10 bringt `TimeProvider` mit; `FakeTimeProvider` steckt in `Microsoft.Extensions.TimeProvider.Testing`. Betrifft -[`CronExpression.cs:53`](../src/ClawdDotNet.Core/Scheduling/CronExpression.cs#L53), -[`AgentScheduler.cs:75`](../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs#L75), -[`ToolJobScheduler.cs:111`](../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs#L111). +[`CronExpression.cs:53`](../src/ClawdDotNet.Core/Scheduling/CronExpression.cs#L53) und den +[`TaskScanner`](../src/ClawdDotNet.Core/Tasks/TaskScanner.cs). (Die ursprünglich hier +genannten `AgentScheduler` und `ToolJobScheduler` sind gelöscht — der Scanner hat sie +abgelöst.) Damit werden Zeitumstellungs- und Langzeit-Tests deterministisch und laufen in Millisekunden statt in Echtzeit. diff --git a/docs/Bestandsaufnahme-2026-07.md b/docs/archiv/Bestandsaufnahme-2026-07.md similarity index 88% rename from docs/Bestandsaufnahme-2026-07.md rename to docs/archiv/Bestandsaufnahme-2026-07.md index 3f379b8..c155fb8 100644 --- a/docs/Bestandsaufnahme-2026-07.md +++ b/docs/archiv/Bestandsaufnahme-2026-07.md @@ -4,7 +4,7 @@ Vollständiges Review von Core-Engine, Security-Layer, Tools, Scheduling und UI. Stand: Commit `92e50d3`. > **Dies ist ein datierter Befund, keine Todoliste.** Er wird nicht fortgeschrieben. -> Was davon offen ist, steht in der [Roadmap](Roadmap.md) — dort auch, was seither +> Was davon offen ist, steht in der [Roadmap](../Roadmap.md) — dort auch, was seither > erledigt wurde. Die Abschnitte zur Oberfläche beziehen sich auf die Windows-Forms- > Fassung, die es seit dem 2026-08-23 nicht mehr gibt. @@ -19,7 +19,7 @@ deshalb umgehbar sind, (2) fehlende Nebenläufigkeits-Absicherung im geteilten C ## 1. Kritische Sicherheitslücken (P0) ### S1 — DatabaseTool: Tabellen-Whitelist ist vollständig umgehbar -[`DatabaseTool.cs:218`](../src/ClawdDotNet.Tools.Database/DatabaseTool.cs#L218) +[`DatabaseTool.cs:218`](../../src/ClawdDotNet.Tools.Database/DatabaseTool.cs#L218) ```csharp return allowed.Any(t => t != null && inputLower.Contains(t)); @@ -36,7 +36,7 @@ DELETE FROM users -- prices Die `users`-Tabelle wird gelöscht. Gleiches gilt für jede beliebige andere Tabelle. Zusätzlich: -- `IsWriteAttempt`/`IsAdminAttempt` ([Z.189/195](../src/ClawdDotNet.Tools.Database/DatabaseTool.cs#L189)) +- `IsWriteAttempt`/`IsAdminAttempt` ([Z.189/195](../../src/ClawdDotNet.Tools.Database/DatabaseTool.cs#L189)) sind ebenfalls Substring-Prüfungen → False Positives (`SELECT * FROM prices WHERE note='update'` wird als Schreibzugriff blockiert). - Mehrere Statements pro Aufruf sind nicht unterbunden (`;`-Verkettung). @@ -48,7 +48,7 @@ vordefinierte, parametrisierte Named Queries ersetzen. Freies SQL vom LLM ist gr schwer abzusichern. ### S2 — SocialMediaManager: Kommando-Injection über yt-dlp -[`SocialMediaManagerTool.cs:442`](../src/ClawdDotNet.Tools.SocialMediaManager/SocialMediaManagerTool.cs#L442), auch Z.484 und Z.490 +[`SocialMediaManagerTool.cs:442`](../../src/ClawdDotNet.Tools.SocialMediaManager/SocialMediaManagerTool.cs#L442), auch Z.484 und Z.490 ```csharp var psi = new ProcessStartInfo(ytDlpPath, $"--print \"%(id)s\" --playlist-end 1 {channelUrl}") @@ -68,7 +68,7 @@ eine Regex validieren (`^https://(www\.)?(youtube\.com|youtu\.be)/…`) und `--` vor dem URL-Argument setzen. ### S3 — DirectAPI: API-Keys landen im Modell-Kontext -[`DirectAPITool.cs:83`](../src/ClawdDotNet.Tools.DirectAPI/DirectAPITool.cs#L83), auch Z.99, 154, 177, 263 +[`DirectAPITool.cs:83`](../../src/ClawdDotNet.Tools.DirectAPI/DirectAPITool.cs#L83), auch Z.99, 154, 177, 263 ```csharp var url = $"https://api.twelvedata.com/quote?symbol={symbol}&apikey={apiKey}"; @@ -86,7 +86,7 @@ landet der Key: grundsätzlich eine bereinigte URL zurückgeben (Query-String entfernen oder `apikey` maskieren). ### S4 — PermissionGate ist faktisch wirkungslos -[`PermissionGate.cs:7`](../src/ClawdDotNet.Core/Security/PermissionGate.cs#L7) +[`PermissionGate.cs:7`](../../src/ClawdDotNet.Core/Security/PermissionGate.cs#L7) ```csharp public bool IsAllowed(string agentId, string toolName, AgentConfig agentConfig) @@ -103,13 +103,13 @@ Rate-Limits pro Agent/Tool/Zeitfenster, Audit-Log jedes Aufrufs mit Argumenten, Approval-Hook für irreversible Aktionen (siehe F-A1). ### S5 — WebFetch: kein SSRF-Schutz bei Redirects -[`WebFetchTool.cs:58`](../src/ClawdDotNet.Tools.WebFetch/WebFetchTool.cs#L58) +[`WebFetchTool.cs:58`](../../src/ClawdDotNet.Tools.WebFetch/WebFetchTool.cs#L58) Die Domain-Whitelist wird nur auf die *ursprüngliche* URL angewendet. `HttpClient` folgt Redirects standardmäßig — eine erlaubte Domain kann auf `http://169.254.169.254/`, `http://localhost:8418/` (dein Gitea!) oder beliebige interne Hosts weiterleiten. -Nebenbei: `uri.Host.Replace("www.", "")` ([Z.59](../src/ClawdDotNet.Tools.WebFetch/WebFetchTool.cs#L59)) +Nebenbei: `uri.Host.Replace("www.", "")` ([Z.59](../../src/ClawdDotNet.Tools.WebFetch/WebFetchTool.cs#L59)) ersetzt das Fragment überall im Hostnamen, nicht nur am Anfang. **Fix:** `HttpClientHandler { AllowAutoRedirect = false }` und Redirects manuell auflösen, @@ -117,7 +117,7 @@ dabei jede Zwischen-URL erneut gegen die Whitelist prüfen. Zusätzlich private (RFC1918, Loopback, Link-Local) hart blockieren. ### S6 — FileRW: Path-Traversal-Prüfung per Präfix -[`FileRWTool.cs:211`](../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L211) +[`FileRWTool.cs:211`](../../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L211) ```csharp if (!fullPath.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase)) @@ -133,7 +133,7 @@ ausnutzbar, aber eine Zeitbombe. ### S7 — Secrets im Klartext `openRouterApiKey`, DB-`connectionString` (mit Passwort), Mail-`password`, Telegram-`password2FA` liegen unverschlüsselt in `AgentSettings.json` / `InstanceConfig.json` -([`InstanceConfig.cs:46`](../src/ClawdDotNet.Core/Config/InstanceConfig.cs#L46)). +([`InstanceConfig.cs:46`](../../src/ClawdDotNet.Core/Config/InstanceConfig.cs#L46)). **Fix:** DPAPI (`ProtectedData.Protect` mit `CurrentUser`-Scope) für alle Secret-Felder, oder Windows Credential Manager. Zumindest sollten die Felder beim Speichern verschlüsselt @@ -144,7 +144,7 @@ und erst zur Laufzeit entschlüsselt werden. ## 2. Bugs (P1) ### B1 — ContextCompactor zerstört die tool_call-Paarung ⚠️ -[`ContextCompactor.cs:140`](../src/ClawdDotNet.Core/Engine/ContextCompactor.cs#L140) +[`ContextCompactor.cs:140`](../../src/ClawdDotNet.Core/Engine/ContextCompactor.cs#L140) ```csharp var tail = messages.Skip(Math.Max(0, messages.Count - ProtectedTailMessages)).ToList(); @@ -166,7 +166,7 @@ einer Nachricht mit Rolle `user` oder `assistant` ohne `tool_calls`. Analog muss `assistant` mit `tool_calls` am Ende immer seine vollständigen `tool`-Antworten behalten. ### B2 — Race Condition auf dem geteilten Chat-Kontext ⚠️ -[`AgentEngine.cs:250`](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L250) und Z.268/316/322 +[`AgentEngine.cs:250`](../../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L250) und Z.268/316/322 `_chatContexts[agentId]` ist eine geteilte `List`. Nur der *Lookup* läuft unter `_lock` — alle `messages.Add(...)` im Loop passieren ungeschützt. @@ -190,8 +190,8 @@ Beim Umsetzen kamen zwei Folgeprobleme dazu, die denselben Ursprung haben: (der laufende Chat hält es bereits) — wird jetzt abgelehnt. ### B3 — `maxTokens` vermischt Abrechnungs-Budget und Kontextgröße ⚠️ -[`LoopGuard.cs:22`](../src/ClawdDotNet.Core/Engine/LoopGuard.cs#L22), Defaults in -[`AgentConfig.cs:105`](../src/ClawdDotNet.Core/Config/AgentConfig.cs#L105) +[`LoopGuard.cs:22`](../../src/ClawdDotNet.Core/Engine/LoopGuard.cs#L22), Defaults in +[`AgentConfig.cs:105`](../../src/ClawdDotNet.Core/Config/AgentConfig.cs#L105) `RecordTokens` summiert `response.Usage.TotalTokens` über alle Schritte. Da jeder Schritt den **kompletten** Kontext erneut sendet, wächst diese Summe quadratisch: @@ -214,7 +214,7 @@ häufigste Frustquelle im laufenden Betrieb. und beide getrennt im UI ausweisen. ### B4 — Kostenanzeige ist doppelt falsch -[`frm_main.cs:292`](../frm_main.cs#L292) +[`frm_main.cs:292`](../../frm_main.cs#L292) ```csharp _statusService?.RecordUsage(model, result.TokensUsed / 2, result.TokensUsed / 2); @@ -224,7 +224,7 @@ _statusService?.RecordUsage(model, result.TokensUsed / 2, result.TokensUsed / 2) Da Output ~5x teurer ist, überschätzt die Anzeige die Kosten um Faktor ~2,5. 2. **Modell fehlt in der Preistabelle**: `AgentConfig.Model` hat den Default `anthropic/claude-sonnet-4-5` — dieser Eintrag existiert in `ModelPricing` - ([`OpenRouterStatusService.cs:15`](../Services/OpenRouterStatusService.cs#L15)) nicht. + ([`OpenRouterStatusService.cs:15`](../../Services/OpenRouterStatusService.cs#L15)) nicht. `CalculateCost` gibt dann stillschweigend `0` zurück. Die Tabelle ist zudem veraltet (`claude-sonnet-4`, `claude-opus-4`, `claude-haiku-4.5`). @@ -235,22 +235,22 @@ statt hartzucodieren. Bei unbekanntem Modell sichtbar warnen statt 0 anzuzeigen. ### B5 — Tool-Ergebnisse landen ungekappt im Kontext Ein einziger `WebFetch` mit dem Default `maxResponseKb: 512` -([`WebFetchTool.cs:90`](../src/ClawdDotNet.Tools.WebFetch/WebFetchTool.cs#L90)) erzeugt bis zu +([`WebFetchTool.cs:90`](../../src/ClawdDotNet.Tools.WebFetch/WebFetchTool.cs#L90)) erzeugt bis zu 512 KB Text ≈ **130.000 Tokens** in einer einzigen Tool-Antwort. `FileRW.read` -([`FileRWTool.cs:245`](../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L245)) hat gar kein Limit, +([`FileRWTool.cs:245`](../../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L245)) hat gar kein Limit, `Database.query` und `Mail.read_inbox` ebenfalls nicht. Gekürzt wird erst nachträglich in der Compaction — und dort nur außerhalb der letzten 6 Nachrichten. Der teure Request ist zu dem Zeitpunkt längst bezahlt. **Fix:** Kappung beim Einfügen in `ExecuteToolCallAsync` -([`AgentEngine.cs:668`](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L668)) — zentral, für alle +([`AgentEngine.cs:668`](../../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L668)) — zentral, für alle Tools, mit konfigurierbarem `maxToolResultTokens` und einem Hinweis an das Modell, dass gekürzt wurde (inkl. Angebot, gezielt nachzulesen). ### B6 — `Task.Delay` wirft bei langen Cron-Intervallen -[`AgentScheduler.cs:89`](../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs#L89) und -[`ToolJobScheduler.cs:126`](../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs#L126) +[`AgentScheduler.cs:89`](../../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs#L89) und +[`ToolJobScheduler.cs:126`](../../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs#L126) `Task.Delay` wirft `ArgumentOutOfRangeException` bei Werten über ~24,8 Tagen. Ein jährlicher Cron (`0 3 1 1 *`) erzeugt eine Wartezeit von bis zu 365 Tagen. Der `catch` fängt nur @@ -262,14 +262,14 @@ Job läuft ab dann einfach nie wieder. Scheduler-Tasks mit einem `ContinueWith`-Fehler-Logger versehen. ### B7 — Cron rechnet in Lokalzeit -[`CronExpression.cs:51`](../src/ClawdDotNet.Core/Scheduling/CronExpression.cs#L51) mit +[`CronExpression.cs:51`](../../src/ClawdDotNet.Core/Scheduling/CronExpression.cs#L51) mit `DateTime.Now`. Bei Zeitumstellung: im Oktober läuft ein `0 2 * * *`-Job doppelt, im März gar nicht. **Fix:** Intern in UTC rechnen und nur für die Anzeige konvertieren, oder `TimeZoneInfo` explizit berücksichtigen. ### B8 — Keine Rekursionsbremse bei AgentComm / AgentSpawn -[`AgentEngine.cs:510`](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L510) +[`AgentEngine.cs:510`](../../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L510) Agent A ruft `send_message(B)` → `ChatAsync(B)` → B ruft `send_message(A)` → … Es gibt keine Tiefenbegrenzung und keinen Zyklus-Check. Bei `SpawnAgentAsync` schützt immerhin der @@ -280,14 +280,14 @@ in der Zwischenzeit brennt jeder Hop einen vollständigen LLM-Run. den Aufrufpfad zur Zyklenerkennung mitgeben. ### B9 — `index_Count` liest die Datei außerhalb des Locks erneut -[`FileRWTool.cs:569`](../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L569) ruft -[`index_Count`](../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L572) auf, nachdem das Lock +[`FileRWTool.cs:569`](../../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L569) ruft +[`index_Count`](../../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L572) auf, nachdem das Lock freigegeben wurde — Race mit parallelen `stock_add`-Aufrufen, plus ein überflüssiges vollständiges Parsen der Index-Datei. Der Zähler ist innerhalb des Locks ohnehin bekannt (`index.Count`). ### B10 — `PersistChatState` schreibt bei jedem Eintrag alles neu -[`AgentEngine.cs:593`](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L593) +[`AgentEngine.cs:593`](../../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L593) Vollständige History **und** vollständiger Kontext werden als `WriteIndented`-JSON bei jedem einzelnen Chat-Eintrag rausgeschrieben → O(n²) Schreiblast über eine Sitzung. Bei einem Agenten @@ -297,19 +297,19 @@ mit 500 Nachrichten sind das mehrere MB pro Nachricht. `WriteIndented = false`. ### B11 — Kein `max_tokens` im Request -[`AgentEngine.cs:105`](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L105) und Z.279 setzen +[`AgentEngine.cs:105`](../../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L105) und Z.279 setzen `ChatRequest.MaxTokens` nie. Ein Modell kann in einem Schritt sein volles Output-Limit ausschöpfen. ### B12 — Kein Retry/Backoff -[`OpenRouterClient.cs:42`](../src/ClawdDotNet.Core/Api/OpenRouterClient.cs#L42) wirft bei jedem +[`OpenRouterClient.cs:42`](../../src/ClawdDotNet.Core/Api/OpenRouterClient.cs#L42) wirft bei jedem Nicht-2xx sofort. Ein einzelnes HTTP 429 killt einen kompletten geplanten Run. Bei OpenRouter sind 429/502/503 im Normalbetrieb zu erwarten. **Fix:** Polly o.ä. mit exponentiellem Backoff + Jitter für 429/5xx, `Retry-After` respektieren. ### B14 — Compaction dupliziert den System-Prompt bei kurzen Konversationen ⚠️ -[`ContextCompactor.cs:140`](../src/ClawdDotNet.Core/Engine/ContextCompactor.cs#L140) +[`ContextCompactor.cs:140`](../../src/ClawdDotNet.Core/Engine/ContextCompactor.cs#L140) *Gefunden durch den Property-Test, nicht beim Lesen des Codes.* @@ -346,7 +346,7 @@ verwenden dagegen das Feld `_instanceId`, das nur gesetzt wird, wenn ### K1 — Geplante Agenten haben kein Gedächtnis `RunAsync` baut bei jedem Cron-Tick eine frische Nachrichtenliste -([`AgentEngine.cs:89`](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L89)). Ein Agent, der alle +([`AgentEngine.cs:89`](../../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L89)). Ein Agent, der alle 30 Minuten läuft, weiß nichts von seinem letzten Lauf: er ruft dieselben Quellen erneut ab, zieht dieselben Schlüsse und kann keine Entwicklung über Zeit verfolgen. @@ -375,7 +375,7 @@ Erste Kandidaten: `CronExpression`, `ContextCompactor` (Paarungs-Invarianten!), `FileRWTool`-Pfadprüfungen. ### K4 — Kein Streaming -`request.Stream = false` fest verdrahtet ([`OpenRouterClient.cs:34`](../src/ClawdDotNet.Core/Api/OpenRouterClient.cs#L34)). +`request.Stream = false` fest verdrahtet ([`OpenRouterClient.cs:34`](../../src/ClawdDotNet.Core/Api/OpenRouterClient.cs#L34)). Bei langen Antworten wirkt die UI eingefroren; es gibt nur den Typing-Indicator. ### K5 — Kein Kostenlimit @@ -410,7 +410,7 @@ Input-Tokens kosten nur ~10 % des Normalpreises (Schreiben in den Cache kostet e Umsetzung: 1. `ChatMessage.Content` muss das Array-Format unterstützen (`[{ "type": "text", "text": "...", "cache_control": { "type": "ephemeral" } }]`). - Aktuell ist es ein reiner `string` ([`ChatMessage.cs:12`](../src/ClawdDotNet.Core/Api/Models/ChatMessage.cs#L12)). + Aktuell ist es ein reiner `string` ([`ChatMessage.cs:12`](../../src/ClawdDotNet.Core/Api/Models/ChatMessage.cs#L12)). 2. Cache-Breakpoint ans Ende des System-Prompts und ans Ende der Tool-Definitionen setzen. 3. Optional einen dritten Breakpoint nach der letzten stabilen Konversationsgrenze (rollierend). 4. `Usage` um `prompt_tokens_details.cached_tokens` erweitern, damit der Effekt messbar wird. @@ -426,7 +426,7 @@ Sinnvolle Defaults: 4.000 Tokens pro Tool-Ergebnis, mit Kürzungshinweis und der gezielt weiterzulesen (Offset-Parameter bei `FileRW.read`, `LIMIT`/`OFFSET` bei `Database.query`). ### T3 — Günstiges Modell für die Compaction (Einsparung: ~95 % der Compaction-Kosten) ★★ -[`ContextCompactor.cs:114`](../src/ClawdDotNet.Core/Engine/ContextCompactor.cs#L114) nutzt +[`ContextCompactor.cs:114`](../../src/ClawdDotNet.Core/Engine/ContextCompactor.cs#L114) nutzt `model` — also das teure Modell des Agenten — um bis zu 30k Zeichen zusammenzufassen. Bei Opus kostet eine einzige Compaction so mehr als der halbe Run. @@ -435,7 +435,7 @@ Bei Opus kostet eine einzige Compaction so mehr als der halbe Run. ### T4 — Proaktiv statt reaktiv kompaktieren ★★ `CompactIfNeededAsync` läuft **nach** dem API-Call -([`AgentEngine.cs:123`](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L123)) und nutzt die +([`AgentEngine.cs:123`](../../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L123)) und nutzt die `promptTokens` der gerade bezahlten Anfrage. Der überfüllte Prompt wurde also bereits berechnet. **Fix:** Vor dem Senden prüfen (mit `EstimateTokens`, das es schon gibt) und erst dann den @@ -448,7 +448,7 @@ was die Tokenkosten verdoppelt statt sie zu begrenzen. ### T6 — Tool-Definitionen verschlanken ★ Die Beschreibungen sind großzügig: `FileRW` allein hat ~500 Zeichen Description plus ein Schema mit 11 Properties ≈ 900 Tokens -([`FileRWTool.cs:26`](../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L26)). Bei 8 zugewiesenen +([`FileRWTool.cs:26`](../../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L26)). Bei 8 zugewiesenen Tools sind das schnell 4–6k Tokens — bei **jedem** Schritt (ohne Caching). Maßnahmen: @@ -458,7 +458,7 @@ Maßnahmen: - Für Agenten mit vielen Tools: zweistufiges Laden (`list_toolsets` → `load_toolset`). ### T7 — `RunAsync` statt `ChatAsync` für Job-Wakeups prüfen ★ -[`ToolJobScheduler.cs:186`](../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs#L186) +[`ToolJobScheduler.cs:186`](../../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs#L186) entscheidet über `UseChatContext`. Mit `true` wird die komplette (potenziell riesige) Chat-Historie in einen "Prüfe neue Mails"-Tick gezogen. Für zustandslose Ticks ist `RunAsync` um Größenordnungen günstiger — der Default sollte bewusst gesetzt und im UI erklärt sein. @@ -509,7 +509,7 @@ und im UI markiert. Setzt B4 (korrekte Kostenerfassung) voraus. **F-A4 — Run-Historie** `AgentRunResult` wird aktuell nur im Speicher als "letztes Ergebnis" gehalten -([`AgentScheduler.cs:14`](../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs#L14)). +([`AgentScheduler.cs:14`](../../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs#L14)). Persistierte Runs (mit Schritten, Tokens, Kosten, Fehlern) wären die Grundlage für Diagnose und Kostenanalyse. @@ -528,7 +528,7 @@ Siehe K3. ## 6. Vorgeschlagene Reihenfolge -> **Abgelöst durch die [Roadmap](Roadmap.md)** (Juli 2026). Die offenen Punkte +> **Abgelöst durch die [Roadmap](../Roadmap.md)** (Juli 2026). Die offenen Punkte > werden dort weitergeführt; dieser Abschnitt bleibt als Stand der Bestandsaufnahme > eingefroren. F-A1/S4, F-A2, F-A5, T6, T7 sowie B6–B8 sind in den Roadmap-Vorhaben > A1–A4 aufgegangen. diff --git a/docs/Deploymentcenter-2.4-Integrationsplan.md b/docs/archiv/Deploymentcenter-2.4-Integrationsplan.md similarity index 95% rename from docs/Deploymentcenter-2.4-Integrationsplan.md rename to docs/archiv/Deploymentcenter-2.4-Integrationsplan.md index 4ae51df..fc452e8 100644 --- a/docs/Deploymentcenter-2.4-Integrationsplan.md +++ b/docs/archiv/Deploymentcenter-2.4-Integrationsplan.md @@ -1,6 +1,6 @@ # Deploymentcenter 2.2 – 2.4: Was noch zu tun ist -Stand: 2026-08-13. Ergänzt [Deploymentcenter-Integration](Deploymentcenter-Integration.md) +Stand: 2026-08-13. Ergänzt [Deploymentcenter-Integration](../Deploymentcenter-Integration.md) (dort steht der Stand nach 2.1) um die drei neuen Ausbaustufen. | Fassung | Was dazukam | Betrifft uns | @@ -40,7 +40,7 @@ pack-and-deploy --config deploy/packager.config.json \ ``` - Zugangsdaten in `deploy/packager.config.json` (per `.gitignore` ausgeschlossen), - Vorlage ohne Werte in [`packager.config.example.json`](../deploy/packager.config.example.json). + Vorlage ohne Werte in [`packager.config.example.json`](../../deploy/packager.config.example.json). - **`ftpRemoteBaseDir` ist `/releases`**, nicht `/public_html/releases` wie in der Packager-Vorlage: Auf diesem Server liegt die Release-Ablage auf der FTP-Wurzel. - Der Packager veröffentlicht mit einem **Sub-Token**, das nur `updateservice:publish` @@ -50,7 +50,7 @@ pack-and-deploy --config deploy/packager.config.json \ Deploymentcenter-Projektbaum in die FTP-Wurzel und hat mit dem Veröffentlichen eines Anwendungspakets nichts zu tun. - Die Versionsgegenprobe des Packagers greift und passt: `` aus - [Directory.Build.props](../Directory.Build.props) stimmt mit `clawddotnet.dll` überein. + [Directory.Build.props](../../Directory.Build.props) stimmt mit `clawddotnet.dll` überein. Offen: `linux-x64` (erst nach der Avalonia-Portierung) und `prod`. @@ -63,7 +63,7 @@ Unsere Konfiguration liegt seit der Linux-Portierung in `AppPaths.ConfigDirector (`%APPDATA%` bzw. XDG), **nicht** neben der Programmdatei. Ein Update kann sie also gar nicht überschreiben. Zu prüfen bleibt nur, dass keine leeren Arbeitsordner ins Paket wandern — die `CreateWorkingDirectories`-Targets in -[ClawdDotNet.csproj](../ClawdDotNet.csproj) legen `tools/`, `Logs/` und `Instances/` +[ClawdDotNet.csproj](../../ClawdDotNet.csproj) legen `tools/`, `Logs/` und `Instances/` unter `OutputPath` an, und die sind mit AppPaths ohnehin überholt. --- @@ -72,7 +72,7 @@ unter `OutputPath` an, und die sind mit AppPaths ohnehin überholt. Aus dem Hinweis ist eine Rückfrage geworden („Jetzt installieren" / „Später"), die den `update-agent` startet. Umgesetzt in -[`DeploymentcenterService.StartUpdate`](../src/ClawdDotNet.App/Services/DeploymentcenterService.cs) +[`DeploymentcenterService.StartUpdate`](../../src/ClawdDotNet.App/Services/DeploymentcenterService.cs) und `App.StartUpdateAsync`. ### Der Agent wird mitgeliefert — er muss es @@ -82,7 +82,7 @@ wo der Benutzer sie hingelegt hat. `ResolveAgentPath()` sucht ihn aber neben der Anwendung. Ohne Mitliefern fände die Anwendung nie einen Agenten und könnte sich nicht aktualisieren. -[`deploy/publish.py`](../deploy/publish.py) holt das ausgelieferte Binary von +[`deploy/publish.py`](../../deploy/publish.py) holt das ausgelieferte Binary von `/installer/`, **prüft die SHA256 gegen `installer.json`** und legt es plattformrichtig ab (`update-agent.exe` bzw. `update-agent`). Bewusst das offizielle statt eines selbst gebauten: Es ist dasselbe, das die Erstinstallation verwendet, und wird zentral gepflegt. @@ -126,7 +126,7 @@ schreibbar ist ([Linux-Analyse](Linux-Portierung-Analyse.md)). Das Deploymentcenter hat daraufhin `location` am Ziel ergänzt (`install`, `config`, `data`, `home`) samt Variablenersetzung in `file`. Damit ist der Weg frei; -[`setup.json`](../src/ClawdDotNet.Desktop/setup.json) liegt im Projekt und wird ins +[`setup.json`](../../src/ClawdDotNet.Desktop/setup.json) liegt im Projekt und wird ins Ausgabeverzeichnis kopiert, landet also im Paket neben der `manifest.json`. ### Der Ordnername ist bewusst kleingeschrieben @@ -148,7 +148,7 @@ leeres Verzeichnis neben dem, aus dem die Anwendung liest. Das Token stellt der Server aus (`source: "provision"`), die Server-Adresse kommt aus dem Installer (`detect:baseurl`). Damit entfällt der Absatz „bis die Avalonia-Einstellungs- ansicht steht, von Hand in `Settings.json`" aus der -[Integrationsbeschreibung](Deploymentcenter-Integration.md) — jedenfalls für frisch +[Integrationsbeschreibung](../Deploymentcenter-Integration.md) — jedenfalls für frisch installierte Systeme. Der Installer schreibt Lizenzschlüssel und Token **im Klartext**; er kennt unsere diff --git a/docs/Deploymentcenter-Anbindung-Review.md b/docs/archiv/Deploymentcenter-Anbindung-Review.md similarity index 90% rename from docs/Deploymentcenter-Anbindung-Review.md rename to docs/archiv/Deploymentcenter-Anbindung-Review.md index 40dc6a0..6b92566 100644 --- a/docs/Deploymentcenter-Anbindung-Review.md +++ b/docs/archiv/Deploymentcenter-Anbindung-Review.md @@ -2,7 +2,7 @@ > **Nachtrag 2026-08-08 — die Anbindung ist umgestellt, Server und SDK stehen auf 2.1.** > Abschnitt 4 und 5 sind abgearbeitet; wie es jetzt aussieht, steht in -> [Deploymentcenter-Integration](Deploymentcenter-Integration.md). +> [Deploymentcenter-Integration](../Deploymentcenter-Integration.md). > > Mit **SDK 2.1 erledigt** (waren Befunde aus Abschnitt 3 bzw. aus der Durchsicht der > 2.0-Anbindung): @@ -48,7 +48,7 @@ Punkte aus derselben Durchsicht — drei davon würden beim Ausrollen wehtun. | Punkt aus dem Vorschlag | Umsetzung | |---|---| -| Format `2::` | [HardwareId.cs:125](../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/HardwareId.cs) | +| Format `2::` | [HardwareId.cs:125](../../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/HardwareId.cs) | | **Kein `MachineName` im Hash** | `ComputeV2Hash`, `:138` — der wichtigste Punkt, sauber umgesetzt | | Quellenkette Windows/Linux | `:42–107`, inklusive `dmi-uuid` | | `IsPlausibleMachineId` (Länge, `uninitialized`, nur Nullen) | `:161` | @@ -57,11 +57,11 @@ Punkte aus derselben Durchsicht — drei davon würden beim Ausrollen wehtun. | Erweiterte Stoppwortliste | `:23` — inkl. `br-`, `virbr`, `cni`, `cali` | | `machine.key` mit `0600` | `:290`, `SetUnixPermissions` mit `#if NET8_0_OR_GREATER` | | Vorgabe per Umgebungsvariable | `LicenseConfig.HardwareIdOverride`, beide Namen | -| XDG-Auflösungskette, nie leerer Pfad | [LicenseConfig.cs:28](../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/LicenseConfig.cs), mit `ValidateNonEmpty` | +| XDG-Auflösungskette, nie leerer Pfad | [LicenseConfig.cs:28](../../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/LicenseConfig.cs), mit `ValidateNonEmpty` | | Mehrfachziel `netstandard2.0;net8.0` | csproj, BouncyCastle nur im netstandard-Zweig | -| `LLS2`-Hülle, AES-GCM, HKDF | [StateStore.cs:169](../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/StateStore.cs) — Schlüssel aus HW-ID abgeleitet, bindet den Cache also echt an die Maschine | +| `LLS2`-Hülle, AES-GCM, HKDF | [StateStore.cs:169](../../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/StateStore.cs) — Schlüssel aus HW-ID abgeleitet, bindet den Cache also echt an die Maschine | | `ILicensePrompt` + Konsolenfassung | vorhanden — genau das, was der kopflose Host braucht | -| Servermigration v1→v2 | [LicenseService.php:108](../../Deploymentcenter/src/Modules/License/LicenseService.php), mit Prüfprotokolleintrag `hwid_migrated` | +| Servermigration v1→v2 | [LicenseService.php:108](../../../Deploymentcenter/src/Modules/License/LicenseService.php), mit Prüfprotokolleintrag `hwid_migrated` | | Schema `hwid_version`/`hwid_source`/`platform` | `sql/migrations/v2_hardware_id.sql`, rückwärtskompatibel | | Verwaltungsansicht zeigt Quelle/Plattform | `public/index.php:1227` | @@ -80,7 +80,7 @@ das ist jetzt reine Anschlussarbeit in ClawdDotNet, keine Konzeptarbeit mehr. ### 2.1 Es wird nichts signiert — die Lizenzprüfung ist eine Vertrauensfrage an DNS -[LicenseClient.cs:62](../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/LicenseClient.cs): +[LicenseClient.cs:62](../../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/LicenseClient.cs): ```csharp string status = root.TryGetProperty("status", out var sProp) ? sProp.GetString() ?? "unknown" : "unknown"; @@ -135,7 +135,7 @@ Der Migrationsweg ist auf beiden Seiten korrekt gebaut — er wird nur nie auslösen, weil der Client eine andere v1-ID berechnet als die, die in der Datenbank steht. -Alt ([LicenseLabrador/HardwareId.cs:20](../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/HardwareId.cs)): +Alt ([LicenseLabrador/HardwareId.cs:20](../../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/HardwareId.cs)): ```csharp rawBuilder.Append(machineId); // MachineGuid, sonst MAC @@ -143,7 +143,7 @@ rawBuilder.Append(Environment.MachineName); // direkt angehängt, kein Tren → sha256(machineGuid + machineName) ``` -Neu ([HardwareId.cs:149](../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/HardwareId.cs)): +Neu ([HardwareId.cs:149](../../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/HardwareId.cs)): ```csharp string raw = $"{Environment.MachineName}:{firstMac}"; @@ -174,7 +174,7 @@ Aktivierungsplätze schon verbraucht sind. ### 2.3 Der Klartext-Rückfall ist noch da, nur woanders -[StateStore.cs:79](../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/StateStore.cs) — +[StateStore.cs:79](../../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/StateStore.cs) — „Legacy Migration Check": ```csharp @@ -217,7 +217,7 @@ und ist als Cache wertlos. nichts. Alte Cachedateien sollen verworfen werden — eine einmalige Online-Prüfung ist der ganze Preis. -Nebenbei: `Checksum = hwInfo.HardwareId` ([LicenseClient.cs:79](../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/LicenseClient.cs)) +Nebenbei: `Checksum = hwInfo.HardwareId` ([LicenseClient.cs:79](../../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/LicenseClient.cs)) ist keine Prüfsumme, sondern eine Kopie der HW-ID. Das Feld ist damit ohne Funktion — entweder mit einem HMAC über die übrigen Felder füllen oder entfernen, damit niemand später Schutz vermutet, wo keiner ist. @@ -228,7 +228,7 @@ damit niemand später Schutz vermutet, wo keiner ist. | Fundstelle | Sache | |---|---| -| [LicenseClient.cs:26](../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/LicenseClient.cs) | Eigener `HttpClient` je Instanz, nie freigegeben, **ohne Zeitgrenze** (Vorgabe 100 s). Der alte `LicenseConfig.HttpTimeout` war 6 s. In `LicenseGate.RunStartupCheck` bedeutet das bis zu 100 s Standbild beim Start, wenn der Server nicht antwortet. | +| [LicenseClient.cs:26](../../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/LicenseClient.cs) | Eigener `HttpClient` je Instanz, nie freigegeben, **ohne Zeitgrenze** (Vorgabe 100 s). Der alte `LicenseConfig.HttpTimeout` war 6 s. In `LicenseGate.RunStartupCheck` bedeutet das bis zu 100 s Standbild beim Start, wenn der Server nicht antwortet. | | `:107` | `catch (Exception ex)` um den gesamten Block: Auch ein Fehler beim Auswerten einer *erfolgreichen* Antwort landet im Offline-Zweig. Ein defekter Server gilt dann als „offline". | | `:47` | `app_version = "1.0.0"` fest verdrahtet. ClawdDotNet hat `BuildInfo.Build` — sollte Parameter sein, sonst steht in der Verwaltungsansicht bei jeder Instanz dasselbe. | | `:32`, `:172` | `HardwareId.GetHardwareId()` bei jedem Aufruf neu: liest unter Linux Dateien und zählt Netzwerkschnittstellen auf. Einmal berechnen und halten. | @@ -277,7 +277,7 @@ abzugleichen. | [Program.cs:112](Program.cs:112) | Lizenzprüfung so verlagern, dass sie ohne Fenster auskommt (kopfloser Host). | | Host (neu) | `--license-status`, `--license-set-key`, `--license-deactivate` — der Client bringt alles Nötige mit. | | [WatchdogClient.cs](src/ClawdDotNet.Core/Watchdog/WatchdogClient.cs) | Pfade auf `/api/watchdog/v1/…`; Registrierungsweg klären (Abschnitt 4). | -| `docs/Integrationsplan-WatchDog-LicenseLabrador.md` | Abgelöst durch [Deploymentcenter-Integration](Deploymentcenter-Integration.md). | +| `docs/Integrationsplan-WatchDog-LicenseLabrador.md` | Abgelöst durch [Deploymentcenter-Integration](../Deploymentcenter-Integration.md). | --- diff --git a/docs/Konzepte-Backup-Finanz-Analyse.md b/docs/archiv/Konzepte-Backup-Finanz-Analyse.md similarity index 97% rename from docs/Konzepte-Backup-Finanz-Analyse.md rename to docs/archiv/Konzepte-Backup-Finanz-Analyse.md index 59e9a51..7a218ee 100644 --- a/docs/Konzepte-Backup-Finanz-Analyse.md +++ b/docs/archiv/Konzepte-Backup-Finanz-Analyse.md @@ -57,8 +57,8 @@ Abhängigkeit. ## Problem 3: JSON-Dateien werden nicht atomar geschrieben ⚠️ Alle Schreibvorgänge laufen über `File.WriteAllText` -([InstanceDirectoryManager.cs:439](../Services/InstanceDirectoryManager.cs#L439), -[AgentEngine.cs:783](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L783)). Ein Absturz +([InstanceDirectoryManager.cs:439](../../Services/InstanceDirectoryManager.cs#L439), +[AgentEngine.cs:783](../../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L783)). Ein Absturz oder Stromausfall mitten im Schreiben hinterlässt eine abgeschnittene Datei. **Das ist bereits passiert:** In der Instanz `TradingTeam` liegt eine @@ -278,7 +278,7 @@ Rohzahlen. # Vorgeschlagene Reihenfolge -> **Abgelöst durch die [Roadmap](Roadmap.md)** (Juli 2026). Die offenen Punkte +> **Abgelöst durch die [Roadmap](../Roadmap.md)** (Juli 2026). Die offenen Punkte > laufen dort als C1–C8 weiter; S4 + K2 sind in den Vorhaben A2/A3 > (Staging-Freigabe, Audit-Log) aufgegangen. diff --git a/docs/Linux-Portierung-Analyse.md b/docs/archiv/Linux-Portierung-Analyse.md similarity index 99% rename from docs/Linux-Portierung-Analyse.md rename to docs/archiv/Linux-Portierung-Analyse.md index 52e4e84..69afd2c 100644 --- a/docs/Linux-Portierung-Analyse.md +++ b/docs/archiv/Linux-Portierung-Analyse.md @@ -534,7 +534,7 @@ LiveCharts2 ist damit **keine Portierung, sondern neue Funktionalität** — sie gehört zum Trading-Teil, nicht zum Linux-Umzug, und ist in den 50–80 PT oben nicht enthalten. Wenn die Kursansichten kommen, sind dafür grob 5–10 PT zusätzlich zu rechnen. Das passt zu dem, was in -[docs/Roadmap.md](docs/Roadmap.md) und der Notiz „Basis vor Trading härten" +[docs/Roadmap.md](../Roadmap.md) und der Notiz „Basis vor Trading härten" festgehalten ist: Erst die Basis, dann die Handelsansichten. Ein Punkt, der jetzt schon zählt: LiveCharts2 setzt auf SkiaSharp, genau wie diff --git a/docs/Lizenz-HardwareId-v2-Implementierungsvorschlag.md b/docs/archiv/Lizenz-HardwareId-v2-Implementierungsvorschlag.md similarity index 95% rename from docs/Lizenz-HardwareId-v2-Implementierungsvorschlag.md rename to docs/archiv/Lizenz-HardwareId-v2-Implementierungsvorschlag.md index d08baa2..509ce8a 100644 --- a/docs/Lizenz-HardwareId-v2-Implementierungsvorschlag.md +++ b/docs/archiv/Lizenz-HardwareId-v2-Implementierungsvorschlag.md @@ -14,7 +14,7 @@ denselben Code betreffen — die sollten in einem Zug mit erledigt werden. ### 1.1 Der Rechnername steckt im Hash — das ist das eigentliche Problem -[HardwareId.cs:43](../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/HardwareId.cs): +[HardwareId.cs:43](../../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/HardwareId.cs): ```csharp rawBuilder.Append(Environment.MachineName); // "for system isolation" @@ -31,12 +31,12 @@ Die Lizenz wäre nach dem zweiten `docker run` verbraucht. Die Absicht („system isolation") ist auch nicht erfüllt: Der Rechnername steht ohnehin im Feld `hostname`, das der Server bei jeder Prüfung mitschreibt -([LicenseService.php:112](../../LicenseLabrador/server/src/LicenseService.php)). +([LicenseService.php:112](../../../LicenseLabrador/server/src/LicenseService.php)). Diagnostisch verlieren wir nichts, wenn er aus dem Hash verschwindet. ### 1.2 Die MAC-Ausweichlösung ist unter Linux instabil -[HardwareId.cs:86](../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/HardwareId.cs) +[HardwareId.cs:86](../../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/HardwareId.cs) nimmt die alphabetisch erste physische MAC. Unter Linux: - Die Stoppwortliste kennt `docker` und `veth`, aber **nicht** `br-` (Bridges), @@ -50,7 +50,7 @@ Ausweichlösung ist damit unter Linux schlimmer als keine. ### 1.3 Der Zustandsspeicher fällt still auf Klartext zurück -[StateStore.cs:41](../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/StateStore.cs) +[StateStore.cs:41](../../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/StateStore.cs) beim Lesen und `:90` beim Schreiben: ```csharp @@ -63,17 +63,17 @@ Folgen: - `SECURITY.md` behauptet, der Cache sei „strikt an die `hardware_id` gebunden". Das stimmt für die *Hülle* (die Prüfung in - [LicenseClient.cs:198](../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/LicenseClient.cs)), + [LicenseClient.cs:198](../../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/LicenseClient.cs)), nicht für die Cache-Datei selbst. - Ernster: `max_seen_time` ist die Uhr-Rückdreh-Sperre - ([StateStore.cs:107](../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/StateStore.cs)). + ([StateStore.cs:107](../../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/StateStore.cs)). Wer eine `state.dat` von Hand schreiben kann, setzt den Wert auf 0 und stellt die Systemuhr zurück. Der Klartext-Rückfall beim **Lesen** macht das möglich, und zwar auf jeder Plattform, auf der DPAPI nicht greift. ### 1.4 Ablageort bricht bei einem systemd-Dienst weg -[LicenseConfig.cs:22](../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/LicenseConfig.cs) +[LicenseConfig.cs:22](../../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/LicenseConfig.cs) verwendet `Environment.GetFolderPath(SpecialFolder.ApplicationData)`. Läuft der Dienst unter `User=clawd` ohne Heimatverzeichnis, ist `HOME` nicht gesetzt und `GetFolderPath` liefert einen **leeren String**. `Path.Combine("", slug, @@ -255,7 +255,7 @@ hwid_source = "machine-id", ``` **Server** — in `LicenseService::validate`, an der Stelle der heutigen Suche -([LicenseService.php:100](../../LicenseLabrador/server/src/LicenseService.php)): +([LicenseService.php:100](../../../LicenseLabrador/server/src/LicenseService.php)): ``` 1. Aktivierung mit hardware_id = suchen @@ -281,7 +281,7 @@ Veröffentlichungen) aus dem Client fallen. Nicht übersehen: Die Hardware-ID geht in zwei weitere Berechnungen ein — `CalculateHmac(state, licenseKey, _hardwareId)` für die Prüfsumme in `LicenseResult` -([LicenseClient.cs:272](../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/LicenseClient.cs)) +([LicenseClient.cs:272](../../../LicenseLabrador/client-dotnet/LicenseLabrador.Client/LicenseClient.cs)) und den Seed des Speicherschutzes (`:287`). Nach dem Formatwechsel schlägt `VerifyChecksum` für jede zwischengespeicherte Hülle fehl. @@ -321,7 +321,7 @@ für den Fall danach. ### 5.2 Abmelden vor dem Umzug (existiert, aber nicht erreichbar) `LicenseService::deactivate` löscht die Aktivierungszeile und gibt den Platz frei -([LicenseService.php:153](../../LicenseLabrador/server/src/LicenseService.php)), +([LicenseService.php:153](../../../LicenseLabrador/server/src/LicenseService.php)), und `LicenseClient.DeactivateAsync` ruft es auf. In ClawdDotNet ist die Methode aber nur über [LicenseGate.cs:39](Services/LicenseGate.cs) erreichbar und dort an die GUI gebunden. diff --git a/docs/archiv/README.md b/docs/archiv/README.md index 0e8956e..8f3a1a5 100644 --- a/docs/archiv/README.md +++ b/docs/archiv/README.md @@ -1,27 +1,41 @@ # Archiv -Die vier Dokumente hier sind die **Entwicklungs-Prompts aus der Anfangszeit** des -Projekts (Mai–Juli 2026). Sie haben ClawdDotNet aufgebaut und beschreiben deshalb -den Stand von damals — unter anderem eine WinForms-Oberfläche mit WebView2, die es -seit dem Frühjahrsputz vom 2026-08-23 nicht mehr gibt. +Was hier liegt, ist **abgeschlossen und wird nicht mehr fortgeschrieben.** Der aktuelle +Stand steht ausschließlich in der [Roadmap](../Roadmap.md); ihr Abschnitt 7 hält fest, +was aus jedem dieser Dokumente dorthin übernommen wurde. -**Sie werden nicht mehr fortgeschrieben.** Wer den heutigen Stand sucht, findet ihn -in [Roadmap](../Roadmap.md), [Bestandsaufnahme](../Bestandsaufnahme-2026-07.md) und -den Konzept-Dokumenten daneben. +Aufgehoben werden sie, weil sie die **Begründung** tragen: warum das System so +geschnitten ist, wie es geschnitten ist, und welche Befunde die Entscheidungen geformt +haben. Diese Herleitung lässt sich in einer Vorhabenliste nicht unterbringen, ohne sie +unlesbar zu machen. -Aufgehoben werden sie aus zwei Gründen: +> **Verweise auf Quelltext können ins Leere gehen.** Viele dieser Papiere zeigen auf +> Dateien der WinForms-Fassung (`frm_*.cs`, `UI/`, `Models/`, `Program.cs`) oder auf die +> alten Scheduler — beides wurde inzwischen entfernt. Wer die Stellen sehen will, findet +> sie im Tag `vor-fruehjahrsputz-2026-08`. Die Zeilennummern wurden bewusst **nicht** +> nachgeführt: Ein archiviertes Dokument beschreibt den Stand seines Datums. -1. **Herkunft.** Sie erklären, warum das System so geschnitten ist, wie es - geschnitten ist — der Schichtschnitt Core/Tools/App stammt von hier. -2. **Eine Regel gilt weiter.** `ClawdDotNet_Prompt_InternetTools.md` enthält die - Pflichtfelder `fetchedAt` / `dataAsOf` / `source`, an die sich alle Internet-Tools - halten. Der [WebSearch-Umsetzungsplan](../umsetzungsplaene/UMSETZUNGSPLAN-WebSearch-Tool.md) - verweist darauf. Zieht diese Regel eines Tages in ein eigenes Dokument um, kann - die Datei ganz weg. +--- -| Datei | Was darin steht | Was davon noch gilt | +## Befunde und Konzepte + +| Dokument | Datum | Was es war | Warum archiviert | +|---|---|---|---| +| [Bestandsaufnahme-2026-07](Bestandsaufnahme-2026-07.md) | Juli 2026 | Vollständiges Review von Engine, Sicherheit, Tools, Scheduling und Oberfläche. Quelle der Kürzel S1–S7, B1–B14, K1–K6, T1–T9, F-A1…F-A7 | Erledigtes steht in Roadmap 5, Offenes in 3.1/3.2/3.7. Die Kürzel leben in der Herkunft-Spalte weiter | +| [Konzepte-Backup-Finanz-Analyse](Konzepte-Backup-Finanz-Analyse.md) | Juli 2026 | Drei Konzepte: Sicherung, Finanzumfeld, Leistungsmessung | Sicherung ist gebaut; der Rest läuft als C1–C8 weiter | +| [Linux-Portierung-Analyse](Linux-Portierung-Analyse.md) | 2026-08-06 | Was kostet der Umzug nach Linux | Der teure Teil — 8.900 Zeilen WinForms — ist mit der Avalonia-Portierung entfallen. Übrig bleiben drei Kernstellen (DPAPI, Pfadvergleiche, Zeitzonen-IDs), sie stehen in Roadmap 3.5 | +| [Lizenz-HardwareId-v2](Lizenz-HardwareId-v2-Implementierungsvorschlag.md) | 2026-08-06 | Überarbeitung der Hardware-Erkennung für LicenseLabrador | **Gegenstandslos.** LicenseLabrador ist durch das Deploymentcenter ersetzt. Lesenswert bleibt Abschnitt 1: warum der Rechnername nicht in eine Hardware-Kennung gehört | +| [Deploymentcenter-Anbindung-Review](Deploymentcenter-Anbindung-Review.md) | 2026-08-08 | Review der ersten Anbindung | Befunde behoben; die Verdrahtung beschreibt heute [Deploymentcenter-Integration](../Deploymentcenter-Integration.md) | +| [Deploymentcenter-2.4-Integrationsplan](Deploymentcenter-2.4-Integrationsplan.md) | 2026-08-15 | Zugangsschutz, Release-Strecke, Update, Erstinstallation, Signatur — durchgearbeitet | Abgearbeitet bis auf DC8 und zwei Betreiberpunkte; die stehen in Roadmap 3.5. Enthält die Messprotokolle der live durchgespielten Setup- und Update-Kette | + +## Entwicklungs-Prompts der Anfangszeit + +Mai–Juli 2026. Sie haben ClawdDotNet aufgebaut und beschreiben deshalb den Stand von +damals — unter anderem eine WinForms-Oberfläche mit WebView2, die es nicht mehr gibt. + +| Dokument | Was darin steht | Was davon noch gilt | |---|---|---| -| `ClawdDotNet_StartPrompt.md` | Gesamtentwurf, Kernklassen, Beispielkonfiguration | Schichtschnitt und Tool-Vertrag; Oberfläche und `configs/*.json` überholt | -| `ClawdDotNet_Prompt_WebviewChatWinForms.md` | WinForms-Oberfläche mit WebView2-Chat | nichts — ersetzt durch `src/ClawdDotNet.Desktop` | -| `ClawdDotNet_Prompt_TelegramClient.md` | Entwurf des TelegramClient-Tools | umgesetzt in `src/ClawdDotNet.Tools.TelegramClient` | -| `ClawdDotNet_Prompt_InternetTools.md` | WebFetch, DirectAPI, WebMonitor | die Pflichtfelder-Regel (siehe oben) | +| [ClawdDotNet_StartPrompt](ClawdDotNet_StartPrompt.md) | Gesamtentwurf, Kernklassen, Beispielkonfiguration | Der Schichtschnitt Core/Tools/App und der Tool-Vertrag stammen von hier. Oberfläche und `configs/*.json` sind überholt | +| [ClawdDotNet_Prompt_WebviewChatWinForms](ClawdDotNet_Prompt_WebviewChatWinForms.md) | WinForms-Oberfläche mit WebView2-Chat | nichts — ersetzt durch `src/ClawdDotNet.Desktop` | +| [ClawdDotNet_Prompt_TelegramClient](ClawdDotNet_Prompt_TelegramClient.md) | Entwurf des TelegramClient-Tools | umgesetzt in `src/ClawdDotNet.Tools.TelegramClient` | +| [ClawdDotNet_Prompt_InternetTools](ClawdDotNet_Prompt_InternetTools.md) | WebFetch, DirectAPI, WebMonitor | **Eine Regel gilt weiter:** die Pflichtfelder `fetchedAt` / `dataAsOf` / `source` in jedem Tool-Ergebnis mit externen Daten. Der [WebSearch-Umsetzungsplan](../umsetzungsplaene/UMSETZUNGSPLAN-WebSearch-Tool.md) verweist darauf. Zieht diese Regel in ein eigenes Dokument um, kann die Datei ganz weg | diff --git a/docs/umsetzungsplaene/UMSETZUNGSPLAN-AgentEditor-Haertung.md b/docs/umsetzungsplaene/UMSETZUNGSPLAN-AgentEditor-Haertung.md index 12a3708..441f4ec 100644 --- a/docs/umsetzungsplaene/UMSETZUNGSPLAN-AgentEditor-Haertung.md +++ b/docs/umsetzungsplaene/UMSETZUNGSPLAN-AgentEditor-Haertung.md @@ -1,5 +1,9 @@ # Umsetzungsplan: AgentEditor härten (Personalverwaltung) +> **Stand 2026-08-23: beschlossen, noch nicht gebaut.** Einordnung siehe +> [Roadmap](../Roadmap.md) 3.2 (nach AgentInspector) — die Reihenfolge gilt dort, +> dieses Dokument ist der Bauplan. + > Stand: 2026-08-05 > Ziel: Änderungen an Identity und Soul im laufenden Betrieb bleiben möglich, > werden aber freigabepflichtig, nachvollziehbar und rücknehmbar. diff --git a/docs/umsetzungsplaene/UMSETZUNGSPLAN-AgentInspector-Supervisor.md b/docs/umsetzungsplaene/UMSETZUNGSPLAN-AgentInspector-Supervisor.md index 9b21f05..72cbb40 100644 --- a/docs/umsetzungsplaene/UMSETZUNGSPLAN-AgentInspector-Supervisor.md +++ b/docs/umsetzungsplaene/UMSETZUNGSPLAN-AgentInspector-Supervisor.md @@ -1,5 +1,8 @@ # Umsetzungsplan: AgentInspector (Supervisor-Einsicht) +> **Stand 2026-08-23: beschlossen, noch nicht gebaut.** Einordnung siehe +> [Roadmap](../Roadmap.md) 3.2 — die Reihenfolge gilt dort, dieses Dokument ist der Bauplan. + > Stand: 2026-08-05 > Ziel: Ein Supervisor-Agent kann beurteilen, ob die anderen Agenten der Instanz > das tun, was sie tun sollen — über Audit-Log, Taskboard und lesenden Zugriff diff --git a/docs/umsetzungsplaene/UMSETZUNGSPLAN-FileRW-Papierkorb-Cleanup.md b/docs/umsetzungsplaene/UMSETZUNGSPLAN-FileRW-Papierkorb-Cleanup.md index 5b7d0b9..276d345 100644 --- a/docs/umsetzungsplaene/UMSETZUNGSPLAN-FileRW-Papierkorb-Cleanup.md +++ b/docs/umsetzungsplaene/UMSETZUNGSPLAN-FileRW-Papierkorb-Cleanup.md @@ -1,5 +1,8 @@ # Umsetzungsplan: FileRW-Papierkorb + Cleanup-Job +> **Stand 2026-08-23: beschlossen, noch nicht gebaut.** Eingeordnet als Punkt 3 der +> [Roadmap](../Roadmap.md) — die Reihenfolge gilt dort, dieses Dokument ist der Bauplan. + > Stand: 2026-08-05 > Ziel: `FileRW.delete` löscht nicht mehr endgültig, sondern verschiebt in einen > Papierkorb je Workspace. Ein Cron-Job räumt den Papierkorb nach X Tagen auf. diff --git a/docs/umsetzungsplaene/UMSETZUNGSPLAN-WebSearch-Tool.md b/docs/umsetzungsplaene/UMSETZUNGSPLAN-WebSearch-Tool.md index 3ce99e0..05e1a2f 100644 --- a/docs/umsetzungsplaene/UMSETZUNGSPLAN-WebSearch-Tool.md +++ b/docs/umsetzungsplaene/UMSETZUNGSPLAN-WebSearch-Tool.md @@ -1,5 +1,9 @@ # Umsetzungsplan: WebSearch-Tool (Internetzugang erweitern) +> **Stand 2026-08-23: nicht beschlossen.** Steht im Ideenspeicher der +> [Roadmap](../Roadmap.md) (Abschnitt 4) und bleibt bewusst zuletzt — größter +> Sicherheitshebel. Dieses Dokument ist der Bauplan, falls entschieden wird. + > Stand: 2026-08-05 > Ziel: Agenten können das Web durchsuchen, statt nur bekannte URLs abzurufen. > Reihenfolge: **Zuletzt.** Größter Sicherheitshebel, deshalb erst nach