{
  "document_type": "technical_concept",
  "language": "de",
  "audience": [
    "AI-Entwicklerteam",
    "Reviewer",
    "Maintainer"
  ],
  "project": {
    "name": "fm-rds-tx",
    "goal": "Aus dem bestehenden FM-Stereo/RDS-TX-System ein technisch sauberes, deterministisches, messbares und betriebsfestes Pro-Level-System machen.",
    "primary_priority": "Technische Perfektion",
    "secondary_priority": "Sinnvolle Umsetzungsreihenfolge mit maximalem Risikoabbau zuerst"
  },
  "executive_summary": {
    "current_strengths": [
      "Saubere Modultrennung zwischen Generator, DSP, Control, Audio, Backend und Plattform.",
      "Persistenter DSP-Zustand ist bereits vorhanden, insbesondere im Generator und im FM-Upsampler.",
      "Live-Updates werden bereits über atomare Snapshots bzw. Pointer modelliert.",
      "Es existieren bereits viele Unit-Tests sowie spektrale Blackbox-Tests für 19 kHz, 38 kHz und 57 kHz."
    ],
    "current_limitations": [
      "Der TX-Pfad in internal/app/engine.go ist noch ein einzelner synchroner Generate/Upsample/Write-Loop ohne entkoppelten Echtzeitpuffer.",
      "Die Runtime-Recovery ist schwach: bei Fehlern wird nur gezählt, geloggt und gewartet; es gibt keinen expliziten Fault-State mit deterministischem Fallback.",
      "Die Control-Plane in internal/control/control.go ist funktional, aber nicht hart genug: keine Authentisierung, keine Transporthärtung, keine Request-Limits, keine Timeouts, keine Audit-Trails.",
      "Validation und Runtime-Semantik sind nicht überall deckungsgleich; Beispiel: fm.outputDrive wird in config.Validate() bis 10 akzeptiert, in Engine.UpdateConfig() aber nur bis 3.",
      "Device-Abstraktion ist brauchbar, aber noch nicht streng genug capability- und kalibrierungsgetrieben.",
      "Observability ist noch zu schwach für echten Dauerbetrieb und reproduzierbare Fehleranalyse."
    ],
    "core_statement": "Der DSP-Kern ist nah an ernsthaft brauchbar. Der Abstand zu Pro-Level liegt primär in Betriebssicherheit, Observability, Hardwarevalidierung und strenger Runtime-Kontrolle."
  },
  "repo_grounding": {
    "confirmed_code_touchpoints": [
      {
        "path": "internal/app/engine.go",
        "observation": "TX läuft aktuell in einer einzelnen Goroutine als synchroner Zyklus: GenerateFrame -> optional FMUpsampler.Process -> driver.Write. Kein echter Producer/Consumer-Puffer zwischen Generator und Hardwarewriter."
      },
      {
        "path": "internal/offline/generator.go",
        "observation": "Generator hat bereits persistenten Zustand, LiveParams per atomic.Pointer und sinnvolle DSP-Kette inklusive optionalem BS.412-Limiter."
      },
      {
        "path": "internal/control/control.go",
        "observation": "HTTP-Control existiert bereits, aber ohne sichtbare Authentisierung, ohne Server-Timeout-Konfiguration und ohne harte API-Grenzen."
      },
      {
        "path": "internal/config/config.go",
        "observation": "Validation ist vorhanden, aber semantisch nicht überall konsistent mit Laufzeitregeln."
      },
      {
        "path": "internal/platform/soapy.go",
        "observation": "Capabilities und RuntimeStats existieren als Ansatz, reichen aber noch nicht für eine wirklich harte device-aware Steuerung."
      },
      {
        "path": "internal/audio/stream.go",
        "observation": "Lock-freier SPSC-Ringbuffer für Live-Audio ist bereits vorhanden und kann als Referenz für deterministische Buffer-Designs dienen."
      }
    ],
    "confirmed_inconsistencies": [
      {
        "id": "CFG-SEM-001",
        "description": "fm.outputDrive wird in Config.Validate() bis 10 akzeptiert, die Fehlermeldung spricht aber von 0..3, und Engine.UpdateConfig() erzwingt tatsächlich 0..3."
      },
      {
        "id": "CTL-UX-001",
        "description": "handleAudioStream() nennt in der Fehlermeldung '--audio-http', im CLI ist dieser Schalter nicht als gleichwertiger offensichtlicher Bedienpfad bestätigt."
      }
    ]
  },
  "design_principles": [
    "Kein verstecktes Glück: Jeder relevante Echtzeit- oder RF-Pfad muss deterministisch, messbar und reproduzierbar sein.",
    "Fail-safe statt fail-weird: Bei Unsicherheit oder Überlast lieber definiert muten oder faulten als kaputt weiterzusenden.",
    "Eine Runtime-Wahrheit: Konfiguration, Live-State und tatsächlich angewandte Hardware-/DSP-Parameter dürfen nicht auseinanderlaufen.",
    "Hardware ist Wahrheit: IQ-Dateien und Unit-Tests reichen nicht; es braucht Hardware-in-the-loop und externe Decoder-/Messvalidierung.",
    "Observability ist Pflicht, nicht Luxus: Kein Pro-Level ohne Metriken, strukturierte Logs, Fault-Telemetrie und reproduzierbare Regressionen.",
    "Keine implizite Semantik: Alle Parameter müssen in Config, API, Runtime und Telemetrie exakt dasselbe bedeuten."
  ],
  "priority_model": {
    "P0": "Technische Perfektion und Determinismus",
    "P1": "Betriebssicherheit und Fehlerbeherrschung",
    "P2": "Hardware-Wahrheit und RF-Qualität",
    "P3": "Sichere und saubere Runtime-Steuerung",
    "P4": "Deployment-, Release- und Service-Reife"
  },
  "workstreams": [
    {
      "id": "WS-01",
      "priority": "P0",
      "title": "Deterministische Echtzeit-TX-Pipeline mit entkoppeltem Writer",
      "why": "Der aktuelle Single-Loop ist elegant, aber anfällig gegen Write-Spikes, Scheduling-Jitter und hardwarebedingte Blockaden. Pro-Level verlangt Entkopplung zwischen Erzeugung und Ausgabe.",
      "objective": "Generator/Upsampler und Hardwarewriter werden als getrennte Stufen mit kleinem, kontrolliertem Frame-Puffer betrieben. Der Writer darf kurzfristige Timing-Jitter absorbieren, ohne sofort den gesamten TX-Zyklus zu ruinieren.",
      "target_architecture": {
        "pipeline": [
          "control-plane",
          "runtime supervisor",
          "generator worker",
          "optional upsampler worker",
          "bounded frame queue",
          "writer worker",
          "driver"
        ],
        "queue_policy": {
          "type": "bounded ring queue",
          "capacity_frames": 3,
          "default_behavior": "Producer füllt vor, Writer sendet in Echtzeit, Supervisor überwacht Queue-Füllstand",
          "allowed_strategies": [
            "block producer kurzzeitig",
            "repeat last safe frame im Fault-Recovery-Modus",
            "mute frame im Sicherheitsmodus"
          ],
          "forbidden_strategies": [
            "unbounded buffering",
            "still und heimlich alte Frames verwerfen ohne Counter/Log",
            "dynamisches Verhalten ohne Telemetrie"
          ]
        }
      },
      "implementation_tasks": [
        {
          "id": "WS-01-T1",
          "title": "FrameQueue einführen",
          "details": [
            "Neue interne Queue-Struktur für CompositeFrame oder DeviceFrame einführen.",
            "Explizit festlegen, ob vor oder nach FMUpsampler gepuffert wird. Empfehlung: Puffern auf Device-Frame-Ebene, damit der Writer nur noch sendet.",
            "FrameQueue muss feste Kapazität, Füllstand, High-Watermark, Low-Watermark und Drop-/Mute-/Repeat-Counter liefern."
          ]
        },
        {
          "id": "WS-01-T2",
          "title": "Writer-Worker einführen",
          "details": [
            "Writer läuft in eigener Goroutine und besitzt alleinige Ownership über driver.Write().",
            "Nur der Writer darf Write- und Tune-nahe Timinginteraktionen mit dem Treiber koordinieren.",
            "Write-Dauer, Blockzeiten und Late-Events werden pro Frame gemessen."
          ]
        },
        {
          "id": "WS-01-T3",
          "title": "Supervisor-Schicht einführen",
          "details": [
            "Supervisor bewertet Queue-Füllstand, Late-Rate, Fehlerhäufigkeit und entscheidet über Normal/Fault/Recovery.",
            "Supervisor ist nicht nur Logik, sondern Runtime-State-Maschine."
          ]
        }
      ],
      "acceptance_criteria": [
        "Keine direkte synchrone Generate->Write-Kopplung mehr im Hauptpfad.",
        "Queue-Füllstand und Write-Latenz sind live sichtbar.",
        "Kurzzeitige Write-Spikes führen nicht sofort zu hörbaren Aussetzern oder unkontrolliertem Timing-Kollaps.",
        "Langlauf mit 6h Testdauer zeigt keine wachsende Drift im Kontrollpfad und keine ungebremste Fehlereskalation."
      ],
      "affected_files": [
        "internal/app/engine.go",
        "internal/output/backend.go",
        "internal/platform/soapy.go"
      ],
      "example_interfaces": {
        "frame_queue_contract": "type FrameQueue interface { Push(frame *output.CompositeFrame) error; Pop(ctx context.Context) (*output.CompositeFrame, error); FillLevel() float64; Depth() int; Capacity() int; Stats() QueueStats }",
        "queue_stats_example": {
          "capacity": 3,
          "depth": 2,
          "fillLevel": 0.6667,
          "pushTimeouts": 0,
          "popTimeouts": 0,
          "droppedFrames": 0,
          "repeatedFrames": 0,
          "mutedFrames": 0
        }
      }
    },
    {
      "id": "WS-02",
      "priority": "P0",
      "title": "Explizite Runtime-State-Maschine und Fault-Handling",
      "why": "Aktuell existieren im Engine-State nur idle, running, stopping. Das reicht nicht für professionelles Fehlermanagement im Sendebetrieb.",
      "objective": "Einführen eines klaren Betriebsmodells mit Fault-, Recovery- und Muted-Zuständen. Jeder kritische Fehlerpfad endet in definiertem Verhalten.",
      "target_state_machine": {
        "states": [
          "idle",
          "arming",
          "prebuffering",
          "running",
          "degraded",
          "muted",
          "faulted",
          "stopping"
        ],
        "transition_examples": [
          {
            "from": "idle",
            "to": "arming",
            "trigger": "StartTX angefordert und Grundvalidierung erfolgreich"
          },
          {
            "from": "arming",
            "to": "prebuffering",
            "trigger": "Driver gestartet, Queue erstellt, Generator bereit"
          },
          {
            "from": "prebuffering",
            "to": "running",
            "trigger": "Queue-Minimum erreicht"
          },
          {
            "from": "running",
            "to": "degraded",
            "trigger": "Late-Rate oberhalb Schwellwert oder Queue-Füllstand wiederholt kritisch"
          },
          {
            "from": "degraded",
            "to": "muted",
            "trigger": "Writer kann keine sichere Ausgabe mehr garantieren"
          },
          {
            "from": "muted",
            "to": "faulted",
            "trigger": "Persistenter Treiberfehler oder Recovery gescheitert"
          },
          {
            "from": "muted",
            "to": "running",
            "trigger": "Queue und Treiber wieder stabil"
          }
        ]
      },
      "implementation_tasks": [
        {
          "id": "WS-02-T1",
          "title": "Fault-Klassifikation definieren",
          "details": [
            "Treiberfehler",
            "Write-Time-Budget überschritten",
            "Queue leer",
            "Queue permanent überfüllt",
            "Signal-Selbsttest fehlgeschlagen",
            "unerlaubte Live-Konfigurationsänderung"
          ]
        },
        {
          "id": "WS-02-T2",
          "title": "Reaktionsstrategie pro Fehlerklasse definieren",
          "details": [
            "Warnen ohne Zustandswechsel",
            "degraded mit Countern",
            "muted mit stiller Trägerstrategie oder kompletter TX-Stille",
            "faulted mit manueller oder automatischer Recovery"
          ]
        },
        {
          "id": "WS-02-T3",
          "title": "Event-Log und Fault-Historie einführen",
          "details": [
            "Jeder Zustandswechsel ist auditierbar.",
            "Faults enthalten Ursache, Timestamp, Metriken und letzten bekannten Runtime-Kontext."
          ]
        }
      ],
      "acceptance_criteria": [
        "Jede kritische Fehlersituation führt in einen expliziten Zustand statt in implizites Weiterlaufen.",
        "Der aktuelle Runtime-State ist über API und Telemetrie jederzeit sichtbar.",
        "Degraded/Muted/Faulted lassen sich in Tests gezielt triggern und verifizieren."
      ],
      "affected_files": [
        "internal/app/engine.go",
        "internal/control/control.go"
      ],
      "example_fault_policy": {
        "late_buffer_threshold_per_60s": 10,
        "queue_critical_fill_below": 0.1,
        "writer_error_burst": 3,
        "policy": [
          "Bei 1-2 Einzelereignissen nur Counter erhöhen.",
          "Ab Burstschwelle auf degraded schalten.",
          "Wenn degraded > 5s anhält oder Write wiederholt fehlschlägt -> muted.",
          "Wenn muted nicht innerhalb definierter Frist stabilisiert werden kann -> faulted."
        ]
      }
    },
    {
      "id": "WS-03",
      "priority": "P0",
      "title": "Semantische Korrektheit und harte Config-/Runtime-Konsistenz",
      "why": "Technische Perfektion scheitert oft nicht am DSP, sondern an stillen Semantikabweichungen zwischen Config, API, Live-Update und tatsächlicher Laufzeit.",
      "objective": "Ein einziger, eindeutig definierter Parameterraum. Jeder Wert hat exakt eine Bedeutung und identische Constraints in Config, HTTP-API, Runtime und Telemetrie.",
      "implementation_tasks": [
        {
          "id": "WS-03-T1",
          "title": "Parameterinventar erstellen",
          "details": [
            "Alle öffentlich und intern verwendeten Parameter inventarisieren.",
            "Für jeden Parameter: Typ, Einheit, Bereich, Default, Hot-Reload-Fähigkeit, Safety-Relevanz, Telemetrie-Name."
          ]
        },
        {
          "id": "WS-03-T2",
          "title": "Validation vereinheitlichen",
          "details": [
            "Config.Validate(), Engine.UpdateConfig() und API-Patch-Validierung dürfen nicht divergieren.",
            "Beispiel: outputDrive muss an allen Stellen denselben Bereich haben."
          ]
        },
        {
          "id": "WS-03-T3",
          "title": "AppliedConfig einführen",
          "details": [
            "Neben DesiredConfig muss es eine AppliedConfig geben.",
            "API-Antworten sollen nicht nur sagen, was gewünscht wurde, sondern was tatsächlich übernommen wurde."
          ]
        }
      ],
      "acceptance_criteria": [
        "Kein Parameter hat an zwei Stellen unterschiedliche Grenzwerte oder Einheiten.",
        "API kann DesiredConfig und AppliedConfig getrennt zurückgeben.",
        "Ungültige Hot-Updates werden deterministisch abgelehnt und nicht teilweise angewandt."
      ],
      "affected_files": [
        "internal/config/config.go",
        "internal/app/engine.go",
        "internal/control/control.go"
      ],
      "example_parameter_schema": {
        "name": "fm.outputDrive",
        "unit": "logical composite drive factor",
        "type": "float64",
        "range": {
          "min": 0.0,
          "max": 3.0
        },
        "default": 1.0,
        "hot_reloadable": true,
        "safety_class": "medium",
        "notes": "Darf nicht mit hardware gain oder RF gain verwechselt werden."
      }
    },
    {
      "id": "WS-04",
      "priority": "P1",
      "title": "Observability, Telemetrie und Diagnosefähigkeit",
      "why": "Ohne harte Telemetrie bleibt jedes Timing- oder RF-Problem ratenbasiert. Pro-Level braucht Metriken, strukturierte Logs und Diagnostik-Endpunkte.",
      "objective": "Vollständige Sichtbarkeit auf Runtime, Queue, Writer, Generator, RF-Selbsttests und API-Aktivität schaffen.",
      "implementation_tasks": [
        {
          "id": "WS-04-T1",
          "title": "Strukturiertes Logging einführen",
          "details": [
            "Einheitliches Logging-Backend nutzen.",
            "Keine verstreuten Printf-only Pfade als primäre Diagnose.",
            "Jeder Fault, State-Change und API-Eingriff wird strukturiert geloggt."
          ]
        },
        {
          "id": "WS-04-T2",
          "title": "Prometheus-kompatible Metriken einführen",
          "details": [
            "Engine-Metriken",
            "Writer-Metriken",
            "Queue-Metriken",
            "RDS-/Pilot-Selbsttest-Metriken",
            "Audio-Stream-Metriken",
            "Control-Plane-Metriken"
          ]
        },
        {
          "id": "WS-04-T3",
          "title": "Debug- und Profiling-Endpunkte",
          "details": [
            "pprof optional aktivierbar",
            "Build-Info, Git-Commit, Build-Tags, Backend, Plattform und Runtime-Version ausgeben"
          ]
        }
      ],
      "acceptance_criteria": [
        "Jeder relevante Betriebsaspekt ist per Runtime-Endpunkt oder Metrics-Endpunkt sichtbar.",
        "Fehlerfälle sind anhand von Logs und Countern nachvollziehbar, ohne den Code erneut zu lesen.",
        "Langlaufprobleme lassen sich zeitlich korrelieren."
      ],
      "example_metrics": [
        "engine_chunks_generated_total",
        "engine_late_buffers_total",
        "engine_fault_transitions_total",
        "writer_write_duration_seconds",
        "queue_fill_ratio",
        "queue_dropped_frames_total",
        "queue_muted_frames_total",
        "driver_write_errors_total",
        "audio_stream_underruns_total",
        "audio_stream_overflows_total",
        "rf_selftest_pilot_db",
        "rf_selftest_rds_57k_db"
      ],
      "affected_files": [
        "internal/app/engine.go",
        "internal/control/control.go",
        "internal/platform/soapy.go",
        "internal/audio/stream.go"
      ]
    },
    {
      "id": "WS-05",
      "priority": "P1",
      "title": "Sichere und erwachsene Control-Plane",
      "why": "Sobald TX start/stop, Frequenz, RDS-Text oder Live-Audio per HTTP steuerbar sind, ist die Control-Plane ein sicherheitsrelevanter Teil des Systems.",
      "objective": "API transport- und anwendungsseitig härten, state-aware machen und auditierbar gestalten.",
      "implementation_tasks": [
        {
          "id": "WS-05-T1",
          "title": "Auth und Deploy-Modi definieren",
          "details": [
            "Mindestens Token-Auth für Remote-Betrieb.",
            "Optionale mTLS-Unterstützung für geschützte Infrastrukturen.",
            "Explizite Betriebsmodi: localhost-only, trusted-lan, secured-remote."
          ]
        },
        {
          "id": "WS-05-T2",
          "title": "HTTP-Server härten",
          "details": [
            "ReadTimeout",
            "WriteTimeout",
            "IdleTimeout",
            "ReadHeaderTimeout",
            "Body-Size-Limits",
            "Content-Type-Validierung",
            "Method enforcement"
          ]
        },
        {
          "id": "WS-05-T3",
          "title": "API semantisch aufräumen",
          "details": [
            "DesiredConfig vs AppliedConfig vs RuntimeState",
            "Idempotente Start/Stop-Endpunkte",
            "Transaktionsartige Apply-/Reject-Antworten für Patches",
            "Audit-Log pro wirksamem Eingriff"
          ]
        }
      ],
      "acceptance_criteria": [
        "Kein ungeschützter Remote-TX-Betrieb im Standardmodus.",
        "API liefert deterministische und vollständige Antworten.",
        "Große oder falsche Requests können das System nicht unkontrolliert stressen."
      ],
      "affected_files": [
        "internal/control/control.go",
        "cmd/fmrtx/main.go"
      ],
      "example_patch_response": {
        "ok": true,
        "requestedChangeId": "cfg-2026-04-05T12:00:00Z-0001",
        "desired": {
          "frequencyMHz": 100.2,
          "ps": "JAN FM"
        },
        "applied": {
          "frequencyMHz": 100.2,
          "ps": "JAN FM"
        },
        "state": "running",
        "warnings": []
      }
    },
    {
      "id": "WS-06",
      "priority": "P2",
      "title": "Hardware-in-the-loop und externe RF-Wahrheitsprüfung",
      "why": "Ein DSP-System ist erst dann pro-tauglich, wenn es auf echter Hardware und mit externem Decoder/Messergebnis wiederholt korrekt ist.",
      "objective": "Nightly- oder manuell triggerbare Hardware-Regressionen etablieren, die nicht nur intern, sondern extern prüfen, was tatsächlich gesendet wird.",
      "implementation_tasks": [
        {
          "id": "WS-06-T1",
          "title": "Loopback-/Capture-Setup definieren",
          "details": [
            "Referenz-SDR oder definierter externer Empfänger als Capture-Seite.",
            "Leistungsschutz und Dummy-Load-Konzept klar dokumentieren.",
            "Standard-Testfrequenz, Standard-Device-Rate und Standard-Testdauer festlegen."
          ]
        },
        {
          "id": "WS-06-T2",
          "title": "Automatisierte Analyse bauen",
          "details": [
            "Pilotenergie 19 kHz",
            "Stereoenergie 38 kHz",
            "RDS-Energie 57 kHz",
            "Deviation/Composite-Level",
            "Trägergenauigkeit",
            "RDS-Decodierbarkeit und Fehlerrate",
            "Langlaufdrift"
          ]
        },
        {
          "id": "WS-06-T3",
          "title": "Externen Decoder in Regression einbinden",
          "details": [
            "PS und RT müssen extern decodierbar und stabil sein.",
            "Nicht nur intern erzeugte Bits prüfen."
          ]
        }
      ],
      "acceptance_criteria": [
        "Definierte Testsignale werden extern reproduzierbar korrekt empfangen.",
        "Pilot-, Stereo- und RDS-Komponenten liegen mit stabilen Pegeln an den erwarteten Frequenzen.",
        "Langlauftests zeigen keine schleichende Entwertung der Sendekette."
      ],
      "affected_files": [
        "internal/offline/spectral_test.go",
        "internal/platform/soapy.go",
        "scripts/*"
      ],
      "example_hil_report": {
        "device": "pluto",
        "testDurationMinutes": 30,
        "pilot19kDetected": true,
        "stereo38kDetected": true,
        "rds57kDetected": true,
        "rdsDecodeSuccessRate": 0.998,
        "maxCarrierErrorHz": 12.0,
        "maxLateBuffers": 0,
        "result": "pass"
      }
    },
    {
      "id": "WS-07",
      "priority": "P2",
      "title": "Device-aware Capability- und Kalibrierungsmodell",
      "why": "Ein generisches Backend-Modell reicht nicht, wenn unterschiedliche SDRs unterschiedliche Raten, Gains, Latenzen und Abweichungen haben.",
      "objective": "Pro Gerät bzw. Gerätetyp bekannte Fähigkeiten und Kalibrierungen explizit abbilden.",
      "implementation_tasks": [
        {
          "id": "WS-07-T1",
          "title": "Capabilities ausbauen",
          "details": [
            "Sample-Rate-Sets oder Bereiche",
            "Gain-Semantik",
            "Frequenzraster",
            "MTU-/Buffer-Empfehlungen",
            "Minimale stabile Chunkgrößen",
            "Tune-Latenzverhalten"
          ]
        },
        {
          "id": "WS-07-T2",
          "title": "Kalibrierungsprofil einführen",
          "details": [
            "frequencyOffsetHz",
            "deviationScale",
            "mpxGainCalibration",
            "driverChunkRecommendation",
            "safeDefaultGain"
          ]
        },
        {
          "id": "WS-07-T3",
          "title": "Device-aware Validation",
          "details": [
            "Config nicht nur gegen generische Regeln validieren, sondern gegen bekannte Device-Fähigkeiten.",
            "Nicht unterstützte Raten oder gefährliche Kombinationen früh blockieren."
          ]
        }
      ],
      "acceptance_criteria": [
        "Treiber und Runtime wissen explizit, was das konkrete Device sicher kann.",
        "Kalibrierte Geräte liefern reproduzierbarere RF-Ergebnisse.",
        "Fehlkonfigurationen werden vor TX-Beginn erkannt."
      ],
      "affected_files": [
        "internal/platform/soapy.go",
        "internal/config/config.go"
      ],
      "example_calibration_profile": {
        "deviceId": "pluto-serial-1234",
        "sampleRateHz": 1000000,
        "frequencyOffsetHz": -18.0,
        "deviationScale": 0.97,
        "mpxGainCalibration": 1.03,
        "safeDefaultGainDb": -20.0,
        "preferredChunkMs": 50
      }
    },
    {
      "id": "WS-08",
      "priority": "P2",
      "title": "Signal-Selbstüberwachung im Betrieb",
      "why": "Nur Post-mortem-Messungen reichen nicht. Das System soll im Betrieb merken, wenn Pilot, RDS oder Composite auffällig werden.",
      "objective": "Leichtgewichtige In-Band-Selbsttests auf Chunk-Basis oder in Intervallen ausführen und in Fault-Logik einspeisen.",
      "implementation_tasks": [
        {
          "id": "WS-08-T1",
          "title": "Chunk-basierte RF-Checks definieren",
          "details": [
            "Goertzel oder kleine FFT für 19 kHz, 38 kHz und 57 kHz",
            "Composite-Clipping- und Pegelindikatoren",
            "Optional Deviation-Schätzer"
          ]
        },
        {
          "id": "WS-08-T2",
          "title": "Anomalieerkennung definieren",
          "details": [
            "Pilot fehlt",
            "RDS ungewöhnlich schwach",
            "unerwartete Composite-Energieverteilung",
            "langsame Drift"
          ]
        }
      ],
      "acceptance_criteria": [
        "Runtime kann relevante RF-Anomalien erkennen und melden.",
        "Selbsttests sind ausreichend billig, um die Echtzeitfähigkeit nicht zu gefährden."
      ],
      "affected_files": [
        "internal/dsp/goertzel.go",
        "internal/offline/generator.go",
        "internal/app/engine.go"
      ]
    },
    {
      "id": "WS-09",
      "priority": "P3",
      "title": "Teststrategie von Unit-Tests zu echter Qualitätsabsicherung erweitern",
      "why": "Viele Tests sind gut. Die richtigen Testklassen sind besser. Pro-Level verlangt deterministische Regressionen, Fuzzing und Concurrency-Tests.",
      "objective": "Testpyramide so ausbauen, dass Signal, Runtime und API gleichermaßen abgesichert sind.",
      "implementation_tasks": [
        {
          "id": "WS-09-T1",
          "title": "Golden-Vector-Tests",
          "details": [
            "Definierte Inputsignale und erwartete Analysewerte festschreiben.",
            "Nicht nur boolsche Pass/Fail-Aussagen, sondern tolerierte numerische Fenster."
          ]
        },
        {
          "id": "WS-09-T2",
          "title": "Long-run Regressionen",
          "details": [
            "Tausende Chunks durchlaufen lassen.",
            "Boundary-Continuity, Drift, Queue-Stabilität, Writer-Stabilität prüfen."
          ]
        },
        {
          "id": "WS-09-T3",
          "title": "Race Detector, Fuzzing und API-Mutation-Tests",
          "details": [
            "Konfigurationspatches",
            "RDS-Texte",
            "Audio-Ingest",
            "Start/Stop-Rennen",
            "gleichzeitige Live-Updates"
          ]
        }
      ],
      "acceptance_criteria": [
        "Es gibt Regressionen für DSP, Runtime, API und HIL.",
        "Race Detector und Fuzzing finden keine bekannten kritischen Pfade mehr.",
        "Nightly-Regressions geben maschinenlesbare Berichte aus."
      ]
    },
    {
      "id": "WS-10",
      "priority": "P4",
      "title": "Service-Reife, Packaging und Reproduzierbarkeit",
      "why": "Ein System ist nicht professionell, wenn nur der Autor es zuverlässig starten kann.",
      "objective": "Saubere Build-, Release- und Betriebsartefakte bereitstellen.",
      "implementation_tasks": [
        {
          "id": "WS-10-T1",
          "title": "Reproduzierbare Builds",
          "details": [
            "Build-Flags, Version, Commit und Tags ins Binary schreiben.",
            "Artefakte pro Zielplattform konsistent erzeugen."
          ]
        },
        {
          "id": "WS-10-T2",
          "title": "Service-Units und Beispiel-Deployments",
          "details": [
            "systemd unit",
            "EnvironmentFile-Unterstützung",
            "Beispielkonfigurationen pro Backend"
          ]
        },
        {
          "id": "WS-10-T3",
          "title": "Migrations- und Schema-Versionierung",
          "details": [
            "Config-Versionen einführen.",
            "Klare Migrationsstrategie für ältere JSON-Konfigurationen."
          ]
        }
      ],
      "acceptance_criteria": [
        "Standardisierte Start- und Betriebswege existieren.",
        "Build- und Runtime-Version sind eindeutig sichtbar.",
        "Alte Konfigurationen können kontrolliert migriert werden."
      ]
    }
  ],
  "implementation_sequence": [
    {
      "order": 1,
      "workstreams": [
        "WS-03",
        "WS-01",
        "WS-02"
      ],
      "reason": "Erst muss die Semantik stimmen, dann die deterministische Pipeline, dann das Fault-Modell. Sonst baut man saubere Infrastruktur auf falschen Annahmen."
    },
    {
      "order": 2,
      "workstreams": [
        "WS-04",
        "WS-05"
      ],
      "reason": "Sobald Runtime-Struktur sauber ist, müssen Sichtbarkeit und sichere Steuerung folgen. Sonst ist der neue Kern schwer überprüfbar und riskant bedienbar."
    },
    {
      "order": 3,
      "workstreams": [
        "WS-06",
        "WS-07",
        "WS-08"
      ],
      "reason": "Jetzt wird die Hardware-Wahrheit und RF-Qualität fest verdrahtet: HIL, Kalibrierung und laufende Signalkontrolle."
    },
    {
      "order": 4,
      "workstreams": [
        "WS-09",
        "WS-10"
      ],
      "reason": "Zum Schluss werden Regressionstiefe, Packaging und Service-Reife maximal professionalisiert."
    }
  ],
  "cross_cutting_rules": {
    "musts": [
      "Jeder neue Runtime-Zustand muss per API und Telemetrie sichtbar sein.",
      "Jede neue Recovery- oder Drop-/Mute-Strategie braucht Counter, Logs und Tests.",
      "Keine neue Konfigurationsoption ohne klaren Typ, Bereich, Einheit, Default und Hot-Reload-Klassifikation.",
      "Hardware-nahe Änderungen brauchen mindestens Simulations- und HIL-Validierung.",
      "Alle Faults müssen eine maschinenlesbare Ursache und eine menschenlesbare Zusammenfassung haben."
    ],
    "must_not": [
      "Keine unbounded Queues.",
      "Keine stillen Fallbacks ohne Telemetrie.",
      "Keine teilweise angewandten Live-Config-Änderungen ohne explizite Rückmeldung.",
      "Keine unterschiedlichen Grenzwerte zwischen Config, API und Runtime.",
      "Keine sicherheitsrelevanten HTTP-Endpunkte ohne Härtung im Remote-Betrieb."
    ]
  },
  "concrete_examples": {
    "example_runtime_status": {
      "state": "degraded",
      "substate": "writer_backpressure",
      "engine": {
        "chunksProduced": 128443,
        "lateBuffers": 7,
        "underruns": 0,
        "maxCycleMs": 51.12,
        "maxWriteMs": 49.91
      },
      "queue": {
        "capacity": 3,
        "depth": 1,
        "fillLevel": 0.3333,
        "droppedFrames": 0,
        "repeatedFrames": 2,
        "mutedFrames": 0
      },
      "driver": {
        "txEnabled": true,
        "streamActive": true,
        "samplesWritten": 64221500,
        "slowWrites": 4
      },
      "lastFault": {
        "code": "WRITER-LATE-BURST",
        "at": "2026-04-05T12:34:56Z",
        "message": "Write-Latenz wiederholt über Chunk-Budget"
      }
    },
    "example_fault_event": {
      "eventId": "fault-000184",
      "severity": "error",
      "stateBefore": "running",
      "stateAfter": "muted",
      "code": "QUEUE-EMPTY-RECOVERY-FAILED",
      "message": "Queue blieb trotz Recovery leer; Ausgang wurde auf Mute gesetzt",
      "metrics": {
        "queueFillLevel": 0.0,
        "lateBuffersLast60s": 14,
        "writerErrorsLast60s": 3
      }
    },
    "example_rollout_plan": {
      "milestone_1": "Semantik und State-Maschine stabil",
      "milestone_2": "Entkoppelter Writer mit Telemetrie",
      "milestone_3": "Sichere API und Audit-Log",
      "milestone_4": "HIL-Regression und Kalibrierung",
      "milestone_5": "Nightly-Qualitätsgates und reproduzierbare Releases"
    }
  },
  "definition_of_done": {
    "technical": [
      "TX-Pfad ist deterministisch entkoppelt und fault-tolerant.",
      "DesiredConfig, AppliedConfig und RuntimeState sind sauber getrennt.",
      "Alle kritischen Fehler führen in explizite Zustände.",
      "RF-Signalqualität ist intern und extern nachweisbar.",
      "Metriken, strukturierte Logs und Diagnosepfade sind vollständig."
    ],
    "operational": [
      "System läuft im Langlauftest stabil.",
      "Remote-Bedienung ist gehärtet und auditierbar.",
      "Gerätespezifische Fähigkeiten und Kalibrierungen sind modelliert.",
      "Builds und Deployments sind reproduzierbar."
    ],
    "quality_gates": [
      "Unit- und Integrationssuite grün",
      "Race Detector grün",
      "Fuzzing ohne kritische Findings",
      "HIL-Regression grün",
      "Soak-Test grün"
    ]
  },
  "final_instruction_to_ai_team": {
    "summary": "Nicht blind Features ergänzen. Zuerst die Semantik und den Runtime-Kern hart machen. Dann Observability und sichere Steuerung. Danach Hardware-Wahrheit, Kalibrierung und Nightly-Regressions. Alles, was nicht deterministisch, messbar und fault-beherrscht ist, ist noch nicht pro-level.",
    "first_step_now": [
      "WS-03 beginnen: Parameterinventar und semantische Vereinheitlichung.",
      "Danach direkt WS-01 und WS-02 in einem Architektur-Branch umsetzen."
    ]
  }
}
