Files
RichardandClaude Opus 5 740649789e 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>
2026-08-23 18:31:06 +02:00

95 lines
4.4 KiB
Markdown

# Audit-Log & Receipts — Nachvollziehbarkeit
> **Bauplan zu einem gebauten System.** Umgesetzt; der Stand steht in der
> [Roadmap](Roadmap.md) 3.1.
Setzt A3 aus der [Roadmap](Roadmap.md) um (F-A2). Zwei zusammengehörige Dinge:
- **Audit-Log** — ein Eintrag je Tool-Aufruf: wer, wann, welches Tool, mit welchem
Ausgang.
- **Receipts** — ein Abschluss-Beleg je Lauf: Ergebnis, Schritte, Tokens, Kosten,
verknüpft mit dem Task.
A3 ist das Fundament für A2 (jede Staging-Entscheidung wird als Datensatz verankert)
und für C7 („Kosten pro Ergebnis", fällt aus den Receipts ab). Die Tool-Fehlerquote aus
der Leistungsanalyse liest sich direkt aus dem Log.
## Warum eigene Tabellen, nicht der State-Store
Dieselbe Überlegung wie bei Gedächtnis und Taskboard: `IStateStore` ist Schlüssel-Wert.
Ein Log, das man nach Lauf, Task oder Tool filtern und dessen Fehlerquote man auswerten
will, braucht typisierte Spalten. Zwei Tabellen auf dem vorhandenen
[`SqliteStorage`](../src/ClawdDotNet.Core/Storage/SqliteStorage.cs): `AuditLog` und
`RunReceipts`.
## Provenienz — von der Engine gestempelt, nie vom Agenten behauptet
Die entscheidende Regel (aus dem OpenAlice-Provenance-Konzept):
- **Herkunft stempelt die Engine.** `AgentId`, `Model` und `Source` kommen aus dem
Wissen der Engine über den Lauf, nicht aus dem Tool-Ergebnis. Ein Tool kann seine
Herkunft nicht fälschen, weil es sie gar nicht schreibt.
- **Einträge sind unveränderlich.** Das Repository hat kein Update und kein Delete —
eine Korrektur ist ein neuer Eintrag. Das ist die eigentliche Zusage, keine fehlende
Funktion.
- **Unbekanntes wird als unbekannt markiert, nicht geraten.** Fehlt die Quelle, steht
`unknown`, nicht ein plausibel geratener Kanal.
- **Worker-Typ und Session sind getrennt.** `Model` (das ausführende Modell) und
`Source` (die verantwortliche Session: `webview`, `telegram`, `task`, `agentcomm`,
`job`, `direct`) sind verschiedene Begriffe und stehen in eigenen Spalten.
## Audit-Log
Gestempelt an genau einer Stelle: `AgentEngine.ExecuteToolCallAsync` — dort, wo jeder
Tool-Aufruf durchläuft. Je Aufruf ein Eintrag mit Ausgang:
| Status | Wann |
|---|---|
| `Ok` | Tool lief und lieferte ein Ergebnis |
| `Error` | Tool meldete einen Fehler oder warf |
| `Denied` | das `PermissionGate` hat abgelehnt |
| `NotFound` | Tool dem Agenten nicht zugewiesen/unbekannt |
Ein Abbruch (Cancellation) wird **nicht** protokolliert — der Aufruf kam nicht zum
Abschluss. Die Argumente werden roh, aber gekappt abgelegt (4 000 Zeichen); die
Ausgangsnotiz kurz (500).
**Best effort:** Ein Fehler beim Schreiben des Audits darf den Lauf nie scheitern
lassen — dieselbe Linie wie bei der Verbrauchserfassung. Der Eintrag wird geschrieben,
nachdem die eigentliche Arbeit getan ist.
## Receipts
Je Lauf ein Beleg, geschrieben beim Abschluss von `RunAsync`/`ChatAsync` (neben der
vorhandenen `RunUsage`-Erfassung). Er trägt Status, Schritte, Prompt-/Completion-/
Cached-Tokens, geschätzte Kosten (aus dem `ModelPricingCatalog`, mit
`CostIsKnown`-Flag) und einen kurzen Ergebnis-Verweis.
**Verknüpfung `RunUsage` ↔ Task:** Der Receipt trägt die `TaskId`, wenn der Lauf aus dem
Taskboard kam — der `EngineTaskDispatcher` reicht sie (samt `source: task`) durch. Damit
ist „Kosten pro Ergebnis" (C7) ein Abfallprodukt: `ListReceiptsForTaskAsync` liefert
alle Belege zu einem Task.
## RunId — die Klammer
Jeder Lauf bekommt zu Beginn eine `RunId` (GUID). Alle Audit-Einträge **und** der
Receipt eines Laufs tragen sie. So lässt sich ein Lauf lückenlos rekonstruieren:
`ListForRunAsync(runId)` gibt die Aufrufe in Reihenfolge, `GetReceiptForRunAsync(runId)`
den Abschluss.
## Verdrahtung
`IAuditRepository` ist optional (wie Gedächtnis und Taskboard): ohne Repo läuft die
Engine unverändert. In `Program.cs` wird ein `SqliteAuditRepository` auf der Instanz-DB
erzeugt und der Engine übergeben.
## Offen
- **Output-Scrubbing** — die `Arguments` können Secrets enthalten. Das zentrale
Maskieren bekannter Secret-Werte (eigener beschlossener Roadmap-Punkt) greift, sobald
es steht; der Andockpunkt (`ExecuteToolCallAsync`) ist derselbe.
- **Review-Oberfläche** — die Anzeige/Durchsicht des Logs und der Receipts gehört zu A2
(Staging-Review im Hauptfenster); die Abfragemethoden dafür stehen bereit.
- **Export** — ein JSONL-Export des Logs wäre für externe Auswertung nützlich (später,
passt zum A6-Spiegel).