# Supervisor, Detektor-Katalog und MCP-Server — Entwurf > **ARCHIVIERT.** Dieses Dokument beschreibt keinen gültigen Stand mehr. > Die Etappen 1 bis 3 sind in 2.6.0 ausgeliefert; der Etappenplan, die offenen > Punkte und die verworfenen Ansätze sind in **[../ROADMAP.md](../ROADMAP.md)** > übernommen. Dort steht, was gilt. > > Aufbewahrt wird der Entwurf wegen der Herleitung — besonders Abschnitt 0 > (warum Beobachtung und Urteil getrennt sind) und Abschnitt 7 (warum der > Client keinen Quelltext sieht). Wer hier etwas liest, prüft es gegen die > Roadmap, bevor er danach handelt. Stand: 2026-08-21. Betrifft alle Projekte, nicht nur das Deploymentcenter. Drei Vorhaben, die aneinanderhaengen und deshalb zusammen beschrieben werden: 1. ein **Supervisor**, der in jeder Anwendung laufend nachsieht, ob etwas schieflaeuft, und Befunde meldet 2. ein **Detektor-Katalog**, der festlegt, wonach er sucht — in allen Projekten unter denselben Namen 3. ein **MCP-Server**, ueber den Claude Code und andere Werkzeuge an Error-Reporting, Supervisor und Bugtracker andocken Die Reihenfolge im Dokument folgt der Sache, nicht der Umsetzung. Der Bauplan steht am Ende unter "Etappen". --- ## 0. Die Grundentscheidung: Beobachtung und Urteil trennen Der Supervisor ist bewusst kein einzelnes Ding. Er zerfaellt an der Vertrauensgrenze in zwei Haelften: | | Beobachter | Diagnostiker | |---|---|---| | laeuft | auf der Kundenmaschine | auf eigener Infrastruktur | | fragt | Ist das *ungewoehnlich*? | Ist das *schlimm*? | | Takt | dauernd, minuetlich | selten, bei Auffaelligkeit | | Kosten je Pruefung | muessen nahe null sein | duerfen hoch sein | | kennt Quellcode | nein | ja | | Technik | Regeln, Zaehler, Schwellen | Agent mit Repo-Zugriff | Zwei Gruende, warum die Trennung nicht verhandelbar ist: **Sicherheit.** Alles, was der ausgelieferte Client lesen kann, kann auch der Kunde lesen. Ein Token im Binary ist extrahierbar, TLS auf der eigenen Maschine abhoerbar, .NET dekompilierbar. Duerfte der Client Quellcode abrufen, waere die Software faktisch offen. Dagegen hilft keine Verschluesselung — der Client muesste entschluesseln koennen, also koennte es der Kunde auch. **Eignung.** Ein Sprachmodell ist schlecht im dauernden Hinsehen und gut im Deuten. Es kann nicht im Minutentakt schauen, hat keinen Verlauf im Kopf, sieht die anderen Installationen nicht und antwortet zweimal verschieden auf dieselbe Lage. Die Aufteilung waere also auch ohne den Sicherheitsaspekt richtig. Der Beobachter meldet **Symptome und Koordinaten** (`build`, `commit_sha`, `file`, `line`). Der Diagnostiker loest die Koordinaten gegen den Quellcode auf. So braucht der Client den Code nie zu sehen. --- ## 1. Detektor-Katalog Der Katalog ist der Kern. Er legt fest, wonach gesucht wird, und zwar unter stabilen Namen — damit Befunde aus verschiedenen Projekten vergleichbar bleiben und `dc_findings` etwas Auswertbares liefert. Ein Detektor-Name ist eine Zeichenkette der Form `familie.sache`. Er wandert nie mehr; kommt etwas dazu, bekommt es einen neuen Namen. ### 1.1 Detektoren, die den Fehler nicht vorher kennen muessen Diese Gruppe ist der eigentliche Gewinn. Sie findet Dinge, an die niemand gedacht hat, weil der Massstab nicht aus einem Kopf kommt, sondern aus der Wirklichkeit. | Name | Findet | Laeuft | |---|---|---| | `novel.error_signature` | Fehlersignatur, die es in dieser Fassung noch nie gab | Server | | `novel.log_template` | Logzeilen-Schablone, die noch nie auftrat | Server | | `silence.periodic` | Bekanntes wiederkehrendes Ereignis bleibt aus (still gestorbener Hintergrundjob) | Client | | `silence.heartbeat` | Instanz meldet sich nicht mehr | Server | | `deviation.self` | Abweichung vom eigenen Verlauf der letzten Wochen | Server | | `deviation.fleet` | Ausreisser gegenueber anderen Installationen derselben Fassung | Server | | `regression.build` | Kennzahl verschiebt sich nach einem Update gegenueber der Vorgaengerfassung | Server | `deviation.self` ist bereits vorhanden: `MetricStore::deviation()` rechnet die Abweichung mit einem Faktor auf die Streuung. `novel.error_signature` ist nahezu geschenkt, weil `BugRepo` mit `first_seen_at` und `occurrence_count` schon gruppiert und zaehlt. `deviation.fleet` ist der staerkste und bisher ungenutzte: dieselbe Fassung laeuft auf N Installationen, eine faellt bei irgendeiner Kennzahl aus dem Rahmen — auch bei einer, an die niemand gedacht hat. ### 1.2 Detektoren ueber die Zeitachse Ein Unit-Test laeuft Millisekunden auf frischem Zustand, ein Kundenprozess Wochen. Alles, was sich ansammelt, ist fuer Tests strukturell unsichtbar. | Name | Findet | Laeuft | |---|---|---| | `trend.monotonic` | Kennzahl waechst ueber N Fenster nur nach oben (Speicher-, Handle-, Cache-Leck) | Client | | `trend.saturation` | Kennzahl naehert sich einer harten Grenze (Platte, Verbindungspool, Dateihandles) | Client | | `trend.latency` | Antwortzeiten driften ueber Tage nach oben (Index-Degradation) | Client | ### 1.3 Detektoren, mit denen die Anwendung sich selbst verpfeift Der ergiebigste und billigste Fang: Zaehler auf die Stellen, an denen die Software heute schon still verzeiht. Dort sitzen die Fehler, die niemand meldet. | Name | Findet | Laeuft | |---|---|---| | `swallowed.exception` | `catch`-Bloecke, die einen Fehler schlucken und weitermachen | Client | | `fallback.usage` | Rueckfall auf den degradierten Pfad haeuft sich | Client | | `retry.storm` | Wiederholungsversuche haeufen sich | Client | | `probe.failed` | Registrierte Probe schlaegt fehl | Client | | `probe.slow` | Probe antwortet, aber deutlich langsamer als ueblich | Client | `fallback.usage` ist der unterschaetzte Eintrag: "Wir haben heute 4.000-mal den Notfallweg genommen und es ist niemandem aufgefallen" ist ein Befund, den weder ein Test noch ein Anwender je erzeugt. ### 1.4 Fachliche Zusicherungen | Name | Findet | Laeuft | |---|---|---| | `invariant.violated` | Vom Projekt formulierte Zusicherung gegen echte Daten verletzt | Client | Das ist die einzige Gruppe, die tatsaechlich "Unit-Test zur Laufzeit" ist — und fuer ihren Zweck ist genau das richtig. Sie deckt die Klasse ab, die sonst komplett durchfaellt: **semantisch falsche, aber unauffaellige Ergebnisse.** Der Bericht zeigt eine falsche Zahl, die Rundung stimmt seit Monaten nicht, ein Mandant sieht Daten eines anderen. Nichts stuerzt ab, keine Kennzahl weicht ab, keine Signatur ist neu — kein anderer Detektor sieht das. Beispiele, wie ein Projekt sie formuliert: Supervisor.Expect("saldo.nonnegative", () => konto.Saldo >= 0); Supervisor.Expect("beleg.balanced", () => soll == haben); Supervisor.Expect("mandant.unique", () => satz.MandantIds.Count == 1); ### 1.5 Was der Katalog bewusst nicht abdeckt Ehrlichkeitshalber festgehalten: Ein Fehler, der plausibel aussieht, keine Kennzahl bewegt, keine Ausnahme wirft und gegen keine formulierte Zusicherung verstoesst, wird hier nicht gefunden. Der einzige Hebel dagegen sind mehr und bessere Zusicherungen aus 1.4. --- ## 2. Befund-Format Ein Befund ist keine Fehlermeldung. Er behauptet nicht, dass etwas kaputt ist, sondern dass etwas ungewoehnlich ist. POST /api/supervisor/v1/observe Scope: supervisor:report ```json { "project_slug": "myapp", "instance": "kunde-4711/app-01", "detector": "trend.monotonic", "subject": "memory.working_set", "observed": {"slope_per_hour": 18400000, "windows": 9}, "baseline": {"median": 412000000, "stddev": 9100000}, "severity_hint": "medium", "build": "v1.4.2", "commit_sha": "a21536f", "environment": "production", "first_seen_at": "2026-08-19T04:12:00Z", "client_ref": "myapp/trend.monotonic/memory.working_set/v1.4.2" } ``` `client_ref` ist bewusst aus Detektor, Gegenstand und Fassung gebaut und nicht zufaellig: derselbe Befund darf beliebig oft gemeldet werden, ohne ein Duplikat anzulegen. Die Deduplizierung in `BugRepo::findByClientRef()` greift dann bereits. `severity_hint` heisst Hinweis, nicht Schweregrad. Die Einstufung entscheidet die empfangende Seite, die den Flottenblick hat. --- ## 3. Supervisor-Client im SDK Ein schlanker, regelbasierter Laeufer. Kein Sprachmodell, keine Netzabhaengigkeit fuer die Erkennung selbst. ### 3.1 Schnittstelle ```csharp public interface IHealthProbe { string Name { get; } // z. B. "db.reachable" TimeSpan Interval { get; } Task RunAsync(CancellationToken ct); } ``` Dazu die Meldewege, die eine Anwendung an ihren heiklen Stellen einstreut: ```csharp Supervisor.Expect(name, bedingung); // invariant.violated Supervisor.Swallowed(name, ex); // swallowed.exception Supervisor.Fallback(name); // fallback.usage Supervisor.Retry(name); // retry.storm Supervisor.Beat(name); // Bezugspunkt fuer silence.periodic ``` Alle fuenf sind absichtlich einzeilig und ohne Rueckgabewert. Was Ueberlegung kostet, wird nicht eingebaut. ### 3.2 Verhalten - Zustand liegt lokal, damit `client_ref` ueber Neustarts stabil bleibt - Zaehler werden gebuendelt gemeldet, nicht je Vorfall - gemeldet wird nur bei Zustandswechsel oder nach Ablauf eines Ruhefensters - `429 rate_limited` verdoppelt das Intervall (wie in der Prompt-Vorlage beschrieben) - faellt das Deploymentcenter aus, laeuft die Anwendung unveraendert weiter; Befunde gehen dann verloren und werden nicht gepuffert Der letzte Punkt ist Absicht. Ein Ueberwachungsteil, das die ueberwachte Anwendung aufhalten oder ihren Speicher fuellen kann, ist schlimmer als keines. ### 3.3 Fassungen - `.NET` in `client-dotnet/Deploymentcenter.Client/Supervisor.cs` - `PHP` in `src/Modules/Supervisor/` fuer die PHP-Anwendungen --- ## 4. Serverseite ### 4.1 Aufnahme `public/api/supervisor/v1/observe.php`, Modul `src/Modules/Supervisor/` mit `FindingRepo`. Bestaetigte Befunde koennen in ein Bugtracker-Item uebergehen; unbestaetigte bleiben Befund. ### 4.2 Die serverseitigen Detektoren Sie haengen in `cli/tick.php` neben `Evaluator::run()` — minuetlicher Cron mit Ueberlappungsschutz ist dort bereits geloest. Wichtig fuer die Reihenfolge: **Diese Detektoren brauchen keinen neuen Client.** `novel.error_signature`, `silence.heartbeat`, `deviation.self`, `deviation.fleet` und `regression.build` arbeiten auf Daten, die heute schon hereinkommen — Fehlerberichte, Watchdog-Pings, Kennzahlen. Sie liefern Nutzen, bevor eine einzige Anwendung ein neues SDK bekommen hat. --- ## 5. Projektuebergreifend arbeiten Einige Projekte sind stark verzahnt, das Deploymentcenter am staerksten. Ein Agent, der das SDK in Projekt X integriert und dabei einen Fehler im Deploymentcenter findet, muss ihn dort ablegen koennen. ### 5.1 Die heutige Sperre `ApiAuth::enforceProject()` bricht mit `403 project_forbidden` ab, sobald ein projektgebundenes Token ein fremdes Projekt anspricht. Die Prompt-Vorlage fordert genau das aber ein ("Faellt dir ein Fehler im Deployment Center selbst auf, melde ihn unter `deploymentcenter`"). Die Vorlage verspricht etwas, das die API verweigert. ### 5.2 Loesung ueber den vorhandenen Token-Typ Die Sperre wird nicht aufgeweicht — sie ist richtig, nur zu grob. Sie unterscheidet nicht, **wo das Token liegt**: - **Laufzeit-Token** (im ausgelieferten Client, auf Kundenhardware): streng projektgebunden, nur melden, nie uebergreifend. Ein extrahiertes Kundentoken darf nicht in fremde Tracker schreiben. Hier bleibt alles wie es ist. - **Werkbank-Token** (Claude Code, MCP, eigene Maschine): darf ueber die Projekte hinweg. `TokenManager::OWNER_TYPES` kennt `dev_agent` bereits. Da die Instanz ausschliesslich eigene Projekte fuehrt und es keine geteilte Instanz fuer Fremde geben wird, genuegt das als Unterscheidung — kein neues Feld, keine Mandantentrennung. `enforceProject()` bekommt eine Ausnahme: `owner_type = 'dev_agent'` darf fremde Projekte ansprechen. Lesend breit, schreibend eng — melden und kommentieren ja, fremde Items aufloesen oder schliessen nein. ### 5.3 Das eigentliche Risiko ist Fehlleitung Ein Agent in Projekt X kann kaum unterscheiden, ob das Deploymentcenter kaputt ist oder ob X das SDK falsch benutzt. Die Voreinstellung eines hilfsbereiten Modells ist im Zweifel "melde es". Schlimmer als der Laerm ist der Folgeschaden: Fehlmeldungen vergiften die Statistik, und die Statistik ist die Grundlage der Detektoren aus 1.1. Ein Detektor, der auf Fehlmeldungen kalibriert, ist wertlos. Drei Bremsen: - **Begruendungspflicht.** Ein Bericht gegen ein fremdes Projekt verlangt `evidence`: was wurde beobachtet, und warum liegt die Ursache dort und nicht hier. Etwas ausformulieren zu muessen kostet einen Reflex fast immer den Kopf. - **Eigener Eingang.** Fremdmeldungen landen mit `status = 'triage_external'`, nicht im offenen Backlog, und zaehlen erst nach Bestaetigung in die Statistik. - **Gedeckelter Schweregrad.** Fremde Melder duerfen `idea`, `wishlist`, `low`, `medium`. `high` und `critical` vergibt die empfangende Seite. ### 5.4 Herkunft und Buendelung Jeder uebergreifende Bericht traegt `reported_from`. Das ist keine Buchhaltung, sondern das wertvollste Signal im Vorgang: Melden drei Projekte unabhaengig dieselbe Sache gegen das Deploymentcenter, ist das kein "low" mehr. Statt drei Items entsteht eines mit wachsender `affects`-Liste. Die Buendelung laeuft ueber die Signatur, nicht ueber `client_ref` — der ist nur je Melder eindeutig. ### 5.5 Beziehungen zwischen Projekten `dc_projects` kennt heute Slug, Name und Notiz. Es fehlt die Beziehung. Neue Tabelle `dc_project_links` mit `from_slug`, `to_slug`, `kind` (`uses_sdk`, `depends_on`, `shares_code`) und `integrated_version`. Das loest nebenbei ein Wartungsproblem: Die von Hand gepflegte Zeile "Deploymentcenter-Anbindung: SDK 2.5.1" in jeder Projekt-`CLAUDE.md` wandert dorthin, wo sie hingehoert. Der Agent meldet die Fassung ueber MCP, wenn er die Anbindung anfasst. Damit ist zum ersten Mal beantwortbar: **Welche meiner Projekte sind von diesem SDK-Fehler betroffen?** ### 5.6 Rueckkanal Wird das Item in SDK 2.6.0 behoben, muessen die meldenden Projekte das erfahren — sonst meldet Projekt X denselben Punkt in drei Monaten erneut und baut seinen Workaround nie zurueck. `GET /api/updateservice/v1/changelog?since=…` liefert bereits `action_items`. Ergaenzt um "was du gemeldet hast, ist in 2.6.0 erledigt" schliesst sich der Kreis. --- ## 6. MCP-Server ### 6.1 Was er bringt Der offensichtliche Teil: Anmeldung einmal statt je Projekt, Schemata statt Prosa, kein `curl` aus dem Gedaechtnis. Der wertvollere: **`docs/AGENT_PROMPT_TEMPLATE.md` verschwindet fast vollstaendig.** Die Datei ist heute in jedes Projekt einkopiert, samt der Zeile "SDK 2.5.1, integriert am …". Das ist eine Wartungslast, die je Projekt waechst und beim ersten Vergessen schweigend veraltet. Ein MCP-Server liefert immer die aktuelle Form — die Frage "gegen welche Fassung habe ich integriert" stellt sich nicht mehr, weil nichts mehr einkopiert ist. ### 6.2 Der Schnitt: nicht aus OpenAPI erzeugen Naheliegend waere, die Werkzeuge aus `public/api/openapi.php` abzuleiten. Dort stehen 24 Endpunkte — 24 Werkzeuge sind ein Kontextfresser, denn Werkzeugdefinitionen liegen dauerhaft im Fenster, anders als eine Doku, die man einmal liest. Ein aufgeblaehter MCP-Server ist schlechter als die 30 Zeilen Prompt von heute. Kuratiert, an der Arbeitsweise entlang statt an der API: | Werkzeug | Zweck | |---|---| | `dc_projects` | Projekte mit Kurzbeschreibung **und Beziehung zum aktuellen Projekt** | | `dc_next_task` | Item uebernehmen, `409 already_claimed` intern behandelt | | `dc_get_item` | Details, Verlauf, Kommentare | | `dc_search` | Items filtern: Projekt, Status, Schweregrad, Build | | `dc_report` | Melden — mit `project_slug`, `reported_from`, bei fremdem Ziel `evidence` | | `dc_comment` | Fortschritt mit `action_taken` | | `dc_resolve` / `dc_release` | Abschliessen bzw. zurueckgeben | | `dc_my_reports` | Was hat dieses Projekt anderswo gemeldet, was wurde daraus | | `dc_error_groups` | Fehlergruppen mit `occurrence_count`, `first_seen_at` | | `dc_findings` | Supervisor-Befunde nach Detektor, Instanz, Fassung | | `dc_metrics` | Verlauf und Abweichung einer Kennzahl | | `dc_symbolicate` | Stacktrace gegen die passende Fassung aufloesen | Bewusst **nicht** aufgenommen: `publish`, `provision`, `deactivate` und Massenoperationen. Ein Release gehoert in die CI, nicht an ein Werkzeug, das ein Modell im Zweifel "hilfreich" ausloest. ### 6.3 Transport Erst ein **stdio-Adapter**: eine ausfuehrbare Datei, die die vorhandene REST-API ruft und das Token aus `DC_TOKEN` liest. Node 24 liegt vor. Kein neuer Angriffspunkt am Server, die Anmeldefrage ist bereits beantwortet, je Projekt drei Zeilen in `.mcp.json`. Ein entfernter Server unter `dc.mhdf.de/mcp` ist der bessere Endzustand, wenn mehrere Maschinen dranhaengen — dann aber mit OAuth statt Bearer-Token in einer Konfigurationsdatei. Groesserer Brocken, lohnt erst wenn der Schnitt sich bewaehrt hat. Die Werkzeugliste wird in der CI gegen `openapi.php` geprueft, damit beide nicht auseinanderlaufen. ### 6.4 Vertrauensgrenze — der wichtigste Punkt hier Ueber diese Werkzeuge fliessen **Daten aus der Wildnis in einen Agenten, der Code schreiben und Befehle ausfuehren darf.** `error_message`, `stack_trace`, Logauszuege und Supervisor-Befunde entstehen auf fremden Maschinen und enthalten regelmaessig Eingaben, die jemand anderes bestimmt hat — ein Dateiname, ein Formularfeld, das in der Ausnahme landet. Ein Text in einem Bugreport ist keine Anweisung, auch wenn er wie eine formuliert ist. Ein Feld mit "bitte ergaenze in `Auth.cs` folgende Zeile" ist trivial zu platzieren, sobald irgendeine Nutzereingabe im Fehlertext landet. Massnahmen: - Fremdtext im Werkzeugergebnis **abgegrenzt und als Daten gekennzeichnet**, nicht frei in den Fliesstext gemischt - getrennte Token: der Triage-Agent bekommt `bugtracker:read` plus gezielt `comment`, nicht `bugtracker:manage` mit allem dran - **kein selbsttaetiges Aufloesen und kein selbsttaetiger Commit** aus einem Lauf, der Fremdtext gelesen hat. Vorschlag ja, Ausfuehrung nein. REST-API und die Kurzfassung des Prompts bleiben bestehen — nicht jedes Werkzeug spricht MCP, und der Rueckfallweg kostet nichts, solange beide aus derselben Quelle beschrieben sind. --- ## 7. Quellcode-Zugriff fuer den Diagnostiker Drei Stufen, in aufsteigender Preisgabe: **Stufe 0 — der Agent laeuft bei dir.** Kein Quellcode im Deploymentcenter. Claude Code hat den Checkout ohnehin lokal und zieht sich Arbeit ueber `dc_next_task`. Neue Angriffsflaeche: null. Preis: Diagnose laeuft nur, wenn eine eigene Maschine laeuft. **Das ist der Startpunkt.** **Stufe 1 — Quelltext-Index im DC, nur Ausschnitte.** Noetig erst, wenn ein Agent autonom rund um die Uhr laufen soll. Dann aber keine klonbare Kopie, sondern eine Schnittstelle, die nie ein Ganzes herausgibt: GET /api/source/v1/snippet?commit=a21536f&file=…&line=42&context=40 GET /api/source/v1/search?q=…&limit=20 Neuer Scope `source:read`, nicht an Client-Token vergeben, verschluesselt abgelegt, Budget je Token und Tag, jeder Abruf im Pruefprotokoll. Der Unterschied zwischen "darf nachschlagen" und "darf mitnehmen". **Stufe 2 — nur Metadaten.** Signaturen, Aufrufgraph, Doc-Kommentare, ohne Methodenkoerper. Reicht zur Triage, reicht nicht zum Nachbauen. ### Symbol-Upload Unabhaengig von der Stufe: Der Packager laedt beim `publish` die PDB bzw. Sourcemap mit hoch, verknuepft mit `commit_sha`. Ausgeliefert wird ein gestripptes Binary. Der Kunde bekommt `at 0x4a2f`, du bekommst `UserAuthService.cs:42`. Kein Quellcode verlaesst das Haus, die Berichte werden trotzdem so gut wie mit Debug-Build. `dc_symbolicate` haengt daran. ### Was nicht funktioniert - Deploy-Key oder Repo-Token im Client — dekompiliert in Minuten - Quellcode verschluesselt mitliefern — der Client muss entschluesseln koennen, also kann es der Kunde auch - den Sprachmodell-Supervisor auf der Kundenmaschine — dann liegt der API-Schluessel dort, und aller Kontext im Speicher fremder Hardware - Obfuskation als Schutz — verzoegert, verhindert nicht --- ## 8. Datenbank **Erledigt — `sql/migrations/013_cross_project_reporting.sql`** (Etappe 1): - `dc_project_links` — `from_slug`, `to_slug`, `kind`, `integrated_version` - `bugtracker_items` — neue Spalten `reported_from`, `evidence` - `bugtracker_item_affects` — betroffene Projekte je Item - `bugtracker_items.status` — Wert `triage_external` ergaenzt **Erledigt — `sql/migrations/014_supervisor_findings.sql`** (Etappe 2): - `supervisor_findings` — Befunde nach dem Format aus Abschnitt 2 - `watchdog_monitors.project_slug` — Kohortenbildung fuer den Flottenvergleich - Taktgeber `supervisor_detectors` in `watchdog_cron_jobs` Scopes in `TokenManager::KNOWN_SCOPES`, ergaenzt: - `supervisor:report` — Befunde einliefern - `supervisor:read` — Befunde lesen - `supervisor:manage` — Befunde sichten und einstufen - `source:read` — nur fuer Stufe 1, spaeter `IMPLIED_SCOPES` entsprechend: `supervisor:report` und `supervisor:manage` schliessen `supervisor:read` ein. Dass Melden und Einstufen getrennt sind, ist Absicht: ein Beobachter auf Kundenhardware darf melden, aber nicht entscheiden, dass seine eigene Meldung erledigt ist. Etappe 1 brauchte keinen neuen Scope: die Unterscheidung laeuft ueber `owner_type = 'dev_agent'`, den `TokenManager::OWNER_TYPES` bereits kannte. --- ## 9. Etappen **Etappe 1 — MCP-Adapter ueber den Bestand. ERLEDIGT.** Werkzeuge fuer alles, was heute schon existiert: `dc_projects`, `dc_next_task`, `dc_get_item`, `dc_search`, `dc_report`, `dc_comment`, `dc_resolve`, `dc_release`, `dc_error_groups` — in `mcp/deploymentcenter-mcp.mjs`, ohne Fremdabhaengigkeiten. Dazu `dev_agent` in `enforceProject()`, `dc_project_links`, `reported_from`, `evidence`, `triage_external`. Kein Serverumbau, sofort nutzbar, ersetzt den Grossteil der Prompt-Vorlage. Noch offen aus dieser Etappe: ein Werkzeug, mit dem der Agent `integrated_version` fortschreibt (`ProjectLinks::record()` ist da, der Endpunkt fehlt), und das Zurueckziehen der Prompt-Vorlage in den Projekten. **Etappe 2 — Katalog und serverseitige Detektoren. ERLEDIGT.** Katalog in `src/Modules/Supervisor/Catalog.php`, Ablage in `FindingRepo`, Detektoren in `ServerDetectors` (haengen in `cli/tick.php`, laufen alle zehn Minuten), Schnittstelle unter `/api/supervisor/v1/`, dazu `dc_findings`, `dc_finding_summary` und `dc_metrics` im MCP-Adapter. **Nutzen ohne eine einzige Client-Aenderung.** Umgesetzt sind `novel.error_signature`, `silence.heartbeat`, `deviation.self`, `deviation.fleet` und `regression.build`. Offen aus 1.1 bleibt `novel.log_template` — dafuer muessten erst Logauszuege strukturiert hereinkommen. Eine Einschraenkung, die man kennen muss: `regression.build` vergleicht die beiden hoechsten Fassungen im Feld im **Querschnitt**, also verschiedene Maschinen zur selben Zeit — nicht dieselbe Maschine vor und nach dem Update. Ein echter Laengsschnitt braeuchte eine Historie der `app_version` je Monitor; das Feld wird heute ueberschrieben. Voraussetzung fuer `deviation.fleet` und `regression.build`: Monitore brauchen eine Projektzuordnung (`watchdog_monitors.project_slug`, neu in Migration 014). Sie wird administrativ gesetzt, nicht vom Agenten gemeldet — sonst braeuchte diese Etappe doch einen Rollout. Ohne Zuordnung laufen die uebrigen Detektoren weiter; ihre Befunde landen unter `supervisor.default_project`. **Etappe 3 — Supervisor-Client. ERLEDIGT.** `.NET` in `client-dotnet/Deploymentcenter.Client/Supervisor*.cs`, PHP als einzelne Datei in `client-php/DeploymentcenterSupervisor.php`, dazu `docs/SUPERVISOR_INTEGRATION_GUIDE.md`. Umgesetzt sind alle clientseitigen Detektoren aus 1.2 bis 1.4: `trend.monotonic`, `trend.saturation`, `trend.latency`, `swallowed.exception`, `fallback.usage`, `retry.storm`, `probe.failed`, `probe.slow`, `silence.periodic`, `invariant.violated`. Der PHP-Entwurf weicht notwendig ab: es gibt kein dauerhaft laufendes Programm, in dem ein Beobachter mitlaufen koennte. Der Zustand liegt deshalb in einer Datei unter Sperre, ausgewertet wird von der ersten Anfrage nach Ablauf des Intervalls, gesendet wird nach `fastcgi_finish_request()`. Proben laufen dadurch in einer echten Anfrage mit und muessen billig sein - das steht so in der Anleitung. Ausrollen ueber die Projekte, eines nach dem anderen. **Etappe 4 — Symbol-Upload und `dc_symbolicate`.** Packager erweitern, Symbolisierung serverseitig. **Etappe 5 — Quelltext-Index Stufe 1.** Nur falls ein autonomer Agent ohne laufende eigene Maschine gebraucht wird. Bis dahin bewusst offen gelassen. --- ## 10. Offene Punkte **Entschieden beim Umsetzen** (standen hier vorher als offen): - Aufbewahrung der Befunde: 30 Tage in `FindingRepo::purge()`, aufgerufen am Ende jedes Detektorlaufs. Deutlich kuerzer als bei Bugtracker-Items, weil Befunde um Groessenordnungen haeufiger entstehen. Entfernt werden nur erledigte, stummgeschaltete und uebernommene - ein offener Befund, der seit Wochen dasteht, ist eine unbeantwortete Frage und soll unbequem bleiben. - Kohortengroesse fuer `deviation.fleet`: fuenf, als `MIN_COHORT` in `ServerDetectors`. Darunter ist die Streuung so grob geschaetzt, dass jeder zweite Wert als Ausreisser durchginge. - `probe.slow` ist ein eigener Detektor geblieben. Er vergleicht gegen das gleitende Mittel der Probe selbst und nur ueber erfolgreiche Laeufe - `deviation.self` haette dafuer den falschen Massstab. **Weiterhin offen:** - `novel.log_template` aus Abschnitt 1.1 - dafuer muessten erst Logauszuege strukturiert hereinkommen. - Ein Laengsschnitt fuer `regression.build`. Braucht eine Historie der `app_version` je Monitor; das Feld wird heute ueberschrieben. - Die Schwellen der clientseitigen Trenderkennung (zehn Prozent Zuwachs ueber sechs Fenster) sind gesetzt, aber noch an keiner echten Installation nachgeprueft. > Wer hier etwas ergaenzt: Beim Umsetzen bitte auch wieder herausnehmen. Diese > Liste stand einmal auf einem Stand, den der Code laengst ueberholt hatte, und > hat prompt zu einer Fehlmeldung gefuehrt.