Eine Roadmap statt neun verteilter Listen

Der Stand lag ueber eine Bestandsaufnahme, drei Konzeptpapiere, vier
Umsetzungsplaene und zwei Deploymentcenter-Dokumente verteilt - jedes mit
eigener Reihenfolge, teils widersprueglich. Alle offenen Punkte daraus sind
in docs/Roadmap.md zusammengefuehrt.

Aufbau der neuen Roadmap
- Statusvokabular: erledigt / beschlossen-offen / Entscheidung noetig /
  zurueckgestellt / Idee. Damit steht das Geparkte sichtbar drin, statt in
  einem Konzeptpapier zu verschwinden.
- Herkunft-Spalte traegt das alte Kuerzel (S4, K2, B9, T4, F-A1, C1, DC1),
  damit die archivierten Papiere auffindbar bleiben, ohne sie zu lesen.
- Abschnitt 1 Reihenfolge, 2 offene Entscheidungen, 3 die Vorhaben nach
  Bereich, 4 Ideenspeicher, 5 Chronik des Erledigten, 6 Modell-Einstufung,
  7 Herkunftskarte.

Was dabei sichtbar wurde
- Neun Entscheidungen blockieren Arbeit, ohne dass sie Aufwand kosten -
  allen voran Matrix oder Rocket.Chat. Sie stehen jetzt gesammelt in
  Abschnitt 2 statt verstreut in den Diskussionsteilen der Konzepte.
- B8 (keine Tiefenbegrenzung bei AgentComm) ist unveraendert offen. Das ist
  keine Theorie: A haelt sein Gate, waehrend es auf B wartet - ruft B nun A,
  warten beide bis zum Timeout. Der Testfall A13 dafuer fehlt bis heute.
- Die vier Umsetzungsplaene vom 2026-08-05 sind alle unumgesetzt und waren
  in keiner Roadmap verzeichnet.

Archiv
Sechs Dokumente ziehen nach docs/archiv/: Bestandsaufnahme, Konzepte
Backup/Finanz/Analyse, Linux-Portierung-Analyse, Lizenz-HardwareId-v2
(gegenstandslos - LicenseLabrador ist ersetzt), Deploymentcenter-Review und
der 2.4-Integrationsplan. Sie bleiben als Begruendung lesbar, werden aber
nicht mehr fortgeschrieben; das README ordnet jedes einzeln ein und warnt,
dass ihre Quelltext-Verweise ins Leere gehen koennen.

Bauplan bleibt Bauplan
Taskboard, Audit, Staging, Memory, Agentenkommunikation, RocketChat und
Deploymentcenter-Integration bleiben in docs/ - sie sind die Detailvorgabe
fuer die Umsetzung, nicht Vorhabenlisten. Jedes bekommt oben eine Zeile,
die seine Rolle und den Umsetzungsstand nennt und auf die Roadmap zeigt.
Dasselbe fuer die vier Umsetzungsplaene: die Reihenfolge gilt in der
Roadmap, nicht im Plan.

