Konfig- und Zustandsdateien atomar schreiben
File.WriteAllText kuerzt die Zieldatei zuerst auf null und fuellt sie dann. Bricht der Vorgang dazwischen ab, ist der alte Inhalt weg und der neue unvollstaendig. Das ist im Betrieb bereits eingetreten: In der Instanz TradingTeam lag eine TokenUsage.json.corrupt_..., die die Fehlerbehandlung beiseitegelegt hatte. Der Verbrauch bis dahin war verloren. AtomicFile schreibt in eine Nebendatei, erzwingt das Schreiben auf die Platte und ersetzt dann. Umgestellt sind ChatHistory, ChatContext, alle Instanz- und Agentenkonfigurationen, Identity und Soul, die App-Einstellungen sowie der Stock-Index. Zum Ersetzen wurde das Windows-Verhalten gemessen statt vermutet. Mit einem Leser, der die Zieldatei geoeffnet haelt: Freigabe des Lesers File.Move File.Replace Read scheitert scheitert ReadWrite scheitert scheitert ReadWrite | Delete scheitert funktioniert File.Move verlangt die Zieldatei exklusiv und scheitert deshalb immer, sobald jemand sie geoeffnet hat. Daher File.Replace — und ein Lesehelfer AtomicFile.ReadAllText, der das Loeschen freigibt, damit unsere eigenen Leser keinen Schreiber blockieren. Die Leser in InstanceDirectoryManager und beim Laden der Chatverlaeufe nutzen ihn jetzt. Zusaetzlich ein Schloss je Zieldatei: Zwei gleichzeitige Schreibvorgaenge auf dieselbe Datei sind ohnehin ein Rennen, ohne Serialisierung scheitern sie aber zusaetzlich mit "Zugriff verweigert". Fuer fremde Leser wie Virenscanner bleibt eine Wiederholung mit Wartezeit. 366 Tests gruen (218 Core, 148 Tools). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ef3e519f6c
commit
1157d28588
@@ -0,0 +1,292 @@
|
||||
# Drei Konzepte: Backup, Finanzumfeld, Leistungsanalyse
|
||||
|
||||
Diskussionsgrundlage, noch nicht umgesetzt.
|
||||
|
||||
---
|
||||
|
||||
# 1. Backup und Wiederherstellung
|
||||
|
||||
## Was überhaupt schützenswert ist
|
||||
|
||||
Nicht alles im Instanzverzeichnis ist gleich wertvoll. Entscheidend ist, was sich
|
||||
**nicht** wiederherstellen lässt:
|
||||
|
||||
| Was | Wert | Bemerkung |
|
||||
|---|---|---|
|
||||
| `Identity.md`, `Soul.md` | **hoch** | Die eigentliche Arbeit an einem Agenten |
|
||||
| `AgentSettings.json`, `InstanceSettings.json` | **hoch** | Tool-Zuweisungen, Budgets, Zugangsdaten |
|
||||
| `state.db` → Tabelle `Memories` | **hoch** | Das Langzeitgedächtnis — über Monate gewachsen |
|
||||
| `Workspace/`, `SharedWorkspace/` | hoch | Berichte, Wissensdatenbank |
|
||||
| `ChatHistory.json`, `ChatContext.json` | mittel | Laufender Arbeitsstand |
|
||||
| `state.db` → `RunUsage` | mittel | Kostenhistorie, Grundlage der Auswertung |
|
||||
| Telegram-Session | **hoch** | Ohne sie ist ein erneuter Login mit Code nötig |
|
||||
| `Logs/` | gering | Nachvollziehbarkeit, groß |
|
||||
| `bin/` | keiner | Wird gebaut |
|
||||
|
||||
## Problem 1: Verschlüsselte Zugangsdaten überleben den Rechner nicht ⚠️
|
||||
|
||||
Das ist eine direkte Folge von S7 und der wichtigste Punkt hier.
|
||||
|
||||
DPAPI verschlüsselt im Benutzerkontext — entschlüsseln kann nur derselbe
|
||||
Windows-Benutzer auf demselben Rechner. Ein Backup, das genau dann gebraucht wird,
|
||||
wenn der Rechner defekt ist, enthält damit **unbrauchbare Zugangsdaten**.
|
||||
|
||||
Ein Backup, das sich nicht auf einem anderen Rechner wiederherstellen lässt, erfüllt
|
||||
seinen Zweck nicht.
|
||||
|
||||
**Lösung:** Beim Backup werden Secrets umgeschlüsselt — von DPAPI auf eine
|
||||
Passphrase (PBKDF2 zur Schlüsselableitung, AES-GCM zur Verschlüsselung). Beim
|
||||
Wiederherstellen wird die Passphrase abgefragt und auf DPAPI des Zielrechners
|
||||
zurückgeschlüsselt.
|
||||
|
||||
Alternativ als bewusste Option: **Backup ohne Zugangsdaten**. Dann ist der Restore
|
||||
unvollständig, aber die Datei ist gefahrlos ablegbar — auch auf einem NAS oder in
|
||||
einer Cloud. Beide Varianten sollten anwählbar sein, mit deutlicher Kennzeichnung
|
||||
im Manifest.
|
||||
|
||||
## Problem 2: SQLite darf nicht einfach kopiert werden
|
||||
|
||||
Mit WAL (seit dem Speicher-Fundament aktiv) stehen die jüngsten Änderungen in
|
||||
`state.db-wal`, nicht in `state.db`. Wer nur die `.db` kopiert, sichert einen
|
||||
veralteten und womöglich inkonsistenten Stand.
|
||||
|
||||
**Richtig:** `VACUUM INTO 'ziel.db'` — erzeugt im laufenden Betrieb eine konsistente,
|
||||
in sich geschlossene Kopie. Ein einzelnes SQL-Kommando, keine zusätzliche
|
||||
Abhängigkeit.
|
||||
|
||||
## Problem 3: JSON-Dateien werden nicht atomar geschrieben ⚠️
|
||||
|
||||
Alle Schreibvorgänge laufen über `File.WriteAllText`
|
||||
([InstanceDirectoryManager.cs:439](../Services/InstanceDirectoryManager.cs#L439),
|
||||
[AgentEngine.cs:783](../src/ClawdDotNet.Core/Engine/AgentEngine.cs#L783)). Ein Absturz
|
||||
oder Stromausfall mitten im Schreiben hinterlässt eine abgeschnittene Datei.
|
||||
|
||||
**Das ist bereits passiert:** In der Instanz `TradingTeam` liegt eine
|
||||
`TokenUsage.json.corrupt_2026…` — die Fehlerbehandlung hat sie gesichert und neu
|
||||
angefangen. Der Verbrauch bis dahin war weg.
|
||||
|
||||
**Lösung:** In eine temporäre Datei daneben schreiben, dann `File.Replace` — das ist
|
||||
auf NTFS atomar. Gehört unabhängig vom Backup repariert.
|
||||
|
||||
## Vorschlag
|
||||
|
||||
Ein `BackupService`, der ein ZIP mit Manifest erzeugt:
|
||||
|
||||
```
|
||||
backup_Instance-TradingTeam_2026-07-28_1400.zip
|
||||
├── manifest.json ← Version, Zeitpunkt, Instanz, Prüfsummen,
|
||||
│ ob Zugangsdaten enthalten sind
|
||||
├── state.db ← via VACUUM INTO, konsistent
|
||||
├── InstanceSettings.json
|
||||
└── Agents/…
|
||||
```
|
||||
|
||||
Eigenschaften:
|
||||
|
||||
- **Planbar** über den vorhandenen ToolJob-Mechanismus (Cron) — kein neuer Scheduler.
|
||||
- **Rotation**: die letzten N behalten, plus je ein wöchentliches/monatliches.
|
||||
- **Restore mit Vorschau**: erst anzeigen, was überschrieben würde, dann bestätigen.
|
||||
- **Prüfsummen im Manifest**, damit ein beschädigtes Archiv beim Wiederherstellen
|
||||
auffällt und nicht erst danach.
|
||||
|
||||
**Der einzige Test, der zählt:** Backup erzeugen → in ein leeres Verzeichnis
|
||||
wiederherstellen → vergleichen. Ein ungeprüftes Restore ist kein Backup, sondern eine
|
||||
Vermutung. Dazu ein Test für den Rechnerwechsel: Backup mit Passphrase, DPAPI-Kontext
|
||||
simuliert anders, Restore muss funktionieren.
|
||||
|
||||
---
|
||||
|
||||
# 2. Was für das Finanzumfeld noch fehlt
|
||||
|
||||
Vorhanden: `DirectAPI` (Kurse, Krypto, Forex), `WebFetch`, `WebMonitor`,
|
||||
`SocialMediaManager` (X, YouTube-Transkripte), `Telegram`, `Mail`, `Database`,
|
||||
`FileRW` mit `stock_add`, seit neuem `Memory`.
|
||||
|
||||
Nach Wirkung sortiert:
|
||||
|
||||
## 2.1 Marktkalender — spart sofort Geld ★★★
|
||||
|
||||
Agenten wissen nicht, ob die Börse offen ist. Ein `*/30`-Cron läuft auch Sonntag um
|
||||
3 Uhr, ruft Kurse ab, analysiert Freitagsdaten und schreibt einen Bericht. Das kostet
|
||||
Tokens und erzeugt Scheinaktivität.
|
||||
|
||||
Zwei Bausteine:
|
||||
|
||||
- **Scheduler-Erweiterung** `onlyWhenMarketOpen: "NYSE"` bzw. `"XETRA"` — der Lauf
|
||||
wird schlicht übersprungen. Wirkt ohne Zutun des Modells.
|
||||
- **Tool `MarketCalendar`** für Fragen des Agenten: Ist heute Handelstag? Wann
|
||||
öffnet/schließt? Vor-/Nachbörse? Nächster Feiertag?
|
||||
|
||||
Handelskalender ändern sich selten und lassen sich als Datei pflegen — keine externe
|
||||
Abhängigkeit nötig.
|
||||
|
||||
## 2.2 Deterministische Berechnung ★★★
|
||||
|
||||
Sprachmodelle rechnen unzuverlässig. Indikatoren vom Modell schätzen zu lassen ist
|
||||
gleich doppelt schlecht: Das Ergebnis stimmt oft nicht, und die Zahlenkolonnen
|
||||
müssen dafür durch den Kontext.
|
||||
|
||||
Ein Tool `Indicators`, das im Code rechnet: gleitende Durchschnitte, RSI, ATR,
|
||||
Volatilität, prozentuale Veränderung, Korrelation, Drawdown, Positionsgröße nach
|
||||
Risiko. Der Agent bekommt Ergebnisse statt Rohdaten.
|
||||
|
||||
Spart Tokens **und** verbessert die Qualität — die seltene Kombination.
|
||||
|
||||
## 2.3 Datenaktualität erzwingen ★★
|
||||
|
||||
`DirectAPI` liefert brav `dataAsOf` mit, aber nichts wertet es aus. Ein Agent kann
|
||||
ungehindert auf drei Tage alten Kursen argumentieren.
|
||||
|
||||
Vorschlag: `maxAgeSeconds` in der Tool-Konfiguration. Überschrittene Daten werden
|
||||
entweder abgelehnt oder mit einem unübersehbaren Hinweis geliefert — nicht
|
||||
stillschweigend durchgereicht.
|
||||
|
||||
## 2.4 Termine und Fundamentaldaten ★★
|
||||
|
||||
Für „Finanznachrichten" ist der Kalender oft wichtiger als der Kurs: Was steht diese
|
||||
Woche an? Aktuell gibt es dazu nichts.
|
||||
|
||||
- Earnings-Termine, Dividenden, Splits
|
||||
- SEC EDGAR: Filings (8-K, 10-Q, 13F) — frei zugänglich, gut strukturiert
|
||||
- Wirtschaftstermine (Zinsentscheide, Inflationsdaten)
|
||||
|
||||
## 2.5 Bestandsregister ★★
|
||||
|
||||
`stock_add` ist eine Wissenssammlung, kein Bestand. Aussagen wie „Wie ist mein Risiko
|
||||
verteilt?" oder „Wie lief die Position seit Einstieg?" sind damit nicht möglich.
|
||||
|
||||
Eine eigene Tabelle mit Positionen (Symbol, Menge, Einstand, Datum, Notiz) — auch
|
||||
rein zur Beobachtung, ohne Handelsanbindung. Sie ist zugleich die Grundlage für die
|
||||
Leistungsmessung aus Teil 3.
|
||||
|
||||
## 2.6 Nachrichten-Entdopplung ★★
|
||||
|
||||
Dieselbe Meldung läuft über zehn Quellen. Ohne Abgleich zahlt man zehnmal, und der
|
||||
Agent hält es für zehn unabhängige Signale — was die Einschätzung systematisch
|
||||
verzerrt.
|
||||
|
||||
Eine `SeenItems`-Tabelle mit Prüfsumme über den normalisierten Titel plus
|
||||
Ähnlichkeitsabgleich. Passt gut zum vorhandenen Speicher-Fundament.
|
||||
|
||||
## 2.7 Prompt-Injection ist hier keine Theorie ★★★
|
||||
|
||||
Finanzinhalte auf X und in Newslettern sind genau der Ort, an dem gezielt manipuliert
|
||||
wird. Ein präparierter Beitrag kann einen Agenten steuern, der Mail versenden und
|
||||
posten darf. K2 aus der Bestandsaufnahme ist in diesem Umfeld die dringlichste
|
||||
Konzeptlücke.
|
||||
|
||||
Konkret: Tool-Ergebnisse als Daten rahmen, im System-Prompt verankern, dass daraus
|
||||
keine Anweisungen befolgt werden, und irreversible Aktionen an eine Freigabe koppeln.
|
||||
|
||||
## Abgrenzung
|
||||
|
||||
Was hier beschrieben ist, sind Recherche- und Analysewerkzeuge. Automatische
|
||||
**Orderausführung** wäre eine andere Kategorie mit eigenen Anforderungen (Broker-API,
|
||||
Fehlerbehandlung bei Teilausführungen, Nachvollziehbarkeit, rechtlicher Rahmen). Das
|
||||
wäre eine bewusste Entscheidung und kein Nebenprodukt der Analyse-Agenten.
|
||||
|
||||
---
|
||||
|
||||
# 3. Kosten und Leistung auswerten
|
||||
|
||||
## Der Kern des Problems
|
||||
|
||||
Kosten sind seit K5 sauber erfasst. Leistung ist ungleich schwerer — und der ehrliche
|
||||
Grund ist:
|
||||
|
||||
> **Leistung ist nur messbar, wenn der Agent sich auf etwas Falsifizierbares festlegt.**
|
||||
|
||||
Ein Agent, der „interessante Beobachtungen" liefert, lässt sich nicht bewerten. Einer,
|
||||
der sagt „NVDA über 5 Handelstage +3 %, Konfidenz 0,7", schon.
|
||||
|
||||
Das Finanzumfeld ist dafür ein Glücksfall: Aussagen werden von der Realität
|
||||
beantwortet, ohne dass jemand sie bewerten muss.
|
||||
|
||||
## Stufe 1 — Betriebsmetriken (sofort möglich)
|
||||
|
||||
Aus vorhandenen Daten, ohne neues Konzept:
|
||||
|
||||
| Metrik | Quelle | Was sie verrät |
|
||||
|---|---|---|
|
||||
| Kosten je Agent/Tag/Modell | `RunUsage` | vorhanden |
|
||||
| Cache-Trefferquote | `CachedTokens / PromptTokens` | ob T1 wirkt |
|
||||
| Fehlerquote | Status `Failed`/`LoopLimitExceeded` | instabile Agenten |
|
||||
| **Leerlaufquote** | Läufe ohne Ergebnis | siehe unten |
|
||||
| Tool-Fehlerquote | braucht Audit-Log (S4) | kaputte Tool-Konfiguration |
|
||||
| Schritte je Lauf | `StepCount` | umständliche Arbeitsweise |
|
||||
|
||||
Die **Leerlaufquote** ist die wirksamste einfache Kennzahl: Ein Agent, der 40 % seiner
|
||||
Läufe ohne greifbares Ergebnis beendet, hat meist ein Zeitplan-Problem — genau das,
|
||||
was der Marktkalender aus Teil 2 löst. Kosten ohne Gegenwert, sofort abstellbar.
|
||||
|
||||
## Stufe 2 — Ergebnisregister
|
||||
|
||||
Bisher wird nirgends festgehalten, **was** ein Lauf hervorgebracht hat.
|
||||
|
||||
Eine Tabelle `AgentOutput`, verknüpft mit dem Lauf: Art (Bericht, Signal, Nachricht,
|
||||
Gedächtniseintrag), Betreff, Verweis. Damit wird aus „Kosten pro Lauf" die deutlich
|
||||
nützlichere Größe **„Kosten pro Ergebnis"**.
|
||||
|
||||
## Stufe 3 — Falsifizierbare Aussagen
|
||||
|
||||
Das eigentliche Leistungsmaß. Ein Agent hält eine Aussage fest:
|
||||
|
||||
```
|
||||
Subjekt: NVDA
|
||||
Aussage: Kurs steigt
|
||||
Horizont: 5 Handelstage
|
||||
Konfidenz: 0.7
|
||||
Begründung: …
|
||||
```
|
||||
|
||||
Ein Auflösungs-Job prüft nach Ablauf gegen die tatsächlichen Kurse — `DirectAPI` hat
|
||||
sie bereits. Kein Mensch muss bewerten.
|
||||
|
||||
Daraus fällt ab:
|
||||
|
||||
- **Trefferquote** je Agent, je Kategorie, je Horizont
|
||||
- **Brier-Score** — misst nicht nur, ob die Richtung stimmte, sondern ob die
|
||||
Konfidenz ehrlich war. Ein Agent, der bei 0,9 nur in 60 % der Fälle recht hat, ist
|
||||
überheblich; das bleibt bei reiner Trefferquote unsichtbar.
|
||||
- **Kosten je richtiger Aussage**
|
||||
- **Vergleich gegen eine Nulllinie** — etwa „der Index steigt immer" oder
|
||||
„Zufallsentscheidung". Ohne Nulllinie ist eine Trefferquote von 55 % nicht
|
||||
einzuordnen.
|
||||
|
||||
## Die vorgeschlagene Kennzahl
|
||||
|
||||
Keine einzelne Zahl, sondern ein Quotient mit Bezugspunkt:
|
||||
|
||||
```
|
||||
Nutzen = Brier-Skill-Score gegenüber Nulllinie
|
||||
Wert = Nutzen / Kosten pro Tag
|
||||
```
|
||||
|
||||
Die Betriebsmetriken aus Stufe 1 dienen der Diagnose: *warum* ist ein Agent teuer —
|
||||
zu viele Schritte, zu große Tool-Ergebnisse, Leerläufe, kein Cache-Treffer?
|
||||
|
||||
## Eine Warnung zur Ehrlichkeit
|
||||
|
||||
Bei 20 Aussagen sagt eine Trefferquote von 60 % statistisch nichts. Die Auswertung
|
||||
muss Fallzahl und Unsicherheitsbereich mit ausweisen, sonst optimiert man Rauschen —
|
||||
und schaltet einen guten Agenten ab, weil er eine schlechte Woche hatte.
|
||||
|
||||
Faustregel für die Anzeige: unter 30 aufgelösten Aussagen keine Rangliste, nur
|
||||
Rohzahlen.
|
||||
|
||||
---
|
||||
|
||||
# Vorgeschlagene Reihenfolge
|
||||
|
||||
| # | Was | Warum zuerst |
|
||||
|---|---|---|
|
||||
| 1 | Atomares Schreiben | Datenverlust ist bereits eingetreten |
|
||||
| 2 | Backup + Restore mit Test | Schützt alles Folgende |
|
||||
| 3 | Marktkalender | Spart sofort Kosten, verbessert Datenlage |
|
||||
| 4 | `Indicators` | Qualität hoch, Tokens runter |
|
||||
| 5 | Ergebnisregister (Stufe 2) | Grundlage jeder Bewertung |
|
||||
| 6 | Aussagen + Auflösung (Stufe 3) | Das eigentliche Leistungsmaß |
|
||||
| 7 | S4 + K2 | Voraussetzung für unbeaufsichtigten Betrieb |
|
||||
|
||||
Punkte 1 und 2 gehören zusammen: Ein Backup nicht-atomar geschriebener Dateien kann
|
||||
eine bereits beschädigte Datei sichern.
|
||||
Reference in New Issue
Block a user