trading-system-docs/a3/README.md

145 lines
5.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Red Queen — A3: Deterministic Safety Layer (V1)
Der **Deterministic Safety Layer** sitzt zwischen Mission/WP-State (A2 `missions.db`)
und dem **späteren** Orchestrator/Action/Retry/Delegation. Er entscheidet
**deterministisch** (Zähler, Limits, Tabellen — nicht „LLM-Lust"):
```
CONTINUE / RETRY / DEBUG / SECOND_OPINION / BLOCK / ESCALATE / CIRCUIT_BREAK
```
Ziel: Red Queen erhält die Safety-Logik, **BEVOR** spätere autonome Mission-Loops
existieren. Dieser Build enthält **KEINE** autonome Orchestrierung — kein dispatcher,
kein loop, kein heartbeat, kein cron, kein self-improvement. A3 ist eine reine
**Library / Safety-Capability**.
---
## DB-Entscheidung (Maker-Entscheidung, §29)
A3 nutzt eine **eigene `safety.db`** (separate SQLite-Datei), **nicht** die A2
`missions.db`:
- **Rollback-sicher für A2:** Die bestehende A2-Datenbank wird überhaupt nicht
angefasst — kein ALTER, kein neues Schema in `missions.db`, keine Gefahr für
Bestandsdaten (`CREATE TABLE IF NOT EXISTS` auf den A3-Tabellen in `safety.db`).
- **Entkopplung:** Safety-State (Circuit, Attempts, Events, Evidence) ist unabhängig
vom Mission-State. Ein beschädigter Mission-State kann den Safety-Layer nicht
mitreißen und umgekehrt.
- **Testbar:** A3-DB wird immer über temp-Pfade getestet, nie produktiv berührt.
Die A2-Integration erfolgt sauber: `SafetyStore` verweist Missions-/WP-IDs
als Fremdschlüssel-Namen (mission_id/wp_id) und ruft A2-Regeln nicht auf; A2-APIs
`mission_block`/`mission_transition` bleiben unberührt. Mission-`BLOCKED` kann in
A4 durch den Orchestrator auf Basis einer `BLOCK`-Safety-Entscheidung gesetzt werden —
A3 selbst mutiert A2 nicht direkt.
---
## Module
| Datei | Inhalt |
|-------|--------|
| `rq_safety.py` | Kernmodul: `SafetyStore`, `SafetyError`, Error-Signature, Strategy-Fingerprint, Redaction, Circuit Breaker, Retry Controller, Oscillation, Fail-Closed, Safety Events, Evidence, `evaluate_next_action` (§21) |
| `rq_safety_telegram.py` | Telegram-Notification-Interface (§19): `format_alert`, `build_payload`, `should_notify` (Anti-Spam). KEIN Daemon. |
| `rq_safety_cli.py` | Dünne, deterministische CLI (`--json`, Exit-Code 2 bei `SafetyError`), A2-CLI-Muster spiegelnd |
| `test_a3.py` | Isolierte Testsuite (temp-DB), Exit-Code 0 = PASS |
---
## Kern-API (`SafetyStore`)
```python
from rq_safety import SafetyStore
store = SafetyStore("path/to/safety.db")
# Attempt Ledger (idempotent via idempotency_key, append-only, redacted)
store.record_attempt("M1", "W1", actor="maker", result="FAIL",
error="boom pid=123", strategy="s1", idempotency_key="k-1")
# Retry / Oscillation / Circuit / Fail-closed
store.evaluate_next_action("M1", "W1", error="boom", strategy_label="s2",
is_mutating=True) # -> DECISION/REASON_CODE/ALLOWED_ACTION
# Circuit Breaker
store.open_circuit("MISSION", "M1", trigger="REG", severity="HIGH")
store.circuit_state("MISSION", "M1")
store.request_circuit_reset("MISSION", "M1", cause="...", recovery_evidence="...")
store.close_circuit("MISSION", "M1", approved_by="human", gate="human_gate", cause="...", recovery_evidence="...")
# Events / Evidence
store.safety_event("OSCILLATION_DETECTED", severity="CRITICAL", mission_id="M1")
store.safety_evidence("test_results", {"failing": 2})
store.evidence()
```
---
## Entscheidungen (Reason Codes, §22)
| Code | Bedeutung |
|------|-----------|
| `RETRY_AVAILABLE` | nächste Aktion erlaubt |
| `RETRY_LIMIT` | Maker/Checker-Repair MAX 3 erreicht → SECOND_OPINION |
| `SAME_ERROR_LIMIT` | gleiche Error-Signatur MAX 2 → DEBUG/Strategiewechsel |
| `FAILED_STRATEGY_REPEAT` | bereits gescheiterte Strategie → keine blinde Wiederholung |
| `NO_MEASURABLE_PROGRESS` | FAIL ohne messbaren Fortschritt (UNKNOWN ≠ Progress) |
| `OSCILLATION_ABAB` | A-B-A-B-Muster → Circuit-Breaker-Kandidat |
| `CIRCUIT_ALREADY_OPEN` | Circuit OPEN → BLOCK (read-only erlaubt) |
| `STATE_INCONSISTENT` | Fail-Closed: Safety-State korrupt → keine Mutation |
| `CRITICAL_TRIGGER` | kritischer GLOBAL-Trigger |
| `HUMAN_GATE_REQUIRED` | Circuit-Reset braucht Human Gate bei HIGH/CRITICAL/GLOBAL |
---
## Limite (A1 SAFETY_CONTRACT, konservativ V1)
- Maker→Checker-Repair: **MAX 3**
- Gleiche Error-Signatur: **MAX 2**
- Gleiche bereits gescheiterte Strategie: **keine blinde Wiederholung**
- Oscillation A-B-A-B: Circuit-Breaker-Kandidat
- `MAX_ITERATIONS=50`: äußerste Runtime-Notbremse, **nicht** operatives Retry-Limit
---
## Fail-Closed (§16)
Bei unbekanntem/inkonsistentem Safety-State → `SAFETY_STATE_ERROR`**STOP**
**Evidence sichern****KEINE Mutation** (read-only Diagnose ggf. erlaubt).
---
## Secret-Safety (§28)
- Alle credential-artigen Werte werden **vor** Persistenz UND vor Fingerprint/Signatur-
Ableitung **redacted** (`redact_secret`).
- Keine Tokens/Passwörter/private Keys/Authorization-Header in `safety.db`/Events/Telegram.
- Secret Exposure wird nur als `SECRET_EXPOSURE_DETECTED` + LOCATION/TYPE + `VALUE=REDACTED` erfasst.
---
## Telegram Interface (§19)
Kein Daemon. Nur Formatter/Payload. **Kein Spam** — nur signifikante Events
(`CIRCUIT_OPENED`, `CRITICAL`, `ESCALATION_REQUIRED`, `HUMAN_DECISION_REQUIRED`,
`RETRY_LIMIT_REACHED`, `OSCILLATION_DETECTED`, `SAFETY_STATE_ERROR`). Payload ist
deterministisch und **redacted**.
```python
from rq_safety_telegram import build_payload
payload = build_payload("CIRCUIT_OPENED", "CRITICAL", reason="...", mission_id="M")
# payload["notify"] == True, payload["text"] fertig formatiert
```
---
## Tests
```bash
python3 test_a3.py # Exit 0 = PASS; isoliert (temp-DB), produktive DBs unberührt
```
Abgedeckt: Attempt Ledger + Idempotenz, Error-Signature-Normalisierung, Strategy-
Fingerprint, Retry-Limits, Progress, Oscillation A-B-A-B, False-Positives,
Circuit-Breaker (+Restart-Persistenz + Negativ-Test), Fail-Closed, Events,
Evidence, Secret-Safety, Telegram-Interface, Loop-Simulation (AE), A2-DB-Isolation.