================================================================================ G10-4.0.1 — Mapping-Review (Read-Site Inventory + Apply-Schema-Audit) ================================================================================ Datum: 2026-05-09 Status: read-only Audit, keine Mutation, durable User-Decisions ausstehend Vorgänger: G10-4.0 audit (durable findings F1–F7), Bot-Restart-Forensik (PID 117) Baseline: Bot PID 117 (start 2026-05-09 08:40:06 UTC), BINANCE_TESTNET=true Boundary: kein Code, keine Tests, kein Bot-Restart, kein Worker, keine Orders, kein Apply, kein Mainnet, kein Push ================================================================================ ================================================================================ 0. SCOPE-KORREKTUR — Mainnet-Guard für G10-4 (durable, accepted) ================================================================================ Korrektes Defense-in-Depth-Mainnet-Gate für spätere G10-4-Implementation: L1 - Settings.BINANCE_TESTNET == True (Bot-Side, harter Reject) L2 - BOT_ENVIRONMENT == "testnet" (Worker-side env, G10-3b enforced) L3 - command.payload.environment == "testnet" (Handler, G10-3b enforced) L4 - profile.environment == "paper" (PHP, G10-2 enforced) L5 - exchange_connection_id IS NULL (Handler, G10-3b enforced) LIVE_TRADING_ENABLED darf höchstens als optionaler Bot-Run-State-Sanity-Check genutzt werden, NIEMALS als Mainnet-Guard. ================================================================================ 1. READ-SITE INVENTORY — alle 13 Phase-1 Keys ================================================================================ Production-Pfade only. tests/, __pycache__/, *.md, *.txt, *.template ausgeschlossen. ================================================================================ KEY #1 — log_level (G7 Summary) ================================================================================ Settings-Konstante in Bot FEHLT (Settings.LOG_LEVEL existiert nicht) Direct os.getenv-Read KEINE Read-Sites in Production KEINE (Bot honoriert Key heute überhaupt nicht) Indirekte Logger-Setup-Pfade (init-time): - trading/main.py:78 from utils.log_setup import setup_logging, get_logger - trading/main.py:79 setup_logging() ← Default INFO, kein Param - trading/utils/log_setup.py:86 def setup_logging(level: int = logging.INFO) -> None: - trading/utils/log_setup.py:133 root.setLevel(level) - trading/utils/log_setup.py:140 h.setLevel(level) - trading/utils/log_setup.py:144 handlers[3].setLevel(logging.ERROR) - trading/command_worker.py:988 logging.basicConfig(level=logging.INFO, ...) (Worker-eigener Logger, nicht Bot-Hot-Path) Hot Path? nein (logger-init-only, einmalig beim Bot-Start) Entscheidungsrelevant? nein Migrations-Empfehlung REVIEW NÖTIG. (a) aus Phase-1-Allowlist entfernen, ODER (b) setup_logging() um Param erweitern + per-Cycle re-init, ODER (c) als Phase-1.1 nachreichen ================================================================================ KEY #2 — decision_log_verbosity (G7 Summary) ================================================================================ Settings-Konstante in Bot FEHLT (Settings.DECISION_LOG_VERBOSITY existiert nicht) Direct os.getenv-Read KEINE Read-Sites in Production KEINE (nur Doku in trading/SAFETY_FILTERS.md:411, und Allowlist-Eintrag in command_worker.py:503, keine Bot-Konsumption) Hot Path? nein Entscheidungsrelevant? nein Migrations-Empfehlung REVIEW NÖTIG (analog #1). ================================================================================ KEY #3 — max_open_positions (G9 Risk) ================================================================================ Settings-Konstante in Bot Settings.MAX_OPEN_POSITIONS (legacy, default 5) + Settings.MULTI_STRATEGY_MAX_OPEN_POSITIONS (multi, default 4) Direct os.getenv-Reads trading/config/settings.py:59 (legacy) trading/config/settings.py:118 (multi) Read-Sites in Production: - trading/execution/risk_manager.py:16 self.max_open_positions = self.settings.MAX_OPEN_POSITIONS (init-time-capture, NICHT property-read) - trading/execution/risk_manager.py:90 max_pos = max_override if max_override is not None else self.max_open_positions (check_open_positions; regime kann via max_override überschreiben — ABER Settings-Wert bleibt unten) - trading/execution/multi_strategy_position_sizer.py:122 max_open = getattr(self._s, 'MULTI_STRATEGY_MAX_OPEN_POSITIONS', 4) (defensive, init-time via self._s) Hot Path? ja (jeder Buy-Decision-Cycle prüft) Entscheidungsrelevant? ja Doppel-Quelle JA — zwei separate Settings, beide aktiv Migrations-Empfehlung ActiveConfigProvider mit User-Decision: (a) Multi-only (default 4) (b) Legacy-only (default 5) (c) beide synchron mutieren (d) eines ignorieren ================================================================================ KEY #4 — max_risk_per_trade_pct (G9 Risk) ================================================================================ Settings-Konstante in Bot Settings.MAX_RISK_PER_TRADE (legacy, default 0.02 = 2%) + Settings.MULTI_STRATEGY_MAX_RISK_PCT (multi, default 0.01 = 1%) Direct os.getenv-Reads trading/config/settings.py:58 (legacy) trading/config/settings.py:114 (multi) Read-Sites in Production: - trading/execution/risk_manager.py:15 self.max_risk_per_trade = self.settings.MAX_RISK_PER_TRADE (init-time-capture) - trading/execution/risk_manager.py:30 risk_amount = portfolio_value * self.max_risk_per_trade (calculate_position — ATR-Sizing) - trading/execution/risk_manager.py:98 return account_balance * self.max_risk_per_trade (calculate_position_size — legacy compat) - trading/execution/multi_strategy_position_sizer.py:167 risk_amount = portfolio_value * self._s.MULTI_STRATEGY_MAX_RISK_PCT Hot Path? ja Entscheidungsrelevant? ja Doppel-Quelle JA (Faktor 2× zwischen den beiden) Migrations-Empfehlung ActiveConfigProvider mit User-Decision (analog #3) ================================================================================ KEY #5 — max_total_exposure_pct (G9 Risk) ================================================================================ Settings-Konstante in Bot Settings.MULTI_STRATEGY_MAX_EXPOSURE_PCT (default 0.40 = 40%) + HARDCODE in trading/execution/position_sizer.py Direct os.getenv-Read trading/config/settings.py:116 (KEIN env-Read für Hardcode) Read-Sites in Production: - trading/execution/position_sizer.py:24 MAX_EXPOSURE_PCT = 0.80 ← MODULE-LEVEL HARDCODE - trading/execution/position_sizer.py:61 max_investable = portfolio_value * MAX_EXPOSURE_PCT - trading/execution/position_sizer.py:68 f"...max {MAX_EXPOSURE_PCT*100:.0f}%" - trading/execution/multi_strategy_position_sizer.py:170 max_invested = portfolio_value * self._s.MULTI_STRATEGY_MAX_EXPOSURE_PCT Hot Path? ja Entscheidungsrelevant? ja Doppel-Quelle + Hardcode JA (40% vs 80%, Faktor 2× und nicht-konsistent) Migrations-Empfehlung REVIEW NÖTIG. Hardcode entfernen + ActiveConfigProvider, ODER legacy position_sizer.py als dead-code markieren (Multi-Strategy ist im Bot DRY_RUN=true → multi-Pfad aktuell nicht aktiv; legacy position_sizer.py wird aber via main.py:1137 PositionSizer() instanziert und in legacy-Flow benutzt). ================================================================================ KEY #6 — min_position_value_usdt (G9 Risk) ================================================================================ Settings-Konstante in Bot Settings.MULTI_STRATEGY_MIN_NOTIONAL (default 10.0) ⚠ NAME-MISMATCH zwischen PHP-Allowlist und Bot Direct os.getenv-Read trading/config/settings.py:120 Read-Sites in Production: - trading/execution/multi_strategy_position_sizer.py:227 if size < self._s.MULTI_STRATEGY_MIN_NOTIONAL: - trading/execution/multi_strategy_position_sizer.py:234 f"(size={size:.2f}, min={self._s.MULTI_STRATEGY_MIN_NOTIONAL})" Hot Path? ja Entscheidungsrelevant? ja Migrations-Empfehlung ActiveConfigProvider mit Alias-Mapping (min_position_value_usdt → MULTI_STRATEGY_MIN_NOTIONAL). Name-Mismatch ist Bot-internal, semantisch identisch (USDT-Mindestwert per Position). ================================================================================ KEY #7 — cash_reserve_pct (G9 Risk) ================================================================================ Settings-Konstante in Bot Settings.MULTI_STRATEGY_CASH_RESERVE_PCT (default 0.05 = 5%) Direct os.getenv-Read trading/config/settings.py:126 Read-Sites in Production: - trading/execution/balance_provider.py:122 cr = float(getattr(self._s, "MULTI_STRATEGY_CASH_RESERVE_PCT", 0.05)) (defensive getattr, INIT-time via self._s) - trading/execution/balance_provider.py:130 f"cash_reserve_pct={cr} fee_buffer_pct={fb}" (Logger) - trading/execution/balance_provider.py:136, 149, 160, 172, 182 dict-Einträge in balance-audit-Output (5 Stellen) Hot Path? ja (jeder Buy-Decision via N8.1 Balance-Guard) Entscheidungsrelevant? ja (steuert usable_balance = free × (1 − cr − fb)) Migrations-Empfehlung ActiveConfigProvider — saubere 1:1 Migration ================================================================================ KEY #8 — fee_buffer_pct (G9 Risk) ================================================================================ Settings-Konstante in Bot Settings.MULTI_STRATEGY_FEE_BUFFER_PCT (default 0.002 = 0.2%) Direct os.getenv-Read trading/config/settings.py:128 Read-Sites in Production: - trading/execution/balance_provider.py:123 fb = float(getattr(self._s, "MULTI_STRATEGY_FEE_BUFFER_PCT", 0.002)) - trading/execution/balance_provider.py:130, 137, 150, 161, 173, 183 dict-Einträge (5 Stellen + Logger) Hot Path? ja Entscheidungsrelevant? ja Migrations-Empfehlung ActiveConfigProvider — saubere 1:1 Migration ================================================================================ KEY #9 — daily_loss_limit_pct (G9 Risk) ================================================================================ Settings-Konstante in Bot FEHLT Direct os.getenv-Read KEINE Read-Sites in Production KEINE Verwandter Konzept-Pfad (NICHT identisch): - trading/execution/risk_manager.py:69-83 check_max_drawdown(portfolio, max_drawdown=0.20) ⚠ Das ist ein STARTING-CAPITAL-DRAWDOWN-Check mit Hardcode-Default 20%, KEIN tagesgenauer daily_loss_limit. Keine semantische Äquivalenz. - trading/main.py:594, 699, 802, 968 check_max_drawdown(portfolio) Aufrufe - trading/docs/architecture_2026-04-29.md:223 "daily_loss_limit → 2% Starting → no-buys (main.py:154-165)" ← VERALTETE DOK-REFERENZ. main.py:154-165 enthält heute nur Imports + Init. Hot Path? nein (Bot konsumiert Key gar nicht) Entscheidungsrelevant? nein (im Bot) Migrations-Empfehlung REVIEW NÖTIG. (a) aus Phase-1-Allowlist entfernen, ODER (b) Bot-side neue Settings + Read-Sites bauen (cycle-day-resetting Loss-Tracker — substantielle neue Logik; semantisch ≠ check_max_drawdown), ODER (c) als Phase-1.1 nachreichen ================================================================================ KEY #10 — weekly_loss_limit_pct (G9 Risk) ================================================================================ Settings-Konstante in Bot FEHLT Direct os.getenv-Read KEINE Read-Sites in Production KEINE Hot Path? nein Entscheidungsrelevant? nein Migrations-Empfehlung analog #9 (Bot-Logik fehlt komplett) ================================================================================ KEY #11 — tier_high_allocation_pct (G9 Risk) ================================================================================ Settings-Konstante in Bot Settings.MULTI_STRATEGY_TIER_HIGH_PCT (default 0.08 = 8%) Direct os.getenv-Read trading/config/settings.py:110 Read-Sites in Production: - trading/execution/multi_strategy_position_sizer.py:277 if score >= TIER_HIGH_MIN_SCORE: return 'CORE-HIGH', float(self._s.MULTI_STRATEGY_TIER_HIGH_PCT) Hot Path? ja (jeder Symbol-Tier-Sizing-Call) Entscheidungsrelevant? ja Migrations-Empfehlung ActiveConfigProvider — saubere 1:1 ================================================================================ KEY #12 — tier_mid_allocation_pct (G9 Risk) ================================================================================ Settings-Konstante in Bot Settings.MULTI_STRATEGY_TIER_MID_PCT (default 0.05 = 5%) Direct os.getenv-Read trading/config/settings.py:111 Read-Sites in Production: - trading/execution/multi_strategy_position_sizer.py:279 return 'CORE-MID', float(self._s.MULTI_STRATEGY_TIER_MID_PCT) Hot Path? ja Entscheidungsrelevant? ja Migrations-Empfehlung ActiveConfigProvider — saubere 1:1 ================================================================================ KEY #13 — tier_low_allocation_pct (G9 Risk) ================================================================================ Settings-Konstante in Bot Settings.MULTI_STRATEGY_TIER_LOW_PCT (default 0.02 = 2%) Direct os.getenv-Read trading/config/settings.py:112 Read-Sites in Production: - trading/execution/multi_strategy_position_sizer.py:281 return 'CORE-LOW', float(self._s.MULTI_STRATEGY_TIER_LOW_PCT) Hot Path? ja Entscheidungsrelevant? ja Migrations-Empfehlung ActiveConfigProvider — saubere 1:1 ================================================================================ 2. MAPPING-TABELLE — alle 13 Keys (kompakt) ================================================================================ # | Runtime-Key | Settings-Konstante | Read-Sites (Bot) | Provider-Property (Vorschlag) | Typ | Default | Status --+----------------------------+-------------------------------------------------------+---------------------------------------------------+--------------------------------------------+------------------+-----------------+-------------- 1 | log_level | (fehlt) | setup_logging() init-time, Default INFO | active_config.log_level | str (enum) | "info" | FEHLT 2 | decision_log_verbosity | (fehlt) | KEINE | active_config.decision_log_verbosity | str (enum) | "summary" | FEHLT 3 | max_open_positions | MAX_OPEN_POSITIONS (5) | risk_manager.py:16+90 | active_config.max_open_positions | int | 4 / 5 | DOPPELT | | + MULTI_STRATEGY_MAX_OPEN_POSITIONS (4) | multi_strategy_position_sizer.py:122 | | | | 4 | max_risk_per_trade_pct | MAX_RISK_PER_TRADE (0.02) | risk_manager.py:15+30+98 | active_config.max_risk_per_trade_pct | float | 0.02 / 0.01 | DOPPELT | | + MULTI_STRATEGY_MAX_RISK_PCT (0.01) | multi_strategy_position_sizer.py:167 | | | | 5 | max_total_exposure_pct | MULTI_STRATEGY_MAX_EXPOSURE_PCT (0.40) | multi_strategy_position_sizer.py:170 | active_config.max_total_exposure_pct | float | 0.40 / 0.80 | DOPPELT | | + HARDCODE 0.80 in position_sizer.py:24 | position_sizer.py:24+61+68 | | | | + HARDCODE 6 | min_position_value_usdt | MULTI_STRATEGY_MIN_NOTIONAL (10.0) | multi_strategy_position_sizer.py:227+234 | active_config.min_position_value_usdt | float | 10.0 | NAME-MISMATCH 7 | cash_reserve_pct | MULTI_STRATEGY_CASH_RESERVE_PCT (0.05) | balance_provider.py:122 (+5 dict-stellen) | active_config.cash_reserve_pct | float | 0.05 | OK 8 | fee_buffer_pct | MULTI_STRATEGY_FEE_BUFFER_PCT (0.002) | balance_provider.py:123 (+5 dict-stellen) | active_config.fee_buffer_pct | float | 0.002 | OK 9 | daily_loss_limit_pct | (fehlt) | KEINE (check_max_drawdown ≠ daily_loss_limit) | active_config.daily_loss_limit_pct | float | - | FEHLT 10| weekly_loss_limit_pct | (fehlt) | KEINE | active_config.weekly_loss_limit_pct | float | - | FEHLT 11| tier_high_allocation_pct | MULTI_STRATEGY_TIER_HIGH_PCT (0.08) | multi_strategy_position_sizer.py:277 | active_config.tier_high_allocation_pct | float | 0.08 | OK 12| tier_mid_allocation_pct | MULTI_STRATEGY_TIER_MID_PCT (0.05) | multi_strategy_position_sizer.py:279 | active_config.tier_mid_allocation_pct | float | 0.05 | OK 13| tier_low_allocation_pct | MULTI_STRATEGY_TIER_LOW_PCT (0.02) | multi_strategy_position_sizer.py:281 | active_config.tier_low_allocation_pct | float | 0.02 | OK Sauberer Mapping-Status: 6 Keys (#7+#8+#11+#12+#13 + teilweise #6) → 1:1 sauber mappbar 4 Keys (#3+#4+#5+#6) → DOPPELT/HARDCODE/NAME-MISMATCH, brauchen User-Decision 3 Keys (#1+#2+#9+#10) → komplett FEHLEN im Bot, brauchen entweder neue Bot-Logik oder aus Phase-1 entfernen ================================================================================ 3. ZU ENTSCHEIDENDE FRAGEN — Mapping-Decisions für G10-4.1 ================================================================================ Q-A max_open_positions: (a) Multi-only (4) (b) Legacy-only (5) (c) beide synchron mutieren (d) eines deprecaten EMPFEHLUNG: (c) beide synchron, später (d) deprecaten wenn Multi-Strategy GA wird. Q-B max_risk_per_trade_pct: (a) Multi-only (0.01) (b) Legacy-only (0.02) (c) beide synchron (d) eines deprecaten EMPFEHLUNG: (c) beide synchron. Q-C max_total_exposure_pct: Hardcode 0.80 in legacy position_sizer.py:24 ist module-level Konstante. (a) Hardcode auf Settings-Lookup umbauen + Multi+Legacy syncen (b) legacy position_sizer.py als dead-code markieren (aber wird in main.py:1137 instanziert!) (c) Hardcode lassen + nur multi-Variante mutieren EMPFEHLUNG: (a) — Hardcode-Cleanup ist Pre-G10-4.1-Pflicht. Q-D min_position_value_usdt: Name-Mismatch. (a) Provider mit Alias-Mapping (PHP-Name → MIN_NOTIONAL) (b) Bot-Settings in MIN_POSITION_VALUE_USDT umbenennen (c) PHP-Allowlist auf min_notional umbenennen EMPFEHLUNG: (a) — minimaler Blast-Radius, nur Provider-Layer. Q-E daily_loss_limit_pct + weekly_loss_limit_pct: (a) aus Phase-1-Allowlist entfernen (PHP-Side-Change) (b) neue Bot-Logik bauen: cycle-day/week-resetting Loss-Tracker, check vor jedem Buy (c) als Phase-1.1 verschieben (G10-4 erstmal ohne) EMPFEHLUNG: (c) für G10-4-Erstrelease, (b) als Phase-1.1. Q-F log_level + decision_log_verbosity: (a) aus Phase-1-Allowlist entfernen (PHP-Side-Change) (b) setup_logging() Param erweitern + per-Cycle-Re-Init für log_level; decision_log_verbosity neue Bot-Logik (c) als Phase-1.1 verschieben EMPFEHLUNG: (c) für G10-4-Erstrelease, (b) als Phase-1.1. ================================================================================ 4. PHP APPLY CAPABILITY AUDIT (frische Re-Verifikation) ================================================================================ Frage | Antwort | Beleg -------------------------------------------------------------------+--------------+---------------------------------------------------- ApplyProfileService::createApplyCommand vorhanden? | NEIN | grep-Count = 0 in | | gui/app/Services/Apply/ApplyProfileService.php ApplyProfileService::createDryRunCommand vorhanden? | JA | "public function" matches: | | __construct | | createDryRunCommand Filament Apply-Button kann dry_run=false erzeugen? | NEIN | ProfileActionFactory.php:312 ->disabled() | | Z. 297: "Apply (G10) is rendered as a permanently- | | disabled button" CommandTypeRegistry blockt dry_run=false? | JA, HART | CommandTypeRegistry.php:293-297: | | if ($payload['dry_run'] !== true) { | | throw "apply_profile_testnet.dry_run_must_be_ | | true_in_phase_1: got " | | } | | Direkt danach Z. 300: environment !== 'testnet' check Wo wird dry_run=false heute abgelehnt? | VIER LAYER | (1) Service hardcoded => true | | (2) kein Apply-Method-Service | | (3) Registry-Validator-Reject | | (4) UI-Button disabled PHP-Dateien für G10-4 Apply-Capability | 3 + 1 | (1) ApplyProfileService.php — createApplyCommand | | (2) CommandTypeRegistry.php — Validator lockern | | (3) ProfileActionFactory.php — Apply-Button enable | | + Confirmation-Dialog | | (+ ggf. Filament-Tooltip-Update zur G10-Phase) KLASSIFIKATION: B) PHP kann nur Dry-run erzeugen — und zwar mit triple-layer (4-fach) Hard-Restriction. => G10-3.5 (PHP createApplyCommand) ist Vorbedingung von G10-4.1. ================================================================================ 5. RUNTIMECONFIGREADER STATUS (frische Re-Verifikation) ================================================================================ Aspekt | Befund ----------------------------------------+------------------------------------------------ Datei vorhanden | OK trading/runtime_config_reader.py | 3199 Bytes, mtime 2026-05-08 (Container) Default-Pfad | trading/state/runtime_config.json Verhalten bei missing | {} (defensive) Verhalten bei corrupt JSON | {} + Warning-Log (defensive) Verhalten bei JSON non-dict | {} + Warning-Log (defensive) Verhalten bei OSError | {} + Warning-Log (defensive) Verhalten bei file empty | {} (defensive) Verhalten bei whitespace-only | {} (defensive) Production-Imports | NUR in command_worker.py:1052-1075 | (G10-1 Startup-Heartbeat — emit_active_config) | NICHT in main.py, NICHT in settings.py runtime_config.json existiert? | NEIN | Container: nur .gitkeep (mtime May 8 05:56) | Host: nur .gitkeep (mtime Mai 8 07:56) Reader-Defensiveness | AUSREICHEND für G10-4.1 — never-raises Bot-Side-Wiring im Trading-Loop | FEHLT VOLLSTÄNDIG Reader ist ein REINER STUB und wird vom Bot ignoriert. Bot-Side-Wiring (in main.py cycle-loop oder via ActiveConfigProvider) fehlt vollständig — das ist der Implementations-Punkt für G10-4.1. ================================================================================ 6. RUNTIMECONFIGWRITER — DESIGN-VORSCHLAG (kein Code, nur Skizze) ================================================================================ Aspekt | Vorschlag ------------------------------------+------------------------------------------------ File-Pfad | trading/state/runtime_config.json | (matched Reader-Default exakt) | Verzeichnis existiert bereits (Container + Host) Backup-Pfad | trading/state/runtime_config..json.bak | z.B. runtime_config.20260509T100000Z.json.bak | KEIN Auto-Pruning (per Q5-Antwort der G10-4.0-Q&A) Atomic-Write-Pattern | tmp-File im SELBEN Verzeichnis (für same-fs-rename), | JSON-dump → os.fsync → os.replace(tmp, target) | tmp-Filename z.B. runtime_config.json.tmp. Vorhandene Helper | KEIN zentraler Helper im Code. | Pattern aus existierenden Scripts: | trading/scripts/state_recon_1_cleanup.py:229-235 | "tmp + os.replace; never leaves a half-written file" | trading/scripts/b_fee_fix_2_backfill.py:397 | os.replace(tmp_path, args.portfolio) | G10-4.1 könnte einen extrahieren: | trading/utils/atomic_json_writer.py Validation vor Write | Re-validierung über existente Helper im command_worker: | _g10_3b_validate_payload_basic | _g10_3b_validate_schema | _g10_3b_validate_cross_field | Fail vor Write -> KEIN Write, command status=failed 13-Key-Whitelist | Hard-coded Set: | _RUNTIME_OUTPUT_ALLOWED_KEYS = | G7_ALLOWED_SUMMARY_KEYS | G9_ALLOWED_RISK_KEYS | Schreiben verweigern, falls payload zusätzliche | Keys enthält Restore-Mechanik | Falls Validation NACH erfolgreichem Write | fehlschlägt (sollte nicht passieren, defensiv): | os.replace(backup, target) | -> audit "apply_rolled_back" state-Verzeichnis Existenz-Garantie | Verzeichnis existiert bereits. | Writer sollte os.makedirs(..., exist_ok=True) als | defensiver Sanity-Check. Output-Schema (Vorschlag) | { | "summary": { "log_level": "info", | "decision_log_verbosity": "summary" }, | "risk": { "max_open_positions": 4, | "cash_reserve_pct": 0.05, ... }, | "_meta": { "applied_at": "2026-05-09T10:00:00Z", | "command_id": "...", | "profile_id": "...", | "version": 1, | "checksum": "..." } | } Permissions | Datei wird vom Worker (UID node) geschrieben, | vom Bot (UID node) gelesen — beide laufen im | selben Container, kein UID-Konflikt Mainnet-Guard im Writer | if not Settings.BINANCE_TESTNET: | raise ValueError( | "validation/mainnet_blocked_g10_4_phase_1" | ) | (positives Test-Pattern, NICHT LIVE_TRADING_ENABLED) Mögliche Testfälle (für späteren G10-4.1): - Atomic write success - tmp-Cleanup wenn write fail mid-stream - Backup-Erstellung vor Write - Restore-on-Mid-Write-Error simulation - 13-Key-Whitelist Reject von extra Keys - OSError-Defensiveness - Mainnet-Guard Reject bei BINANCE_TESTNET=false - Re-Validation vor Write (full G7+G9 cascade) - Idempotenz bei identischem Payload ================================================================================ 7. BOUNDARY / HEALTH (Audit-Run, durable) ================================================================================ Check | Stand vor G10-4.0.1 | Stand nach G10-4.0.1 | Bewertung ---------------------------------------+--------------------+---------------------+----------- Bot-PID | 117 | 117 (stabil) | OK .env mtime | 1777991334 | 1777991334 | OK runtime_config.json existiert | nein | nein | OK BINANCE_TESTNET | true | true | OK (Mainnet blockiert) clawbot-worker container aktiv | nein | nein | OK commands count | 2 | 2 (alle succeeded) | OK command_audit_log count | 9 | 9 | OK audit_events count | 4 | 4 | OK config_profiles count | 1 | 1 | OK risk_settings count | 11 | 11 | OK Code geändert | - | nein | OK Tests geändert | - | nein | OK Bot-Restart | - | nein | OK Worker gestartet | - | nein | OK Orders erzeugt | - | nein | OK Apply ausgeführt | - | nein | OK runtime_config.json mutiert | - | nein | OK live_portfolio.json mutiert | - | (Bot-Cycle-Drift, | OK | | nicht durch Audit) | Mainnet-Pfad sichtbar | - | nein | OK Push | - | repo hat kein remote | OK Stop-Regeln getriggert | - | KEINE | OK ================================================================================ 8. EMPFOHLENE NÄCHSTE ETAPPE ================================================================================ Reihenfolge (durable, basiert auf G10-4.0 + G10-4.0.1): (8.1) USER-DECISIONS einholen zu den 6 Mapping-Fragen Q-A bis Q-F (Section 3). Ohne diese Decisions bleiben die problematischen Keys ungelöst. (8.2) G10-3.5 PHP createApplyCommand (PHP-only). Ohne diesen Schritt kann PHP keinen dry_run=false Command erzeugen. G10-4.1 wäre ohne G10-3.5 dead code. 3 Dateien: ApplyProfileService.php, CommandTypeRegistry.php, ProfileActionFactory.php. (8.3) G10-4.1 Bot-Side Implementation nach Mapping-Decisions. - RuntimeConfigWriter (~80 LoC) - ActiveConfigProvider (~120 LoC, 13 Property-Reads) - Hot-Path-Migration der ~10 production read-sites - 8–12 zusätzliche Tests - Mainnet-Guard via BINANCE_TESTNET=true (NICHT LIVE_TRADING_ENABLED) (8.4) G10-4.2 Handler-Branch dry_run=false + Live-E2E Apply - analog G10-3c-Pattern: Container-Sync, Pre-State, --once, Post-Verify (8.5) Optional NACH G10-Komplettierung: Naming-Cleanup-Phase (paper_trader → live_trader, LIVE_TRADING_ENABLED → BOT_RUN_ENABLED) ================================================================================ 9. KURZFASSUNG ================================================================================ (9.1) READ-SITE INVENTORY abgeschlossen. 6 Keys sauber mappbar. 4 Keys mit Doppelquelle / Hardcode / Name-Mismatch. 3 Keys (eigentlich 4: log_level, decision_log_verbosity, daily_loss_limit_pct, weekly_loss_limit_pct) FEHLEN komplett im Bot. (9.2) PHP-AUDIT bestätigt: Klassifikation B) — PHP kann nur Dry-run, mit 4-Layer-Hard-Block. G10-3.5 ist Vorbedingung von G10-4.1. (9.3) READER ist defensive Stub, NICHT im Bot-Trading-Loop verdrahtet. Wiring ist Implementations-Punkt für G10-4.1. (9.4) WRITER-DESIGN skizziert: tmp + os.fsync + os.replace, Backup vor Mutation, 13-Key-Whitelist, Re-Validation vor Write, Mainnet-Guard via BINANCE_TESTNET=true. (9.5) BOUNDARY perfekt eingehalten: Bot-PID 117 stabil, .env mtime unverändert, runtime_config.json nicht existent, kein Worker, kein Mainnet, keine Orders, keine Mutationen. (9.6) NÄCHSTER SCHRITT: User-Decisions zu Q-A bis Q-F (Section 3) — danach G10-3.5 oder G10-4.1 nach Reihenfolge in Section 8. ================================================================================ ENDE DES BERICHTS ================================================================================