Nebenbei repariert: Taskboard-Konzept und Teststrategie verwiesen auf
AgentScheduler und ToolJobScheduler, die seit der Scanner-Konsolidierung
geloescht sind. Alle Dokument-Verweise in docs/ sind geprueft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-08-23 18:31:06 +02:00
co-authored by Claude Opus 5
parent 2853541629
commit 740649789e
18 changed files with 443 additions and 406 deletions
+4
View File
@@ -1,5 +1,9 @@
# Agentenkommunikation — Erfassung, Ansicht, Auswertung # 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 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 paarweise nachlesbar und lässt sich von einem Agenten automatisiert auswerten — um zu
finden, wo die Zusammenarbeit klemmt. finden, wo die Zusammenarbeit klemmt.
+3
View File
@@ -1,5 +1,8 @@
# Audit-Log & Receipts — Nachvollziehbarkeit # 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: 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 - **Audit-Log** — ein Eintrag je Tool-Aufruf: wer, wann, welches Tool, mit welchem
+4 -1
View File
@@ -1,5 +1,8 @@
# Deploymentcenter-Integration # 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 Stand: 2026-08-08, Deploymentcenter **2.1**. Ersetzt den früheren
`Integrationsplan-WatchDog-LicenseLabrador.md`. `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 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 `status`. Ein Schlüssel, der nichts prüft, ist schlimmer als keiner: Er lässt Schutz
vermuten, wo keiner ist. Details in 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` ### Der Projekt-Slug ist `clawddotnet`
+4 -1
View File
@@ -1,6 +1,9 @@
# Memory — Langzeitgedächtnis für Agenten # 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 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 nichts von seinem letzten Durchgang — er rief dieselben Quellen ab, zog dieselben
Schlüsse und konnte keine Entwicklung über Zeit verfolgen. Schlüsse und konnte keine Entwicklung über Zeit verfolgen.
+296 -306
View File
@@ -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 | Gepflegt wird nur noch dieses Dokument. Was aus den alten Papieren wurde, steht in
|---|---| [Abschnitt 7](#7--woher-das-hier-kommt).
| 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.
--- ---
Zentrale Liste aller offenen Vorhaben. Sie löst die beiden „Vorgeschlagene ## Wie das hier zu lesen ist
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.
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.
--- ---
## ABeschlossen (aus dem OpenAlice-Vergleich, Juli 2026) ## 0Stand
Hintergrund: Konzeptvergleich mit [OpenAlice](https://github.com/TraderAlice/OpenAlice) Der Kern trägt. Engine, Taskboard, Audit, Gedächtnis, Budget, Sicherung und die
(AGPL-3.0 — Konzepte übernehmen ja, Code nein). Übernommen werden Taskboard, Oberfläche sind gebaut und getestet (585 Tests grün, Build fehlerfrei, keine bekannten
Staging-Freigabe, Audit-Log und das Skill-Modell. Die Inbox-Idee entfällt zugunsten Sicherheitslücken in den Paketen). Die Sicherheitsbefunde S1S7 und die Bugs B1B5,
der geplanten Matrix-Migration (A5). B11, B12 aus der Bestandsaufnahme sind abgearbeitet.
### A1 — Taskboard — **erledigt** Drei Dinge stehen im Weg:
Aufgaben als Markdown-Dateien mit YAML-Frontmatter im `SharedWorkspace`: 1. **Die Freigabe-Ansicht fehlt.** Staging ist gebaut und greift — aber niemand kann
`title`, `status` (`backlog | todo | in_progress | done | canceled`), `priority`, freigeben. Damit ist der unbeaufsichtigte Betrieb, für den das ganze A2-Vorhaben da
`assignee`, optional `when` (`at` | `every` | `cron` **mit Zeitzone**). war, nicht möglich.
2. **A5 ist unentschieden.** Rocket.Chat ist gebaut und bedient denselben Zweck, für den
- **Scanner statt Delay-Schleifen**: Ein Takt (~60 s) prüft, was fällig ist. Matrix vorgesehen war. Solange das offen ist, hängen Streaming (K4), der
Persistiert werden nur Last-Fired-Marker — ein fehlgeschlagener Lauf bleibt der Notfallkanal und ein Teil von A6 in der Luft.
einzige Versuch für diesen Termin, kein automatischer Retry-Sturm. 3. **Agenten können sich gegenseitig verklemmen.** `AgentComm.send_message` hat keine
- **Assignee bestimmt die Ausführung**: `@new` = frischer Lauf ohne Historie, Tiefenbegrenzung; A→B→A blockiert bis zum Timeout. Bekannt seit Juli, unverändert.
`@<agent>` = 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.
--- ---
## BOffen aus der Bestandsaufnahme ## 1Reihenfolge
| Punkt | Was | Stand | Was als Nächstes ansteht, mit Begründung. Alles darunter in Abschnitt 3.
|---|---|---|
| T4 | Proaktiv statt reaktiv kompaktieren | offen, unverändert |
| K2-Rest | Untrusted Content als Daten rahmen (`<untrusted_content>`) | 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 |
Erledigt seit der letzten Fortschreibung: B4 vollständig (Preise kommen live vom | # | Vorhaben | Warum an dieser Stelle | Bereich |
`/models`-Endpunkt, unbekannte Modelle werden sichtbar gemeldet). Beim Frühjahrsputz |---|---|---|---|
dazugekommen: die automatische Sicherung lief ins Leere — die Oberfläche bot sie an | **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) |
und schrieb die Uhrzeit weg, aber der `BackupScheduler` wurde nie gestartet. Jetzt | **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) |
verdrahtet. | **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 (`<untrusted_content>`) 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`, `@<agent>`, `@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. 35 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 WatchDog und LicenseLabrador sind durch das
[Deploymentcenter](Deploymentcenter-Integration.md) ersetzt: eine Adresse, ein Token, [Deploymentcenter](Deploymentcenter-Integration.md) ersetzt: eine Adresse, ein Token,
und dazu Update-Prüfung, Fehler-Stream und Bugtracker. Watchdog läuft wieder pro dazu Update-Prüfung, Fehler-Stream und Bugtracker. Watchdog läuft pro Instanz.
Instanz (ein Monitor je Instanz, mit Gesundheitsprüfungen und angekündigtem Ende).
Offen: | Punkt | Herkunft | Stand | Was |
|---|---|---|---|
| Zugangsschutz | DC-2.4 | ✅ | Lizenzschlüssel als Basic-Auth-Zugang zur Release-Ablage. Benutzername wird als `lic_<sha256[0..16]>` 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 | | **A13** | 📋 | `send_message` A→B→A wird nach `maxDelegationDepth` abgebrochen statt zu verklemmen. Gehört zwingend zu Reihenfolge-Punkt #4 |
| DC2 | Agenten-Tool für den Bugtracker | macht den Claim/Lease-Workflow des Deploymentcenters nutzbar | | R4/R5 | 📋 | Zeitumstellung Oktober (feuert genau einmal) und März (wird nicht übersprungen) |
| 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` | | 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 |
| 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.22.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.
--- ---
## COffen aus dem Finanz-/Analyse-Konzept ## 4Ideenspeicher
Punkte 12 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) | | **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 |
| C2 | `Indicators`-Tool — deterministische Berechnung | Qualität hoch, Tokens runter | | **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 |
| C3 | Datenaktualität erzwingen (`maxAgeSeconds`) | | | **Http** | Generisches REST-Tool mit Allowlist je Agent | `DirectAPI` ist fest auf Finanz-Provider verdrahtet — jede neue API erfordert heute Code |
| C4 | Termine & Fundamentaldaten (Earnings, EDGAR, Wirtschaftskalender) | | | **Shell** | Sandboxed, mit Kommando-Allowlist | Ersetzt die hartcodierten yt-dlp/ffmpeg-Aufrufe |
| C5 | Bestandsregister (Positionen) | Grundlage für C7/C8 | | **Git** | Für den „Senior Developer"-Agenten | |
| C6 | Nachrichten-Entdopplung (`SeenItems`) | | | **Vision** | Charts und Screenshots analysieren | |
| C7 | Ergebnisregister (Stufe 2, „Kosten pro Ergebnis") | fällt weitgehend aus den A3-Receipts ab | | ~~Notify~~ | — | **Gestrichen**, geht in A5 auf |
| C8 | Falsifizierbare Aussagen + Auflösung, Brier-Score (Stufe 3) | braucht C5, C7 und einen Auflösungs-Task (A1) |
### 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 |
--- ---
## DToolkandidaten (unbeschlossen) ## 5Erledigt
WebSearch, Http (generisch mit Allowlist), Shell (sandboxed), Git, Vision. Damit die Chronik nicht mit den alten Papieren verschwindet.
Notify ist gestrichen — geht in A5 auf.
**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 | | ✅ 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 |
| ✅ | A3 Audit-Log | klein, sofort nützlich; musste vor A2 da sein, damit Freigaben protokolliert werden | | ✅ 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 |
| **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 | | Freigabe-Ansicht | 4.6 | Reine Oberflächenarbeit gegen eine fertige API |
| 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 | | Delegationstiefe (B8) | ⚠️ **mit Vorsicht** | Fasst das Agent-Gate an, an dem schon ein Deadlock lauerte. Erst Invarianten festlegen, dann bauen, Test A13 zwingend |
| 3 | A5 entscheiden: Matrix oder Rocket.Chat | Blockiert K4 (Streaming) und färbt auf A6 ab. Entscheidung, keine Umsetzung — deshalb früh | | Output-Scrubbing | 4.6 | Ein zentraler Filter an `ExecuteToolCallAsync`, Werte aus dem Secret-Register |
| 4 | C1 Marktkalender | spart sofort Kosten; nutzt A1-Frontmatter | | A4 Skills | 4.6 | `FileSystemWatcher` mit Debounce (~500 ms); agentengeschriebene Skills erst nach Freigabe aktiv |
| 5 | A4 Skills/Toolsets | Token-Hebel, Cache-stabil | | Memory-Flush vor Compaction | 4.6 mit Anleitung | Der `ContextCompactor` hatte B1/B14 — die bestehenden Paarungs-Tests müssen unverändert grün bleiben |
| 6 | C2 Indicators | Qualität + Kosten | | Historie-Umzug + FTS5 | 4.6 | Migration nur nach frischem Backup; alte JSON erst nach verifiziertem Import löschen |
| 7 | C7 + C8 Ergebnisregister, Aussagen | das eigentliche Leistungsmaß; braucht A3 | | A6 MySQL-Spiegel | 4.6 mit Anleitung | Outbox mit Wasserzeichen, idempotente Upserts, nie blockieren. **Der getestete Restore-Pfad ist Teil der Definition of Done** |
| — | DC1 „Fehler melden"-Schaltfläche | zwischendurch; der Client steht, es fehlt der Knopf | | C1, C2 | 4.6 | Reine Fachlogik, deterministisch testbar |
| — | 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 |
Leitlinie der Reihung: erst Nachvollziehbarkeit und Kontrolle (Audit, Staging), Generell: Neue Subsysteme kommen mit Tests nach der [Teststrategie](Teststrategie.md).
dann Fähigkeiten — ein Agent, der unbeaufsichtigt läuft, braucht zuerst Bremsen, Bei den markierten Punkten sind die Invarianten-Tests kein Nice-to-have, sondern die
dann PS. 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 ### Weiter gültig — Baupläne
machbar, sofern die hier notierten Vorgaben mitgegeben werden.
> Die beiden hier markierten Stellen sind inzwischen gebaut: Der **Scanner-Kern** Aus der Roadmap verlinkt. Wer einen Punkt anfasst, liest das zugehörige Dokument.
> (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.
| Vorhaben | Einstufung | Vorgabe / Begründung | | Dokument | Wofür |
|---|---|---| |---|---|
| A1: Dateiformat, Frontmatter-Parsing, `task_*`-Tool, Migration | 4.6 | klar spezifizierbar, gut testbar | | [Taskboard-Konzept](Taskboard-Konzept.md) | Dateiformat, Wahrheitsaufteilung Datei/DB, Scanner-Verhalten, Invarianten |
| 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") | | [Audit-Konzept](Audit-Konzept.md) | Schema, Provenance-Regeln, Receipts |
| A2: Gate, Policy, Staging-Queue, Review-UI, Approval-Records | 4.6 | mit der folgenden Architektur-Vorgabe | | [Staging-Konzept](Staging-Konzept.md) | Policy-Auflösung, Plan-Freeze, Fortsetzung nach Freigabe — **Bauplan für Punkt #1** |
| 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 | | [Memory-Konzept](Memory-Konzept.md) | Modell, Schlüssel-Semantik, Abrufreihenfolge |
| A3: Audit-Log + Receipts | 4.6 | append-only, klares Schema, keine Nebenläufigkeitsfallen | | [Agentenkommunikation-Konzept](Agentenkommunikation-Konzept.md) | Fünf Phasen, Korrelation, Nachrichtenspeicher |
| A4: Skills | 4.6 | `FileSystemWatcher` mit Debounce (~500 ms); agentengeschriebene Skills erst nach Freigabe aktiv (siehe A4) | | [RocketChat-Nextcloud-Konzept](RocketChat-Nextcloud-Konzept.md) | Rocket.Chat gebaut; Nextcloud, Rückweg und `ChannelRouter` offen. Enthält die Messung gegen die echte Instanz |
| Memory-Flush vor Compaction | 4.6 mit Anleitung | Harte Grenzen: max. 35 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 | | [Deploymentcenter-Integration](Deploymentcenter-Integration.md) | Wie Heartbeat, Fehler-Stream, Bugtracker und Updates verdrahtet sind |
| Memory-Auto-Injection | 4.6 | in die Nutzernachricht, nie in den System-Prompt (sonst verfällt der Prompt-Cache T1); Deckel ~200 Tokens | | [umsetzungsplaene/](umsetzungsplaene/) | Vier Detailpläne: FileRW-Papierkorb, AgentInspector, AgentEditor-Härtung, WebSearch |
| 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 |
Generell: Neue Subsysteme (Scanner, Staging, Audit, Replikator) kommen mit Tests ### Weiter gültig — Handbücher
nach der [Teststrategie](Teststrategie.md) — die Invarianten-Tests sind bei den
markierten Punkten kein Nice-to-have, sondern die Absicherung dafür, dass ein | Dokument | Wofür |
schwächeres Modell sie umsetzen darf. |---|---|
| [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` | S1S7, B1B14, K1K6, T1T9, F-A1…F-A7 — erledigte in Abschnitt 5, offene in 3.1/3.2/3.7 |
| `Konzepte-Backup-Finanz-Analyse.md` | Backup ✅; Finanzteil als C1C6; 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 |
+7 -2
View File
@@ -1,5 +1,10 @@
# Taskboard — Aufgaben statt Delay-Schleifen # 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 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) 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, 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 Heute gibt es zwei getrennte, je für sich unzureichende Wege, einen Agenten Arbeit
tun zu lassen: tun zu lassen:
- **Der Cron-Scheduler** ([`AgentScheduler`](../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs), - **Der Cron-Scheduler** (`AgentScheduler`, `ToolJobScheduler` — beide inzwischen
[`ToolJobScheduler`](../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs)) hängt starr gelöscht, siehe unten) hing starr
am Agenten: eine Cron-Zeile je Agent, ausgeführt über ein `Task.Delay` bis zum 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). 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 Cron läuft in Lokalzeit ohne explizite Zone (B7). Ob mit oder ohne Kontext gelaufen
+5 -4
View File
@@ -1,6 +1,6 @@
# ClawdDotNet — Teststrategie # 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) Ziel: Fehlerklassen wie B1 (Compaction zerstört tool_call-Paarung) und B2 (Race Condition)
strukturell unmöglich machen, statt sie im Betrieb zu entdecken. strukturell unmöglich machen, statt sie im Betrieb zu entdecken.
@@ -61,9 +61,10 @@ internal sealed class FakeChatClient : IChatCompletionClient
### R2 — `TimeProvider` statt `DateTime.Now` ### R2 — `TimeProvider` statt `DateTime.Now`
.NET 10 bringt `TimeProvider` mit; `FakeTimeProvider` steckt in .NET 10 bringt `TimeProvider` mit; `FakeTimeProvider` steckt in
`Microsoft.Extensions.TimeProvider.Testing`. Betrifft `Microsoft.Extensions.TimeProvider.Testing`. Betrifft
[`CronExpression.cs:53`](../src/ClawdDotNet.Core/Scheduling/CronExpression.cs#L53), [`CronExpression.cs:53`](../src/ClawdDotNet.Core/Scheduling/CronExpression.cs#L53) und den
[`AgentScheduler.cs:75`](../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs#L75), [`TaskScanner`](../src/ClawdDotNet.Core/Tasks/TaskScanner.cs). (Die ursprünglich hier
[`ToolJobScheduler.cs:111`](../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs#L111). genannten `AgentScheduler` und `ToolJobScheduler` sind gelöscht — der Scanner hat sie
abgelöst.)
Damit werden Zeitumstellungs- und Langzeit-Tests deterministisch und laufen in Millisekunden Damit werden Zeitumstellungs- und Langzeit-Tests deterministisch und laufen in Millisekunden
statt in Echtzeit. statt in Echtzeit.
@@ -4,7 +4,7 @@ Vollständiges Review von Core-Engine, Security-Layer, Tools, Scheduling und UI.
Stand: Commit `92e50d3`. Stand: Commit `92e50d3`.
> **Dies ist ein datierter Befund, keine Todoliste.** Er wird nicht fortgeschrieben. > **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- > erledigt wurde. Die Abschnitte zur Oberfläche beziehen sich auf die Windows-Forms-
> Fassung, die es seit dem 2026-08-23 nicht mehr gibt. > 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) ## 1. Kritische Sicherheitslücken (P0)
### S1 — DatabaseTool: Tabellen-Whitelist ist vollständig umgehbar ### 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 ```csharp
return allowed.Any(t => t != null && inputLower.Contains(t)); 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. Die `users`-Tabelle wird gelöscht. Gleiches gilt für jede beliebige andere Tabelle.
Zusätzlich: 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'` sind ebenfalls Substring-Prüfungen → False Positives (`SELECT * FROM prices WHERE note='update'`
wird als Schreibzugriff blockiert). wird als Schreibzugriff blockiert).
- Mehrere Statements pro Aufruf sind nicht unterbunden (`;`-Verkettung). - 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. schwer abzusichern.
### S2 — SocialMediaManager: Kommando-Injection über yt-dlp ### 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 ```csharp
var psi = new ProcessStartInfo(ytDlpPath, $"--print \"%(id)s\" --playlist-end 1 {channelUrl}") 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. vor dem URL-Argument setzen.
### S3 — DirectAPI: API-Keys landen im Modell-Kontext ### 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 ```csharp
var url = $"https://api.twelvedata.com/quote?symbol={symbol}&apikey={apiKey}"; 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). grundsätzlich eine bereinigte URL zurückgeben (Query-String entfernen oder `apikey` maskieren).
### S4 — PermissionGate ist faktisch wirkungslos ### 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 ```csharp
public bool IsAllowed(string agentId, string toolName, AgentConfig agentConfig) 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). Approval-Hook für irreversible Aktionen (siehe F-A1).
### S5 — WebFetch: kein SSRF-Schutz bei Redirects ### 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 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/`, Redirects standardmäßig — eine erlaubte Domain kann auf `http://169.254.169.254/`,
`http://localhost:8418/` (dein Gitea!) oder beliebige interne Hosts weiterleiten. `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. ersetzt das Fragment überall im Hostnamen, nicht nur am Anfang.
**Fix:** `HttpClientHandler { AllowAutoRedirect = false }` und Redirects manuell auflösen, **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. (RFC1918, Loopback, Link-Local) hart blockieren.
### S6 — FileRW: Path-Traversal-Prüfung per Präfix ### 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 ```csharp
if (!fullPath.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase)) if (!fullPath.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase))
@@ -133,7 +133,7 @@ ausnutzbar, aber eine Zeitbombe.
### S7 — Secrets im Klartext ### S7 — Secrets im Klartext
`openRouterApiKey`, DB-`connectionString` (mit Passwort), Mail-`password`, Telegram-`password2FA` `openRouterApiKey`, DB-`connectionString` (mit Passwort), Mail-`password`, Telegram-`password2FA`
liegen unverschlüsselt in `AgentSettings.json` / `InstanceConfig.json` 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, **Fix:** DPAPI (`ProtectedData.Protect` mit `CurrentUser`-Scope) für alle Secret-Felder,
oder Windows Credential Manager. Zumindest sollten die Felder beim Speichern verschlüsselt 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) ## 2. Bugs (P1)
### B1 — ContextCompactor zerstört die tool_call-Paarung ⚠️ ### 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 ```csharp
var tail = messages.Skip(Math.Max(0, messages.Count - ProtectedTailMessages)).ToList(); 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. `assistant` mit `tool_calls` am Ende immer seine vollständigen `tool`-Antworten behalten.
### B2 — Race Condition auf dem geteilten Chat-Kontext ⚠️ ### 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<ChatMessage>`. Nur der *Lookup* läuft unter `_chatContexts[agentId]` ist eine geteilte `List<ChatMessage>`. Nur der *Lookup* läuft unter
`_lock` — alle `messages.Add(...)` im Loop passieren ungeschützt. `_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. (der laufende Chat hält es bereits) — wird jetzt abgelehnt.
### B3 — `maxTokens` vermischt Abrechnungs-Budget und Kontextgröße ⚠️ ### B3 — `maxTokens` vermischt Abrechnungs-Budget und Kontextgröße ⚠️
[`LoopGuard.cs:22`](../src/ClawdDotNet.Core/Engine/LoopGuard.cs#L22), Defaults in [`LoopGuard.cs:22`](../../src/ClawdDotNet.Core/Engine/LoopGuard.cs#L22), Defaults in
[`AgentConfig.cs:105`](../src/ClawdDotNet.Core/Config/AgentConfig.cs#L105) [`AgentConfig.cs:105`](../../src/ClawdDotNet.Core/Config/AgentConfig.cs#L105)
`RecordTokens` summiert `response.Usage.TotalTokens` über alle Schritte. Da jeder Schritt den `RecordTokens` summiert `response.Usage.TotalTokens` über alle Schritte. Da jeder Schritt den
**kompletten** Kontext erneut sendet, wächst diese Summe quadratisch: **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. und beide getrennt im UI ausweisen.
### B4 — Kostenanzeige ist doppelt falsch ### B4 — Kostenanzeige ist doppelt falsch
[`frm_main.cs:292`](../frm_main.cs#L292) [`frm_main.cs:292`](../../frm_main.cs#L292)
```csharp ```csharp
_statusService?.RecordUsage(model, result.TokensUsed / 2, result.TokensUsed / 2); _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. 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 2. **Modell fehlt in der Preistabelle**: `AgentConfig.Model` hat den Default
`anthropic/claude-sonnet-4-5` — dieser Eintrag existiert in `ModelPricing` `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. `CalculateCost` gibt dann stillschweigend `0` zurück.
Die Tabelle ist zudem veraltet (`claude-sonnet-4`, `claude-opus-4`, `claude-haiku-4.5`). 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 ### B5 — Tool-Ergebnisse landen ungekappt im Kontext
Ein einziger `WebFetch` mit dem Default `maxResponseKb: 512` 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` 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. `Database.query` und `Mail.read_inbox` ebenfalls nicht.
Gekürzt wird erst nachträglich in der Compaction — und dort nur außerhalb der letzten 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. 6 Nachrichten. Der teure Request ist zu dem Zeitpunkt längst bezahlt.
**Fix:** Kappung beim Einfügen in `ExecuteToolCallAsync` **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 Tools, mit konfigurierbarem `maxToolResultTokens` und einem Hinweis an das Modell, dass gekürzt
wurde (inkl. Angebot, gezielt nachzulesen). wurde (inkl. Angebot, gezielt nachzulesen).
### B6 — `Task.Delay` wirft bei langen Cron-Intervallen ### B6 — `Task.Delay` wirft bei langen Cron-Intervallen
[`AgentScheduler.cs:89`](../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs#L89) und [`AgentScheduler.cs:89`](../../src/ClawdDotNet.Core/Scheduling/AgentScheduler.cs#L89) und
[`ToolJobScheduler.cs:126`](../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs#L126) [`ToolJobScheduler.cs:126`](../../src/ClawdDotNet.Core/Scheduling/ToolJobScheduler.cs#L126)
`Task.Delay` wirft `ArgumentOutOfRangeException` bei Werten über ~24,8 Tagen. Ein jährlicher `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 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. Scheduler-Tasks mit einem `ContinueWith`-Fehler-Logger versehen.
### B7 — Cron rechnet in Lokalzeit ### 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. `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` **Fix:** Intern in UTC rechnen und nur für die Anzeige konvertieren, oder `TimeZoneInfo`
explizit berücksichtigen. explizit berücksichtigen.
### B8 — Keine Rekursionsbremse bei AgentComm / AgentSpawn ### 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 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 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. den Aufrufpfad zur Zyklenerkennung mitgeben.
### B9 — `index_Count` liest die Datei außerhalb des Locks erneut ### B9 — `index_Count` liest die Datei außerhalb des Locks erneut
[`FileRWTool.cs:569`](../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L569) ruft [`FileRWTool.cs:569`](../../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L569) ruft
[`index_Count`](../src/ClawdDotNet.Tools.FileRW/FileRWTool.cs#L572) auf, nachdem das Lock [`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 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 vollständiges Parsen der Index-Datei. Der Zähler ist innerhalb des Locks ohnehin bekannt
(`index.Count`). (`index.Count`).
### B10 — `PersistChatState` schreibt bei jedem Eintrag alles neu ### 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 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 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`. `WriteIndented = false`.
### B11 — Kein `max_tokens` im Request ### 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 `ChatRequest.MaxTokens` nie. Ein Modell kann in einem Schritt sein volles Output-Limit
ausschöpfen. ausschöpfen.
### B12 — Kein Retry/Backoff ### 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 Nicht-2xx sofort. Ein einzelnes HTTP 429 killt einen kompletten geplanten Run. Bei OpenRouter
sind 429/502/503 im Normalbetrieb zu erwarten. sind 429/502/503 im Normalbetrieb zu erwarten.
**Fix:** Polly o.ä. mit exponentiellem Backoff + Jitter für 429/5xx, `Retry-After` respektieren. **Fix:** Polly o.ä. mit exponentiellem Backoff + Jitter für 429/5xx, `Retry-After` respektieren.
### B14 — Compaction dupliziert den System-Prompt bei kurzen Konversationen ⚠️ ### 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.* *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 ### K1 — Geplante Agenten haben kein Gedächtnis
`RunAsync` baut bei jedem Cron-Tick eine frische Nachrichtenliste `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, 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. zieht dieselben Schlüsse und kann keine Entwicklung über Zeit verfolgen.
@@ -375,7 +375,7 @@ Erste Kandidaten: `CronExpression`, `ContextCompactor` (Paarungs-Invarianten!),
`FileRWTool`-Pfadprüfungen. `FileRWTool`-Pfadprüfungen.
### K4 — Kein Streaming ### 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. Bei langen Antworten wirkt die UI eingefroren; es gibt nur den Typing-Indicator.
### K5 — Kein Kostenlimit ### K5 — Kein Kostenlimit
@@ -410,7 +410,7 @@ Input-Tokens kosten nur ~10 % des Normalpreises (Schreiben in den Cache kostet e
Umsetzung: Umsetzung:
1. `ChatMessage.Content` muss das Array-Format unterstützen 1. `ChatMessage.Content` muss das Array-Format unterstützen
(`[{ "type": "text", "text": "...", "cache_control": { "type": "ephemeral" } }]`). (`[{ "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. 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). 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. 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`). 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) ★★ ### 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. `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. 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 ★★ ### T4 — Proaktiv statt reaktiv kompaktieren ★★
`CompactIfNeededAsync` läuft **nach** dem API-Call `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. `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 **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 ★ ### T6 — Tool-Definitionen verschlanken ★
Die Beschreibungen sind großzügig: `FileRW` allein hat ~500 Zeichen Description plus ein Die Beschreibungen sind großzügig: `FileRW` allein hat ~500 Zeichen Description plus ein
Schema mit 11 Properties ≈ 900 Tokens 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 46k Tokens — bei **jedem** Schritt (ohne Caching). Tools sind das schnell 46k Tokens — bei **jedem** Schritt (ohne Caching).
Maßnahmen: Maßnahmen:
@@ -458,7 +458,7 @@ Maßnahmen:
- Für Agenten mit vielen Tools: zweistufiges Laden (`list_toolsets``load_toolset`). - Für Agenten mit vielen Tools: zweistufiges Laden (`list_toolsets``load_toolset`).
### T7 — `RunAsync` statt `ChatAsync` für Job-Wakeups prüfen ★ ### 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) 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` 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. 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** **F-A4 — Run-Historie**
`AgentRunResult` wird aktuell nur im Speicher als "letztes Ergebnis" gehalten `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 Persistierte Runs (mit Schritten, Tokens, Kosten, Fehlern) wären die Grundlage für Diagnose
und Kostenanalyse. und Kostenanalyse.
@@ -528,7 +528,7 @@ Siehe K3.
## 6. Vorgeschlagene Reihenfolge ## 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 > werden dort weitergeführt; dieser Abschnitt bleibt als Stand der Bestandsaufnahme
> eingefroren. F-A1/S4, F-A2, F-A5, T6, T7 sowie B6B8 sind in den Roadmap-Vorhaben > eingefroren. F-A1/S4, F-A2, F-A5, T6, T7 sowie B6B8 sind in den Roadmap-Vorhaben
> A1A4 aufgegangen. > A1A4 aufgegangen.
@@ -1,6 +1,6 @@
# Deploymentcenter 2.2 2.4: Was noch zu tun ist # 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. (dort steht der Stand nach 2.1) um die drei neuen Ausbaustufen.
| Fassung | Was dazukam | Betrifft uns | | 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), - 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 - **`ftpRemoteBaseDir` ist `/releases`**, nicht `/public_html/releases` wie in der
Packager-Vorlage: Auf diesem Server liegt die Release-Ablage auf der FTP-Wurzel. 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` - 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 Deploymentcenter-Projektbaum in die FTP-Wurzel und hat mit dem Veröffentlichen eines
Anwendungspakets nichts zu tun. Anwendungspakets nichts zu tun.
- Die Versionsgegenprobe des Packagers greift und passt: `<Version>` aus - Die Versionsgegenprobe des Packagers greift und passt: `<Version>` 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`. 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 (`%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 nicht überschreiben. Zu prüfen bleibt nur, dass keine leeren Arbeitsordner ins Paket
wandern — die `CreateWorkingDirectories`-Targets in 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. 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 Aus dem Hinweis ist eine Rückfrage geworden („Jetzt installieren" / „Später"), die den
`update-agent` startet. Umgesetzt in `update-agent` startet. Umgesetzt in
[`DeploymentcenterService.StartUpdate`](../src/ClawdDotNet.App/Services/DeploymentcenterService.cs) [`DeploymentcenterService.StartUpdate`](../../src/ClawdDotNet.App/Services/DeploymentcenterService.cs)
und `App.StartUpdateAsync`. und `App.StartUpdateAsync`.
### Der Agent wird mitgeliefert — er muss es ### 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 Anwendung. Ohne Mitliefern fände die Anwendung nie einen Agenten und könnte sich nicht
aktualisieren. 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 `/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 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. 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`, Das Deploymentcenter hat daraufhin `location` am Ziel ergänzt (`install`, `config`,
`data`, `home`) samt Variablenersetzung in `file`. Damit ist der Weg frei; `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`. Ausgabeverzeichnis kopiert, landet also im Paket neben der `manifest.json`.
### Der Ordnername ist bewusst kleingeschrieben ### 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 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- Installer (`detect:baseurl`). Damit entfällt der Absatz „bis die Avalonia-Einstellungs-
ansicht steht, von Hand in `Settings.json`" aus der 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. installierte Systeme.
Der Installer schreibt Lizenzschlüssel und Token **im Klartext**; er kennt unsere Der Installer schreibt Lizenzschlüssel und Token **im Klartext**; er kennt unsere
@@ -2,7 +2,7 @@
> **Nachtrag 2026-08-08 — die Anbindung ist umgestellt, Server und SDK stehen auf 2.1.** > **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 > 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 > Mit **SDK 2.1 erledigt** (waren Befunde aus Abschnitt 3 bzw. aus der Durchsicht der
> 2.0-Anbindung): > 2.0-Anbindung):
@@ -48,7 +48,7 @@ Punkte aus derselben Durchsicht — drei davon würden beim Ausrollen wehtun.
| Punkt aus dem Vorschlag | Umsetzung | | Punkt aus dem Vorschlag | Umsetzung |
|---|---| |---|---|
| Format `2:<plattform>:<hex>` | [HardwareId.cs:125](../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/HardwareId.cs) | | Format `2:<plattform>:<hex>` | [HardwareId.cs:125](../../../Deploymentcenter/client-dotnet/Deploymentcenter.Client/HardwareId.cs) |
| **Kein `MachineName` im Hash** | `ComputeV2Hash`, `:138` — der wichtigste Punkt, sauber umgesetzt | | **Kein `MachineName` im Hash** | `ComputeV2Hash`, `:138` — der wichtigste Punkt, sauber umgesetzt |
| Quellenkette Windows/Linux | `:42107`, inklusive `dmi-uuid` | | Quellenkette Windows/Linux | `:42107`, inklusive `dmi-uuid` |
| `IsPlausibleMachineId` (Länge, `uninitialized`, nur Nullen) | `:161` | | `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` | | Erweiterte Stoppwortliste | `:23` — inkl. `br-`, `virbr`, `cni`, `cali` |
| `machine.key` mit `0600` | `:290`, `SetUnixPermissions` mit `#if NET8_0_OR_GREATER` | | `machine.key` mit `0600` | `:290`, `SetUnixPermissions` mit `#if NET8_0_OR_GREATER` |
| Vorgabe per Umgebungsvariable | `LicenseConfig.HardwareIdOverride`, beide Namen | | 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 | | 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 | | `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 | | Schema `hwid_version`/`hwid_source`/`platform` | `sql/migrations/v2_hardware_id.sql`, rückwärtskompatibel |
| Verwaltungsansicht zeigt Quelle/Plattform | `public/index.php:1227` | | 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 ### 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 ```csharp
string status = root.TryGetProperty("status", out var sProp) ? sProp.GetString() ?? "unknown" : "unknown"; 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 auslösen, weil der Client eine andere v1-ID berechnet als die, die in der
Datenbank steht. 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 ```csharp
rawBuilder.Append(machineId); // MachineGuid, sonst MAC rawBuilder.Append(machineId); // MachineGuid, sonst MAC
@@ -143,7 +143,7 @@ rawBuilder.Append(Environment.MachineName); // direkt angehängt, kein Tren
→ sha256(machineGuid + machineName) → 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 ```csharp
string raw = $"{Environment.MachineName}:{firstMac}"; 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 ### 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": „Legacy Migration Check":
```csharp ```csharp
@@ -217,7 +217,7 @@ und ist als Cache wertlos.
nichts. Alte Cachedateien sollen verworfen werden — eine einmalige nichts. Alte Cachedateien sollen verworfen werden — eine einmalige
Online-Prüfung ist der ganze Preis. 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 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, Funktion — entweder mit einem HMAC über die übrigen Felder füllen oder entfernen,
damit niemand später Schutz vermutet, wo keiner ist. damit niemand später Schutz vermutet, wo keiner ist.
@@ -228,7 +228,7 @@ damit niemand später Schutz vermutet, wo keiner ist.
| Fundstelle | Sache | | 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". | | `: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. | | `: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. | | `: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). | | [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. | | 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). | | [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). |
--- ---
@@ -57,8 +57,8 @@ Abhängigkeit.
## Problem 3: JSON-Dateien werden nicht atomar geschrieben ⚠️ ## Problem 3: JSON-Dateien werden nicht atomar geschrieben ⚠️
Alle Schreibvorgänge laufen über `File.WriteAllText` Alle Schreibvorgänge laufen über `File.WriteAllText`
([InstanceDirectoryManager.cs:439](../Services/InstanceDirectoryManager.cs#L439), ([InstanceDirectoryManager.cs:439](../../Services/InstanceDirectoryManager.cs#L439),
[AgentEngine.cs:783](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L783)). Ein Absturz [AgentEngine.cs:783](../../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L783)). Ein Absturz
oder Stromausfall mitten im Schreiben hinterlässt eine abgeschnittene Datei. oder Stromausfall mitten im Schreiben hinterlässt eine abgeschnittene Datei.
**Das ist bereits passiert:** In der Instanz `TradingTeam` liegt eine **Das ist bereits passiert:** In der Instanz `TradingTeam` liegt eine
@@ -278,7 +278,7 @@ Rohzahlen.
# Vorgeschlagene Reihenfolge # 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 C1C8 weiter; S4 + K2 sind in den Vorhaben A2/A3 > laufen dort als C1C8 weiter; S4 + K2 sind in den Vorhaben A2/A3
> (Staging-Freigabe, Audit-Log) aufgegangen. > (Staging-Freigabe, Audit-Log) aufgegangen.
@@ -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 5080 PT oben gehört zum Trading-Teil, nicht zum Linux-Umzug, und ist in den 5080 PT oben
nicht enthalten. Wenn die Kursansichten kommen, sind dafür grob 510 PT nicht enthalten. Wenn die Kursansichten kommen, sind dafür grob 510 PT
zusätzlich zu rechnen. Das passt zu dem, was in 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. festgehalten ist: Erst die Basis, dann die Handelsansichten.
Ein Punkt, der jetzt schon zählt: LiveCharts2 setzt auf SkiaSharp, genau wie Ein Punkt, der jetzt schon zählt: LiveCharts2 setzt auf SkiaSharp, genau wie
@@ -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 ### 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 ```csharp
rawBuilder.Append(Environment.MachineName); // "for system isolation" 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 Die Absicht („system isolation") ist auch nicht erfüllt: Der Rechnername steht
ohnehin im Feld `hostname`, das der Server bei jeder Prüfung mitschreibt 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. Diagnostisch verlieren wir nichts, wenn er aus dem Hash verschwindet.
### 1.2 Die MAC-Ausweichlösung ist unter Linux instabil ### 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: nimmt die alphabetisch erste physische MAC. Unter Linux:
- Die Stoppwortliste kennt `docker` und `veth`, aber **nicht** `br-` (Bridges), - 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 ### 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: beim Lesen und `:90` beim Schreiben:
```csharp ```csharp
@@ -63,17 +63,17 @@ Folgen:
- `SECURITY.md` behauptet, der Cache sei „strikt an die `hardware_id` gebunden". - `SECURITY.md` behauptet, der Cache sei „strikt an die `hardware_id` gebunden".
Das stimmt für die *Hülle* (die Prüfung in 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. nicht für die Cache-Datei selbst.
- Ernster: `max_seen_time` ist die Uhr-Rückdreh-Sperre - 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 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, die Systemuhr zurück. Der Klartext-Rückfall beim **Lesen** macht das möglich,
und zwar auf jeder Plattform, auf der DPAPI nicht greift. und zwar auf jeder Plattform, auf der DPAPI nicht greift.
### 1.4 Ablageort bricht bei einem systemd-Dienst weg ### 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 verwendet `Environment.GetFolderPath(SpecialFolder.ApplicationData)`. Läuft der
Dienst unter `User=clawd` ohne Heimatverzeichnis, ist `HOME` nicht gesetzt und Dienst unter `User=clawd` ohne Heimatverzeichnis, ist `HOME` nicht gesetzt und
`GetFolderPath` liefert einen **leeren String**. `Path.Combine("", slug, `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 **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 = <v2> suchen 1. Aktivierung mit hardware_id = <v2> suchen
@@ -281,7 +281,7 @@ Veröffentlichungen) aus dem Client fallen.
Nicht übersehen: Die Hardware-ID geht in zwei weitere Berechnungen ein — Nicht übersehen: Die Hardware-ID geht in zwei weitere Berechnungen ein —
`CalculateHmac(state, licenseKey, _hardwareId)` für die Prüfsumme in `CalculateHmac(state, licenseKey, _hardwareId)` für die Prüfsumme in
`LicenseResult` `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 und den Seed des Speicherschutzes (`:287`). Nach dem Formatwechsel schlägt
`VerifyChecksum` für jede zwischengespeicherte Hülle fehl. `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) ### 5.2 Abmelden vor dem Umzug (existiert, aber nicht erreichbar)
`LicenseService::deactivate` löscht die Aktivierungszeile und gibt den Platz frei `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 und `LicenseClient.DeactivateAsync` ruft es auf. In ClawdDotNet ist die Methode
aber nur über [LicenseGate.cs:39](Services/LicenseGate.cs) erreichbar und dort aber nur über [LicenseGate.cs:39](Services/LicenseGate.cs) erreichbar und dort
an die GUI gebunden. an die GUI gebunden.
+34 -20
View File
@@ -1,27 +1,41 @@
# Archiv # Archiv
Die vier Dokumente hier sind die **Entwicklungs-Prompts aus der Anfangszeit** des Was hier liegt, ist **abgeschlossen und wird nicht mehr fortgeschrieben.** Der aktuelle
Projekts (MaiJuli 2026). Sie haben ClawdDotNet aufgebaut und beschreiben deshalb Stand steht ausschließlich in der [Roadmap](../Roadmap.md); ihr Abschnitt 7 hält fest,
den Stand von damals — unter anderem eine WinForms-Oberfläche mit WebView2, die es was aus jedem dieser Dokumente dorthin übernommen wurde.
seit dem Frühjahrsputz vom 2026-08-23 nicht mehr gibt.
**Sie werden nicht mehr fortgeschrieben.** Wer den heutigen Stand sucht, findet ihn Aufgehoben werden sie, weil sie die **Begründung** tragen: warum das System so
in [Roadmap](../Roadmap.md), [Bestandsaufnahme](../Bestandsaufnahme-2026-07.md) und geschnitten ist, wie es geschnitten ist, und welche Befunde die Entscheidungen geformt
den Konzept-Dokumenten daneben. 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 S1S7, B1B14, K1K6, T1T9, 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 C1C8 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
MaiJuli 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_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.md` | WinForms-Oberfläche mit WebView2-Chat | nichts — ersetzt durch `src/ClawdDotNet.Desktop` | | [ClawdDotNet_Prompt_WebviewChatWinForms](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_TelegramClient](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_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 |
@@ -1,5 +1,9 @@
# Umsetzungsplan: AgentEditor härten (Personalverwaltung) # 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 > Stand: 2026-08-05
> Ziel: Änderungen an Identity und Soul im laufenden Betrieb bleiben möglich, > Ziel: Änderungen an Identity und Soul im laufenden Betrieb bleiben möglich,
> werden aber freigabepflichtig, nachvollziehbar und rücknehmbar. > werden aber freigabepflichtig, nachvollziehbar und rücknehmbar.
@@ -1,5 +1,8 @@
# Umsetzungsplan: AgentInspector (Supervisor-Einsicht) # 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 > Stand: 2026-08-05
> Ziel: Ein Supervisor-Agent kann beurteilen, ob die anderen Agenten der Instanz > 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 > das tun, was sie tun sollen — über Audit-Log, Taskboard und lesenden Zugriff
@@ -1,5 +1,8 @@
# Umsetzungsplan: FileRW-Papierkorb + Cleanup-Job # 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 > Stand: 2026-08-05
> Ziel: `FileRW.delete` löscht nicht mehr endgültig, sondern verschiebt in einen > 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. > Papierkorb je Workspace. Ein Cron-Job räumt den Papierkorb nach X Tagen auf.
@@ -1,5 +1,9 @@
# Umsetzungsplan: WebSearch-Tool (Internetzugang erweitern) # 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 > Stand: 2026-08-05
> Ziel: Agenten können das Web durchsuchen, statt nur bekannte URLs abzurufen. > Ziel: Agenten können das Web durchsuchen, statt nur bekannte URLs abzurufen.
> Reihenfolge: **Zuletzt.** Größter Sicherheitshebel, deshalb erst nach > Reihenfolge: **Zuletzt.** Größter Sicherheitshebel, deshalb erst nach