R8: Accounting- + Supervisor-Modul + Core-Datenfundament (S-0)

Portierung der beiden fehlenden Grundbausteine aus PolytraderSharp (voller Ausbau).

Core S-0 (Datenfundament fuer Analyse/Forensik):
- core_decision_journal + core_order_events (+ ReasonCode/Decision/OrderEvent-Enums),
  IDecisionJournal/IOrderEventLog mit fehlertoleranten EF-Impls (Handel bricht nie).
- SignalId-Durchreichung TradeSignal -> ExecutionService -> core_trade_history;
  ExecutionService schreibt an jeder Verzweigung Journal/Order-Events.
- JSONL-Log-Sink (LogJson + Dual-Sink), pure Analytik: RealizedPnlEngine (FIFO),
  TradeAnalytics, DossierBuilder. Migration AddAnalysisFoundation.

Accounting-Modul (acc_): unabhaengiger IBKR-Kontoauszug (Activity Flex Query) hinter
Interfaces mit Offline-Null-Stubs -> append-only Ledger + Periodenabrechnung/BWA + FX
(USD/EUR) + CSV/PDF (PDFsharp/MigraDoc). Steuerschicht bewusst offen (Platzhalter-Tab).
Kein Handel. Migration InitialAccounting.

Supervisor-Modul (sup_): read-only OpenRouter-Agent (Function-Calling-Loop) + read-only
Tool-Registry (8 Tools) + Profile + Dossier-Browser + Counterfactual-Job (Stub) +
Tagesbericht/MCP-Light (opt-in). Migration InitialSupervisor.

Verdrahtung: Program.cs (beide Module + Icons), slnx/App/Tests-Referenzen,
provision-db.ps1, AppSettings-Sektionen, docs/konzepte, README.

Tests: 79 -> 117 gruen (FIFO/KPIs/Dossier/JSONL, Classifier/Engine/FX/Idempotenz,
OpenRouter/Registry/Agent/MCP, STA-Konstruktion beider neuen Fenster).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-31 09:25:18 +02:00
co-authored by Claude Opus 4.8
parent cbbedb2e0e
commit 2a312ca035
86 changed files with 6880 additions and 22 deletions
+36 -2
View File
@@ -11,7 +11,8 @@ public class LoggingService
{
private RichTextBox? _rtb;
private AppLogLevel _minLevel = AppLogLevel.Info;
private readonly object _fileLock = new();
private readonly object _fileLock = new();
private readonly object _jsonlLock = new();
private static readonly string LogBaseDir =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
@@ -33,11 +34,23 @@ public class LoggingService
public void Error(string module, string message, Exception? ex = null)
=> Write(AppLogLevel.Error, module, message, ex);
public void Write(AppLogLevel level, string module, string message, Exception? ex = null)
// Überladungen mit CorrelationId (SignalId) schreiben zusätzlich strukturiert ins JSONL,
// sodass der Supervisor die komplette Kette „alles zu diesem Signal" filtern kann.
public void Info (string module, string message, string? cid, Exception? ex = null)
=> Write(AppLogLevel.Info, module, message, ex, cid);
public void Warn (string module, string message, string? cid, Exception? ex = null)
=> Write(AppLogLevel.Warn, module, message, ex, cid);
public void Error(string module, string message, string? cid, Exception? ex = null)
=> Write(AppLogLevel.Error, module, message, ex, cid);
public void Write(AppLogLevel level, string module, string message, Exception? ex = null, string? cid = null)
{
if (level < _minLevel) return;
var entry = new LogEntry(DateTime.Now, level, module, message, ex);
WriteToFile(entry);
WriteToJsonl(entry, cid);
WriteToRtb(entry);
}
@@ -61,6 +74,27 @@ public class LoggingService
catch { /* Logging darf niemals abstürzen */ }
}
// ─── JSONL (KI-freundlicher Zweit-Sink) ─────────────────────────────────────
/// <summary>
/// Schreibt zusätzlich eine JSON-Zeile nach Logs\{yyyy-MM-dd}.jsonl (Dual-Sink). Zeilenweise
/// filter-/parsebar (Datum/Level/Quelle/Text/CorrelationId) Grundlage für Log Viewer + Supervisor.
/// </summary>
private void WriteToJsonl(LogEntry e, string? cid)
{
try
{
Directory.CreateDirectory(LogBaseDir);
var file = Path.Combine(LogBaseDir, $"{e.Timestamp:yyyy-MM-dd}.jsonl");
var message = e.Exception != null ? $"{e.Message} | {e.Exception.Message}" : e.Message;
var json = LogJson.WriteLine(e.Timestamp, e.Level, e.Module, message, cid);
lock (_jsonlLock)
File.AppendAllText(file, json + "\n");
}
catch { /* Logging darf niemals abstürzen */ }
}
// ─── RichTextBox ──────────────────────────────────────────────────────────
private static readonly Color ColorInfo = Color.FromArgb(150, 210, 150);