Sammelcommit fuer den ueber mehrere Sitzungen gewachsenen, bisher nicht
eingecheckten Stand. Getrennte Commits waeren ehrlicher gewesen, sind es
nachtraeglich aber nicht mehr: BugRepo, changelog.json und die Doku tragen
Aenderungen aus allen Straengen gleichzeitig, und keine Zwischenstufe waere
lauffaehig.
ROADMAP IM DEPLOYMENTCENTER (2.7.0)
Planungsstand, Reihenfolge und Zustaendigkeit lagen in handgepflegten
Markdown-Dateien neben einem Bugtracker, der genau diese drei Dinge bereits
fuehrt. Zwei Pfleger fuer dasselbe Feld - Drift war eine Frage der Zeit.
Ab jetzt: Zustand im DC, Begruendung in der Datei. Kein Feld hat zwei Pfleger.
- Migration 016: epic, roadmap_rank, target_build, defer_trigger,
doc_anchor, Status "deferred", Tabelle roadmap_epics.
KEINE Roadmap-Tabelle - ein Eintrag ist ein bugtracker_item.
- Zugehoerigkeit ist ein Feld: Ein Item steht auf der Roadmap, wenn es ein
epic hat. Ein zweites Kennzeichen daneben koennte auseinanderlaufen.
- Kennung ist die Item-ID. Handvergebene Kuerzel ("A12") erzeugen die
schlimmste Fehlerart: Beide Seiten stimmig, Verschiedenes gemeint, weil
die Kennung nach einer Loeschung neu vergeben wurde.
- Zurueckstellen verlangt defer_trigger. Ohne benannten Anlass ist ein
Vorhaben nicht zurueckgestellt, sondern vergessen. Die Regel sitzt im
Repository, damit sie auf allen drei Schreibwegen gleich greift.
- Modules/Bugtracker/Roadmap.php, /api/bugtracker/v1/roadmap.php,
WebUI-Modul mit Filtern, cli/roadmap.php --write/--check,
dc_roadmap und dc_roadmap_set im MCP-Adapter.
- cli/roadmap.php --write ERZEUGT den Zustandsteil der Markdown-Datei;
--check prueft nur die Prosa. Was erzeugt wird, kann nicht driften.
- docs/ROADMAP_MIGRATION.md: Uebernahme fuer die anderen Projekte.
TESTINSTANZ UND TESTTOR
- dc-dev.mhdf.de: zweite Installation, eigene DB, eigene Schluessel,
Basic-Auth davor, Rocket.Chat aus.
- 124 Testfaelle in tests/e2e gegen API, Rechte, Migrationen, Sperre.
- scripts/deploy.py bringt vor jedem Upload erst den anstehenden Stand auf
die Testinstanz und laesst dann den Testlauf laufen. Erst bei
Rueckgabewert 0 geht etwas auf die Produktion (--ohne-test als Notausgang).
Andersherum prueft der Lauf aelteren Code als den, der gleich hochgeht.
- tests/ ist aus dem Produktiv-Deploy ausgeschlossen; testctl.php kann
nicht versehentlich auf dc.mhdf.de landen.
- Ein Lauf mit mehr uebersprungenen als geprueften Faellen endet mit
Rueckgabewert 2 statt 0. Nichts ist kaputt, geprueft wurde es aber auch
nicht - der Unterschied darf nicht am Rueckgabewert verschwinden.
SUPERVISOR, PROJEKTLANDSCHAFT, NACHPRUEFUNG (2.6.0/2.6.1)
- Migration 013: projektuebergreifend melden (dev_agent, evidence,
triage_external, affects).
- Migration 014: supervisor_findings, Katalog, fuenf serverseitige
Detektoren im Tick.
- Migration 015: Nachpruefung als Arbeitsschlange statt Benachrichtigung.
- DEV-Lizenzschluessel zur Selbstbedienung, dc-testkit fuer die Test-VM.
- MCP-Adapter: 15 Werkzeuge, ohne Fremdabhaengigkeiten, mit Abgrenzung
von Fremddaten gegen Prompt-Injektion.
BEHOBEN
- observe und status im Supervisor legten den Zustand des Befundes als
"status" in die Antwort. Http::ok() merged ['status' => 'success']
darunter, also gewann der Befundzustand - eine angenommene Meldung kam
als status="open" an. Heisst jetzt finding_status. War Item #59.
Migrationen 013-016 sind auf dem Produktivserver noch NICHT ausgefuehrt.
Ohne sie bricht das WebUI, weil die Roadmap-Ansicht bei jedem Seitenaufruf
gegen bugtracker_items.epic abfragt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
619 lines
30 KiB
Markdown
619 lines
30 KiB
Markdown
# Roadmap
|
||
|
||
Der eine Ort für alles Geplante, Zurückgestellte und bewusst Verworfene.
|
||
|
||
Bis 2.6.0 lagen diese Angaben über mehrere Entwurfsdokumente verstreut — mit
|
||
der Folge, dass eine Liste offener Punkte noch als offen galt, obwohl der Code
|
||
sie längst erledigt hatte. Deshalb: **Was hier steht, gilt. Wer etwas umsetzt,
|
||
zieht den Eintrag hier nach.**
|
||
|
||
Die abgelösten Entwürfe liegen unter [archiv/](./archiv/) — sie enthalten die
|
||
ausführliche Begründung, aber keinen gültigen Stand mehr.
|
||
|
||
---
|
||
|
||
## Status-Kennzeichnung
|
||
|
||
| | Bedeutung |
|
||
|---|---|
|
||
| ✅ | Erledigt und ausgeliefert |
|
||
| 🔨 | In Arbeit |
|
||
| 📋 | Geplant, als Nächstes dran |
|
||
| 🧊 | **Zurückgestellt** — bewusst nicht jetzt, Auslöser genannt |
|
||
| ❌ | **Verworfen** — mit Begründung, nicht erneut vorschlagen |
|
||
| ⚙️ | Betriebsaufgabe, kein Code |
|
||
|
||
---
|
||
|
||
## Als Nächstes
|
||
|
||
1. **[I8] Migration 016 ausführen** — ohne sie steht das Roadmap-Modul, das
|
||
2.7.0 mitbringt, vor leeren Spalten
|
||
2. **[I9] Diese Datei selbst übernehmen** — das Verfahren einmal hier
|
||
durchlaufen, bevor die anderen Projekte es aus der Anleitung bekommen
|
||
3. **[B1] Befunde in der Oberfläche** — sie sind derzeit nur über API und MCP
|
||
erreichbar. Ohne Sicht auf die Befunde ist alles Weitere blind
|
||
4. **[G5] `dc-testkit findings`** — dasselbe von der Test-VM aus, und
|
||
Voraussetzung für G8
|
||
5. **[G8] Testartefakt oder echter Befund?** — die Frage, an der sich
|
||
entscheidet, ob Befunde aus Testläufen etwas wert sind
|
||
6. **[A4] Symbol-Upload und `dc_symbolicate`** — Stacktraces aus gestrippten
|
||
Binaries auflösen, ohne dass Quelltext das Haus verlässt
|
||
|
||
Davor stehen die Betriebsaufgaben ⚙️ aus Abschnitt E — ohne sie laufen zwei
|
||
der fünf serverseitigen Detektoren gar nicht.
|
||
|
||
**Diese Liste ist die letzte ihrer Art.** Ab I9 ergibt sie sich aus Reihenfolge
|
||
und Status und wird erzeugt, statt hier fortgeschrieben zu werden — sie ist
|
||
genau die Sorte Angabe, die von Hand zuverlässig veraltet.
|
||
|
||
Nicht mehr auf der Liste: der Supervisor im ausgelieferten Programm. Verworfen,
|
||
siehe H.
|
||
|
||
---
|
||
|
||
## A — Supervisor und Befunde
|
||
|
||
Der Supervisor beantwortet die Frage „ist das ungewöhnlich?". Die Frage „ist
|
||
das schlimm?" beantwortet das Deploymentcenter, wo Verlauf, Flotte und
|
||
Quelltext bekannt sind. Diese Trennung ist die Grundentscheidung des ganzen
|
||
Entwurfs — siehe [archiv/SUPERVISOR_MCP_DESIGN.md](./archiv/SUPERVISOR_MCP_DESIGN.md),
|
||
Abschnitt 0.
|
||
|
||
> **Der Supervisor lebt nur noch auf der Serverseite.** Ein Beobachter im
|
||
> ausgelieferten Programm ist verworfen (H) — er hätte zu viele Baustellen
|
||
> aufgemacht und wäre den Mehraufwand nicht wert gewesen. Was bleibt:
|
||
>
|
||
> - die **serverseitigen Detektoren**, die auf ohnehin eingehenden Daten
|
||
> arbeiten und nichts in den Anwendungen brauchen
|
||
> - der Eingang `POST /api/supervisor/v1/observe` für alles, was von außen
|
||
> meldet — heute Prüfwerkzeuge und Testläufe
|
||
> - der **Katalog** als gemeinsame Sprache für Befundnamen
|
||
>
|
||
> Der Zweck, den ein Client-Beobachter erfüllt hätte, ist bei
|
||
> **Error-Reporting und Bugtracker** besser aufgehoben. Die werden
|
||
> weiterentwickelt.
|
||
|
||
| | Vorhaben | Stand |
|
||
|---|---|---|
|
||
| A1 | Detektor-Katalog mit stabilen Namen (`Modules/Supervisor/Catalog.php`) | ✅ 2.6.0 |
|
||
| A2 | Fünf serverseitige Detektoren im Tick: `novel.error_signature`, `silence.heartbeat`, `deviation.self`, `deviation.fleet`, `regression.build` | ✅ 2.6.0 |
|
||
| A3 | ~~Supervisor-Client für .NET und PHP~~ | ❌ verworfen, siehe H |
|
||
| A4 | **Symbol-Upload und `dc_symbolicate`** | 📋 |
|
||
| A5 | `novel.log_template` — Logzeilen-Schablonen, die noch nie auftraten | 🧊 |
|
||
| A6 | Längsschnitt für `regression.build` | 🧊 |
|
||
| A7 | Schwellen der serverseitigen Detektoren an echten Daten nachprüfen | 📋 |
|
||
|
||
### A4 — Symbol-Upload und `dc_symbolicate` 📋
|
||
|
||
Der Packager lädt beim `publish` die PDB bzw. Sourcemap mit hoch, verknüpft mit
|
||
`commit_sha`. Ausgeliefert wird ein gestripptes Binary. Der Kunde bekommt
|
||
`at 0x4a2f`, du bekommst `UserAuthService.cs:42`.
|
||
|
||
Der Gewinn: Berichte werden so gut wie mit einem Debug-Build, **ohne dass
|
||
Quelltext das Haus verlässt**. Das ist der Hebel, der den größten Nutzen pro
|
||
Aufwand bringt — und die Voraussetzung dafür, dass ein Diagnose-Agent mit einer
|
||
Fehlermeldung überhaupt etwas anfangen kann.
|
||
|
||
Betroffen: `client-dotnet/Deploymentcenter.Packager`, ein Ablageort für
|
||
Symboldateien, `dc_symbolicate` im MCP-Adapter.
|
||
|
||
### A5 — `novel.log_template` 🧊
|
||
|
||
**Auslöser:** sobald Logauszüge strukturiert hereinkommen. Heute liefert nichts
|
||
sie in einer Form, aus der sich Schablonen bilden ließen.
|
||
|
||
### A6 — Längsschnitt für `regression.build` 🧊
|
||
|
||
`regression.build` vergleicht heute die beiden höchsten Fassungen im Feld im
|
||
**Querschnitt** — verschiedene Maschinen zur selben Zeit, nicht dieselbe
|
||
Maschine vor und nach dem Update. Bei gemischten Kohorten kann ein Unterschied
|
||
deshalb auch von der Maschine kommen statt von der Fassung.
|
||
|
||
**Auslöser:** wenn Fehlzuordnungen auffallen. Nötig wäre eine Historie der
|
||
`app_version` je Monitor; das Feld wird heute überschrieben.
|
||
|
||
### A7 — Schwellen nachprüfen 📋
|
||
|
||
Die serverseitigen Detektoren rechnen mit gesetzten, aber nirgends
|
||
nachgeprüften Werten: `SIGMA = 3.0` für `deviation.self` und `deviation.fleet`,
|
||
`MIN_COHORT = 5`, `REGRESSION_RATIO = 1.25`, `NOVEL_WINDOW_MIN = 120` — alle in
|
||
`ServerDetectors`.
|
||
|
||
Beurteilbar erst, wenn eine Weile echte Daten durchgelaufen sind. Die Frage
|
||
lautet für jeden Wert gleich: Wie viele der erzeugten Befunde hat jemand als
|
||
brauchbar eingestuft? Der Status `ignored` an den Befunden beantwortet das von
|
||
selbst, sobald gesichtet wird.
|
||
|
||
---
|
||
|
||
## B — Oberfläche
|
||
|
||
| | Vorhaben | Stand |
|
||
|---|---|---|
|
||
| B1 | **Befunde im WebUI: Liste, Filter nach Detektor, Einstufen** | 📋 |
|
||
| B2 | Fremdmeldungen sichtbar (`triage_external` in Filter, Abzeichen, Bearbeiten) | ✅ 2.6.0 |
|
||
| B3 | Monitoren ein Projekt zuweisen | 📋 |
|
||
|
||
### B1 — Befunde im WebUI 📋
|
||
|
||
Befunde sind heute nur über `/api/supervisor/v1/findings` und die MCP-Werkzeuge
|
||
erreichbar. Für die Sichtung durch einen Menschen fehlt die Ansicht — und damit
|
||
auch der einzige Weg, `supervisor:manage` sinnvoll zu nutzen.
|
||
|
||
Gebraucht wird: Zählung je Detektor als Einstieg, dahinter die Einzelbefunde
|
||
mit `observed`/`baseline`, und die Statuswechsel (`acknowledged`, `promoted`,
|
||
`resolved`, `ignored`). Beim Übernehmen in ein Bugtracker-Item die Verknüpfung
|
||
über `supervisor_findings.bug_item_id` setzen — die Spalte gibt es bereits.
|
||
|
||
### B3 — Monitoren ein Projekt zuweisen 📋
|
||
|
||
`watchdog_monitors.project_slug` wird administrativ gesetzt, nicht vom Agenten
|
||
gemeldet. Dafür fehlt das Bedienelement in der Monitor-Verwaltung. Bis dahin
|
||
nur per SQL — siehe E1.
|
||
|
||
---
|
||
|
||
## C — Projektlandschaft
|
||
|
||
| | Vorhaben | Stand |
|
||
|---|---|---|
|
||
| C1 | Projektübergreifend melden (`dev_agent`, `evidence`, `triage_external`, `affects`) | ✅ 2.6.0 |
|
||
| C2 | Beziehungen zwischen Projekten (`dc_project_links`, `integrated_version`) | ✅ 2.6.0 |
|
||
| C3 | **Rückkanal: „was du gemeldet hast, ist behoben"** | ✅ 2.6.1 — als Arbeitsschlange, nicht als Benachrichtigung |
|
||
| C4 | Agent-Prompt-Vorlage in den Projekten durch MCP ablösen | 📋 |
|
||
|
||
### C3 — Rückkanal ✅
|
||
|
||
Wird ein Item behoben, das ein anderes Projekt gemeldet hat, erfährt dieses
|
||
Projekt heute nichts davon. Folge: Es meldet denselben Punkt in drei Monaten
|
||
erneut und baut seinen Workaround nie zurück.
|
||
|
||
`GET /api/updateservice/v1/changelog?since=…` liefert bereits `action_items`.
|
||
Zu ergänzen ist der Abgleich über `bugtracker_item_affects`: „Item #42, das du
|
||
gemeldet hast, ist in 2.7.0 erledigt."
|
||
|
||
Das schließt den Kreis, den C1 geöffnet hat. Ohne ihn ist der Meldeweg ein
|
||
Briefkasten ohne Leerung.
|
||
|
||
**Gelöst in 2.6.1 — aber anders als hier ursprünglich gedacht.** Der Entwurf
|
||
sah eine Benachrichtigung vor. Gebaut wurde stattdessen eine Arbeitsschlange,
|
||
und das ist die bessere Antwort auf dieselbe Frage:
|
||
|
||
- **Passiv:** Wer erneut meldet, bekommt die Auskunft von selbst. Der
|
||
Report-Endpunkt vergleicht `build_version` gegen `resolved_in_build` und
|
||
antwortet mit `known_fixed_in`, statt ein Regressionsitem anzulegen.
|
||
- **Aktiv:** Ein veröffentlichter Fix stellt sein Item auf
|
||
`awaiting_verification`. Damit steht es in `?action=next` — auch beim
|
||
meldenden Fremdprojekt, über `bugtracker_item_affects`. Der Melder wird also
|
||
gefragt, ob der Fix bei ihm wirkt.
|
||
|
||
**Warum keine Zustellstrecke.** Agenten fragen ohnehin nach Arbeit. Ein Status,
|
||
der in der Warteschlangenabfrage vorkommt, *ist* die Zustellung — ohne
|
||
Speicher, ohne Entstörung, ohne Quittungen. Der Workaround-Fall, der die ganze
|
||
Diskussion trug, ist damit erledigt: Er brauchte keinen Push, sondern einen
|
||
Anlass, noch einmal hinzusehen.
|
||
|
||
Was bleibt: Wer einen Workaround gebaut hat, muss den Prüfauftrag auch
|
||
annehmen. Nimmt ihn niemand an, wird nach 30 Tagen ungeprüft geschlossen — mit
|
||
einem Vermerk, der das ausdrücklich sagt.
|
||
|
||
### C4 — Prompt-Vorlage entlasten 📋
|
||
|
||
[AGENT_PROMPT_TEMPLATE.md](./AGENT_PROMPT_TEMPLATE.md) ist in jedes Projekt
|
||
einkopiert, samt der von Hand gepflegten Versionszeile.
|
||
|
||
**Der Zuschnitt hat sich mit 2.6.1 geändert.** Ursprünglich stand hier
|
||
„durch MCP ablösen". Inzwischen gibt es drei Wege zum Deploymentcenter, und
|
||
keiner löst die anderen ab:
|
||
|
||
| Wo der Agent arbeitet | Weg | Was er braucht |
|
||
|---|---|---|
|
||
| Projektverzeichnis mit `.mcp.json` | MCP-Adapter | keine Vorlage |
|
||
| Linux-Test-VM | `dc-testkit` | Kurzfassung, kein `curl` |
|
||
| alles Übrige | REST direkt | die volle Vorlage |
|
||
|
||
Die Vorlage bleibt also — sie ist der Rückfallweg und beschreibt zugleich, was
|
||
`dc-testkit` tut. Zu tun ist trotzdem etwas: In Projekten **mit** eingerichtetem
|
||
Adapter kann sie auf die Kurzfassung schrumpfen, und die handgepflegte
|
||
Versionszeile ersetzt in allen Fällen `dc_link_project`.
|
||
|
||
Das ist der Punkt, an dem es sich lohnt, die Vorlage in drei Bausteine zu
|
||
zerlegen statt in einen Block: Grundlagen, „mit MCP", „auf der Test-VM". Heute
|
||
trägt jedes Projekt alles mit.
|
||
|
||
---
|
||
|
||
## D — Werkzeuganbindung (MCP)
|
||
|
||
| | Vorhaben | Stand |
|
||
|---|---|---|
|
||
| D1 | stdio-Adapter mit 13 Werkzeugen, ohne Fremdabhängigkeiten | ✅ 2.6.0 |
|
||
| D2 | Fremddaten im Werkzeugergebnis abgegrenzt kennzeichnen | ✅ 2.6.0 |
|
||
| D3 | Abgleich: Werkzeugliste gegen `openapi.php` | 📋 |
|
||
| D4 | Entfernter MCP-Server unter `/mcp` mit OAuth | 🧊 |
|
||
| D5 | `dc_roadmap` und `dc_roadmap_set` — Planungsstand als Werkzeug | ✅ 2.7.0 (siehe I) |
|
||
|
||
### D3 — Abgleich Werkzeugliste ↔ OpenAPI 📋
|
||
|
||
Adapter und OpenAPI beschreiben dieselben Endpunkte. Ohne Abgleich laufen sie
|
||
auseinander, und es fällt erst auf, wenn ein Werkzeug ins Leere greift.
|
||
|
||
Das Projekt hat **keine CI-Strecke**. Als Erstes reicht deshalb ein Skript, das
|
||
von Hand oder aus `deploy.py` heraus läuft. Eine echte Pipeline wäre ein
|
||
eigenes Vorhaben und lohnt erst, wenn es mehr zu prüfen gibt als diese eine
|
||
Zusage.
|
||
|
||
### D4 — Entfernter Server 🧊
|
||
|
||
**Auslöser:** wenn mehrere Maschinen oder Personen dranhängen. Dann aber mit
|
||
OAuth statt Bearer-Token in einer Konfigurationsdatei — sonst liegt dasselbe
|
||
Token auf jeder Maschine. Solange der stdio-Adapter je Projekt reicht, lohnt
|
||
der Aufwand nicht.
|
||
|
||
---
|
||
|
||
## E — Betrieb
|
||
|
||
Kein Code, aber Voraussetzung dafür, dass Gebautes wirkt.
|
||
|
||
| | Aufgabe | Stand |
|
||
|---|---|---|
|
||
| E1 | Migrationen 013 und 014 auf dem Server ausführen | ⚙️ |
|
||
| E2 | PHP-Seite von 2.6.0 prüfen — auf der Entwicklungsmaschine lief kein Lint | ⚙️ |
|
||
| E3 | Monitoren ein Projekt zuordnen (`watchdog_monitors.project_slug`) | ⚙️ |
|
||
| E4 | Je Projekt ein Werkbank-Token (`dev_agent`) anlegen | ⚙️ |
|
||
| E5 | Supervisor-Vorbereitungen in den Projekten zurückbauen | ⚙️ |
|
||
|
||
**E3 ist Voraussetzung für `deviation.fleet` und `regression.build`.** Ohne
|
||
Zuordnung überspringen beide Detektoren die betroffenen Monitore; die übrigen
|
||
drei laufen weiter.
|
||
|
||
**E4 vor E5.** Ohne Werkbank-Token laufen `dc_link_project` und `dc_report` aus
|
||
den Projekten heraus ins Leere.
|
||
|
||
**E2 gehört auf die Test-VM.** Die gesamte PHP-Seite von 2.6.0 — Migrationen
|
||
013 und 014, der Supervisor-Endpunkt, das projektübergreifende Melden — wurde
|
||
auf einer Maschine ohne PHP geschrieben. Weder Lint noch ein Lauf haben sie je
|
||
gesehen. Seit 2.6.1 gibt es die geteilte Test-VM (Abschnitt G); dort gehört das
|
||
geprüft, bevor es auf den Produktivserver geht. Mindestens:
|
||
|
||
```bash
|
||
find src public cli -name '*.php' -print0 | xargs -0 -n1 php -l
|
||
php cli/migrate.php
|
||
php cli/tick.php # ohne --quiet: zeigt den Detektorlauf
|
||
```
|
||
|
||
**E5 ist reiner Rückbau geworden.** In mehreren Projekten wurden
|
||
Vorbereitungen für einen lokalen Supervisor begonnen — UI-Steuerelemente,
|
||
teilweise ein KI-Agent. Da der Client-Supervisor verworfen ist (H), fällt das
|
||
ersatzlos weg; nichts tritt an seine Stelle. Was an den Vorbereitungen wertvoll
|
||
ist, ist die Überlegung, **worauf** zu achten wäre — die gehört als Prüfung in
|
||
die Testläufe oder als Fehlermeldung in den Bugtracker, nicht in ein
|
||
Beobachterteil.
|
||
|
||
Der Auftrag zum Einfügen steht in
|
||
[SUPERVISOR_INTEGRATION_GUIDE.md](./SUPERVISOR_INTEGRATION_GUIDE.md).
|
||
|
||
---
|
||
|
||
## F — Quelltext-Zugriff für die Diagnose
|
||
|
||
Die Software bleibt geschlossen. Es gibt keine öffentliche Stelle, an der
|
||
Quelltext zu sehen ist. Drei Stufen, in aufsteigender Preisgabe:
|
||
|
||
| | Stufe | Stand |
|
||
|---|---|---|
|
||
| F1 | **Stufe 0** — Diagnose-Agent läuft auf eigener Maschine mit lokalem Checkout | ✅ Der gegenwärtige Weg |
|
||
| F2 | **Stufe 1** — Quelltext-Index im DC, nur Ausschnitte | 🧊 |
|
||
| F3 | **Stufe 2** — nur Metadaten: Signaturen, Aufrufgraph, keine Rümpfe | 🧊 |
|
||
|
||
### F2 — Quelltext-Index Stufe 1 🧊
|
||
|
||
**Auslöser:** wenn ein Agent autonom rund um die Uhr laufen soll, ohne dass
|
||
eine eigene Maschine läuft. Solange Claude Code den Checkout ohnehin lokal hat,
|
||
wäre das zusätzliche Angriffsfläche ohne Gegenwert.
|
||
|
||
Falls es kommt, dann als 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`, nie an Client-Token, verschlüsselt abgelegt, Budget
|
||
je Token und Tag, jeder Abruf im Prüfprotokoll. Der Unterschied zwischen „darf
|
||
nachschlagen" und „darf mitnehmen".
|
||
|
||
### F3 — Stufe 2 🧊
|
||
|
||
**Auslöser:** falls selbst Ausschnitte zu viel sind. Signaturen, Aufrufgraph
|
||
und Doc-Kommentare ohne Methodenkörper reichen zur Triage, aber nicht zum
|
||
Nachbauen.
|
||
|
||
---
|
||
|
||
## G — Testumgebung und Selbstbedienung
|
||
|
||
Die geteilte Linux-Test-VM. Anleitung: **[TESTUMGEBUNG.md](./TESTUMGEBUNG.md)** — dort
|
||
steht auch, was auf der Maschine belegt ist.
|
||
|
||
| | Vorhaben | Stand |
|
||
|---|---|---|
|
||
| G1 | **Kopfloser Installationsmodus fuer den `update-agent`** | 📋 |
|
||
| G2 | DEV-Lizenzschluessel zur Selbstbedienung (`POST /api/license/v1/dev-key`, Scope `license:dev`) | ✅ 2.6.1 |
|
||
| G3 | `dc-testkit` — ein Weg fuer Lizenz, Auslieferung und Meldung | ✅ 2.6.1 |
|
||
| G4 | Werkbank-Token je Projekt auf der Test-VM hinterlegen | ⚙️ |
|
||
| G5 | **`dc-testkit supervisor` — prüfen, ob eine Anbindung wirklich meldet** | 📋 |
|
||
| G6 | Test-Monitore aus dem Flottenvergleich heraushalten | 📋 |
|
||
| G7 | Befunde tragen die Umgebung, ausserhalb `production` eine Stufe niedriger | ✅ 2.6.1 |
|
||
| G8 | **Testartefakt oder echter Befund? — die offene Frage** | 📋 |
|
||
| G8 | Nachpruefung als Arbeitsschlange (`awaiting_verification`, `in_verification`, `fix_insufficient`) | ✅ 2.6.1 |
|
||
| G9 | Auswertung über `meta_json`: wie oft fällt ein Fix durch die Prüfung? | 🧊 |
|
||
|
||
### G1 — Kopfloser Installationsmodus 📋
|
||
|
||
`update-agent --action install` ist ein Dialog mit Auswahllisten und Passwortabfrage. Ein
|
||
Agent kann ihn nicht treiben: Auswahllisten brauchen Pfeiltasten an einem echten Terminal,
|
||
und ein Agent darf grundsaetzlich kein Passwort eingeben.
|
||
|
||
Folge: `dc-testkit install` prueft die **Auslieferung** in ein leeres Verzeichnis — denselben
|
||
Pfad, den der Installer intern nimmt, mit Download, SHA256, Signatur, Staging und Rollback.
|
||
Ungeprueft bleiben damit die Aufloesung von `setup.json` und das Schreiben der Konfiguration.
|
||
Das ist genau der Teil, der je Anwendung anders aussieht und deshalb am ehesten bricht.
|
||
|
||
Gebraucht wird `--action install --answers antworten.json`: dieselben Felder, die der Dialog
|
||
erfragt, aus einer Datei. Fehlt ein Pflichtfeld, bricht der Lauf ab, statt zu fragen. Das
|
||
Installationskonto bliebe dabei aussen vor — mit einem DEV-Lizenzschluessel kommt der Agent
|
||
ohnehin an die Release-Ablage.
|
||
|
||
Betroffen: `client-dotnet/Deploymentcenter.UpdateAgent/Installation.cs`.
|
||
|
||
### G5 — `dc-testkit findings` 📋
|
||
|
||
Die Nahtstelle zwischen Testumgebung und Supervisor, die heute fehlt.
|
||
|
||
Ein Testlauf erzeugt Befunde — teils durch `novel.error_signature` aus den
|
||
gemeldeten Fehlern, teils künftig direkt über `observe`. Sehen kann man sie von
|
||
der VM aus nicht: `dc-testkit` kennt `doctor`, `license`, `install`, `update`,
|
||
`run`, `projects` und `report`, aber nichts zum Supervisor.
|
||
|
||
Gebraucht wird wenig:
|
||
|
||
```
|
||
dc-testkit findings # was hat dieser Lauf ausgelöst?
|
||
dc-testkit findings --env all # auch das, was in production auffiel
|
||
```
|
||
|
||
Dahinter `GET /api/supervisor/v1/findings?project_slug=…`. Derselbe Zuschnitt
|
||
wie `dc_findings` im MCP-Adapter — die Abfrage existiert, es fehlt nur der Weg
|
||
dorthin von der VM aus.
|
||
|
||
Das ist zugleich die Voraussetzung für G8: Ohne Sicht auf die eigenen Befunde
|
||
kann niemand entscheiden, ob einer ein Artefakt des Prüfstands war.
|
||
|
||
Das Token braucht dafür zusätzlich `supervisor:read`; heute trägt es auf der
|
||
VM nur `bugtracker:manage` und `license:dev` (§4.2 der Anleitung).
|
||
|
||
### G6 — Test-Monitore aus dem Flottenvergleich 📋
|
||
|
||
`deviation.fleet` bildet Kohorten aus (Projekt, `app_version`) und meldet, wer
|
||
daraus ausschert. `watchdog_monitors` hat **kein** Feld für die Umgebung.
|
||
|
||
Bekommt die Test-VM einen Monitor mit demselben Projekt und derselben Fassung
|
||
wie die Produktivinstallationen, landet sie in deren Kohorte — und fällt dort
|
||
zwangsläufig auf: andere Maschine, andere Last, andere Plattenbelegung. Das
|
||
Ergebnis wären Befunde, die nichts über die Software aussagen, dafür aber die
|
||
Kohortenwerte verschieben und damit echte Ausreißer verdecken.
|
||
|
||
Zwei Wege, beide vertretbar:
|
||
|
||
- ein Feld `environment` an `watchdog_monitors`, und `deviation.fleet` sowie
|
||
`regression.build` sehen nur `production` an
|
||
- oder eine Kennzeichnung über `group_key`, ohne Schemaänderung
|
||
|
||
Solange auf der VM kein Monitor mit Produktivfassung läuft, ist nichts kaputt.
|
||
Es fällt nur genau dann auf, wenn es zu spät ist — deshalb hier vermerkt.
|
||
|
||
### G7 — Umgebung am Befund ✅ 2.6.1
|
||
|
||
Testläufe **sollen** Befunde erzeugen — ein Lauf, der einen Fehler auslöst, den
|
||
es vorher nicht gab, hat genau das getan, wofür er da ist. Die Detektoren
|
||
laufen deshalb in jeder Umgebung.
|
||
|
||
Unterschieden wird zweifach: über `environment` am Befund, und über den
|
||
Schweregradhinweis. Was außerhalb von `production` auffällt, ist eine Stufe
|
||
niedriger eingestuft — nicht weil es unwichtig wäre, sondern weil dort
|
||
systematisch mehr Rauschen entsteht. Wer beides gleich hoch einstuft, liest
|
||
bald keines von beiden mehr.
|
||
|
||
### G8 — Testartefakt oder echter Befund? 📋
|
||
|
||
**Die eigentlich schwierige Frage.** Ein Testlauf meldet „API-Aufruf
|
||
fehlgeschlagen". Liegt das daran, dass auf der VM keine Live-Zugangsdaten
|
||
liegen — oder wäre es beim Kunden genauso passiert?
|
||
|
||
Vollständig automatisch ist das nicht zu beantworten. Vier Ansätze, die
|
||
zusammen den Aufwand aber klein halten:
|
||
|
||
**1. Der Prüfstand sagt, was ihm fehlt.**
|
||
Die Testumgebung weiß, was sie *nicht* hat: keine Zahlungs-API, kein echter
|
||
SMTP, DEV-Lizenz statt Kundenlizenz. Wird das einmal als Liste hinterlegt und
|
||
bei jeder Meldung mitgeschickt, lässt sich ein Befund, der eine bekannte Lücke
|
||
berührt, sofort als `environment_limited` kennzeichnen. Das ist der billigste
|
||
Schritt und nutzt Wissen, das ohnehin vorhanden und stabil ist.
|
||
|
||
**2. Die Umkehrung: nicht das Scheitern zählt, sondern der Umgang damit.**
|
||
Der wichtigste Gedanke hier. Fehlende Zugangsdaten sind ein Artefakt — *wie die
|
||
Software darauf reagiert*, ist es nicht. Läuft sie in eine endlose
|
||
Wiederholung? Schluckt sie den Fehler? Bleibt Zustand halb geschrieben zurück?
|
||
Landet das Passwort im Protokoll?
|
||
|
||
Das sind Produktionsbefunde, auch wenn der Auslöser künstlich war — denn in
|
||
Produktion laufen Zugangsdaten ab, werden rotiert, fällt eine Gegenstelle aus.
|
||
**Der Prüfstand ist damit kein Störfaktor, sondern eine billige
|
||
Fehlereinspeisung.** Ein `retry.storm`, ausgelöst durch fehlende Zugangsdaten,
|
||
ist ein echter Befund.
|
||
|
||
**3. Vergleich über Umgebungen statt Beurteilung des Einzelfalls.**
|
||
Feuert derselbe Detektor mit demselben `subject` auch in `production`, ist die
|
||
Frage beantwortet. Feuert er ausschließlich in `development`, ist er
|
||
verdächtig. Das ist dieselbe Mechanik wie bei `deviation.fleet`, nur über
|
||
Umgebungen statt über Installationen — Populationen vergleichen, nicht
|
||
Einzelbefunde deuten.
|
||
|
||
**4. Einmal entscheiden, nicht jedes Mal.**
|
||
Was übrig bleibt, entscheidet ein Mensch oder ein Agent — aber **je Signatur,
|
||
nicht je Vorkommnis**. Dafür gibt es das Vorbild bereits: `IgnoreRules` im
|
||
Bugtracker (Muster, Begründung, Trefferzähler). Ein Befund, der einmal als
|
||
Artefakt eingestuft wurde, bleibt es für seine Signatur und zählt trotzdem
|
||
weiter hoch — fällt er plötzlich häufiger an, sieht man es.
|
||
|
||
Die Kosten sind damit eine Entscheidung je neuer Signatur, nicht je Lauf. Das
|
||
ist tragbar; alles darüber hinaus wäre Rätselraten mit mehr Schritten.
|
||
|
||
**Reihenfolge:** 1 und 4 zuerst — beide klein und sofort wirksam. 3 ergibt sich
|
||
fast von selbst, sobald Befunde aus beiden Umgebungen nebeneinander liegen. 2
|
||
ist keine Umsetzung, sondern eine Lesehaltung: beim Sichten nicht fragen
|
||
„warum ist das fehlgeschlagen", sondern „wie hat sich die Software dabei
|
||
verhalten".
|
||
|
||
### G9 — Auswertung der Statuswechsel 🧊
|
||
|
||
**Auslöser:** wenn die Frage „wie oft trägt ein Fix nicht?" tatsächlich gestellt
|
||
wird. Seit 2.6.1 schreibt jeder Statuswechsel strukturiertes `meta_json`
|
||
(`from`, `to`, `actor`, `since`) in `bugtracker_comments`. Damit lassen sich
|
||
Verweildauern und Durchläufe auswerten, **ohne** eine Historientabelle daneben.
|
||
|
||
Eine eigene Tabelle verdient sich erst bei Fragen über Items hinweg — Median der
|
||
Prüfdauer, Quote durchgefallener Fixes je Projekt. Vorher wäre sie eine zweite
|
||
Wahrheit über denselben Vorgang.
|
||
|
||
### G4 — Werkbank-Token auf der Test-VM ⚙️
|
||
|
||
Ohne das Token laufen `dc-testkit license` und `dc-testkit report` ins Leere. Je Projekt eines
|
||
anlegen (Besitzerart `dev_agent`, Rechte `bugtracker:manage` und `license:dev`), auf der VM
|
||
unter `~/.config/dc-testkit/` hinterlegen und in der Belegungsliste vermerken. Deckt sich mit
|
||
E4 — dasselbe Token traegt beides.
|
||
|
||
---
|
||
|
||
## I — Roadmap im Deploymentcenter
|
||
|
||
Diese Datei war bis 2.6.1 der einzige Ort für Planung — und pflegte damit
|
||
Status, Reihenfolge und Zuständigkeit von Hand, neben einem Bugtracker, der
|
||
genau diese drei Dinge bereits führt. Zwei Pfleger für dasselbe Feld.
|
||
|
||
Ab 2.7.0 gilt die Arbeitsteilung: **Zustand im DC, Begründung hier.**
|
||
|
||
| | Vorhaben | Stand |
|
||
|---|---|---|
|
||
| I1 | Migration 016: `epic`, `roadmap_rank`, `target_build`, `defer_trigger`, `doc_anchor`, Status `deferred`, Tabelle `roadmap_epics` | ✅ 2.7.0 |
|
||
| I2 | `Modules/Bugtracker/Roadmap.php` — Sicht, Reihenfolge, Erzeugung, Abgleich | ✅ 2.7.0 |
|
||
| I3 | `/api/bugtracker/v1/roadmap.php` — list, epics, next, active, render, check, set, move, reorder, epic | ✅ 2.7.0 |
|
||
| I4 | WebUI-Modul **Roadmap**: Übersicht, Liste, Aufnahmeliste, Themenbereiche | ✅ 2.7.0 |
|
||
| I5 | `cli/roadmap.php --write/--check/--list` | ✅ 2.7.0 |
|
||
| I6 | `dc_roadmap`, `dc_roadmap_set` im MCP-Adapter | ✅ 2.7.0 |
|
||
| I7 | Übernahmeleitfaden für die anderen Projekte | ✅ 2.7.0 — [ROADMAP_MIGRATION.md](./ROADMAP_MIGRATION.md) |
|
||
| I8 | **Migration 016 auf dem Server ausführen** | ⚙️ |
|
||
| I9 | **Diese Datei selbst übernehmen** — Einträge A1–H als Items anlegen, Kennungen auf Item-IDs umstellen | 📋 |
|
||
| I10 | Die anderen Projekte übernehmen (myapp, polytrader, predictalytics) | 📋 |
|
||
| I11 | `--check` in `scripts/deploy.py` einhängen | 📋 |
|
||
| I12 | Auswertung: wie lange steht ein Vorhaben in welcher Lage? | 🧊 |
|
||
|
||
### I1–I7 — der gebaute Teil ✅
|
||
|
||
Kein neues Modul und keine Roadmap-Tabelle: Ein Roadmap-Eintrag **ist** ein
|
||
`bugtracker_item`. Es fehlten nur vier Angaben, die ein Backlog nicht braucht
|
||
und eine Planung schon — Themenbereich, Reihenfolge, Zielfassung und der
|
||
Auslöser für Zurückgestelltes.
|
||
|
||
**Die Zugehörigkeit ist ein Feld.** Ein Item steht auf der Roadmap, wenn es ein
|
||
`epic` hat. Ein zweites Kennzeichen daneben wären zwei Angaben, die dasselbe
|
||
behaupten und auseinanderlaufen können.
|
||
|
||
**Die Kennung ist die Item-ID.** Handvergebene Kürzel (`A12`) erzeugen die
|
||
schlimmste Fehlerart: Beide Seiten sind für sich stimmig und meinen
|
||
Verschiedenes, weil die Kennung nach einer Löschung neu vergeben wurde.
|
||
AUTO_INCREMENT vergibt nie zweimal dieselbe Nummer — eine gelöschte Zeile
|
||
hinterlässt eine hängende Referenz, und die *meldet* der Abgleich.
|
||
|
||
**Zurückstellen verlangt einen Auslöser.** `status = deferred` ohne
|
||
`defer_trigger` wird abgelehnt, in Repository, API und Oberfläche gleichermaßen.
|
||
Ohne benannten Anlass ist ein Vorhaben nicht zurückgestellt, sondern vergessen —
|
||
und die Regel gehört an die Stelle, an der geschrieben wird, nicht nur in ein
|
||
Formular.
|
||
|
||
### I9 — diese Datei übernehmen 📋
|
||
|
||
Die Einträge A1–G9 stehen noch als handvergebene Kürzel hier. Sie werden Items;
|
||
die Abschnitte werden Themenbereiche (in Migration 016 bereits angelegt).
|
||
Danach ersetzt ein erzeugter Block die Statustabellen, und die Prosa bleibt.
|
||
|
||
**Reihenfolge:** erst I8 (Migration), dann I9, dann I11 (Abgleich im Deploy).
|
||
I10 kommt zuletzt — die anderen Projekte bekommen ein Verfahren, das hier
|
||
einmal durchlaufen ist, nicht eines aus der Anleitung.
|
||
|
||
Bis dahin gilt diese Datei unverändert weiter. Sie ist erst abgelöst, wenn der
|
||
Block darin steht.
|
||
|
||
### I12 — Verweildauern 🧊
|
||
|
||
**Auslöser:** wenn die Frage „warum dauert das so lange?" tatsächlich gestellt
|
||
wird. `status_changed_at` und das strukturierte `meta_json` aus 2.6.1 tragen
|
||
die Antwort bereits; eine Auswertung daneben lohnt erst, wenn jemand sie liest.
|
||
|
||
---
|
||
|
||
## H — Verworfen
|
||
|
||
Diese Punkte sind geprüft und abgelehnt. **Nicht erneut vorschlagen** — und
|
||
falls doch, dann nur mit einem Argument, das hier noch nicht steht.
|
||
|
||
| Vorschlag | Warum nicht |
|
||
|---|---|
|
||
| ❌ **Supervisor-Beobachter im ausgelieferten Programm** (auch regelbasiert, ohne Sprachmodell) | Zu viele Baustellen für den Ertrag. Er hätte in jeder Anwendung Einbau, Rückbau bestehender Vorbereitungen, eigenen Zustand auf Kundenhardware, ein weiteres Token im Binary und eine zweite Fassungspflege gebraucht — und dabei überwiegend das gemeldet, was Error-Reporting und Bugtracker ohnehin abdecken. Der Code war fertig und ist am 29.08.2026 wieder entfernt worden; er liegt in der Historie, falls die Abwägung je anders ausfällt. **Stattdessen:** Error-Reporting und Bugtracker weiterentwickeln, Befunde serverseitig ermitteln |
|
||
| ❌ Sprachmodell-Supervisor auf der Kundenmaschine | API-Schlüssel läge auf fremder Hardware; Kontext im Speicher fremder Maschinen; kann nicht im Minutentakt hinsehen; hat keinen Verlauf und sieht die Flotte nicht; antwortet zweimal verschieden auf dieselbe Lage |
|
||
| ❌ Quelltext mit dem Client ausliefern, auch verschlüsselt | Der Client muss entschlüsseln können, also kann es der Kunde auch |
|
||
| ❌ Deploy-Key oder Repo-Token im Client | Dekompiliert in Minuten |
|
||
| ❌ Obfuskation als Schutz einplanen | Verzögert, verhindert nicht |
|
||
| ❌ MCP-Werkzeuge 1:1 aus OpenAPI erzeugen | 24 Endpunkte; Werkzeugdefinitionen liegen dauerhaft im Kontextfenster. Ein aufgeblähter Adapter wäre schlechter als die Prompt-Vorlage, die er ersetzt |
|
||
| ❌ `publish`, `provision`, `deactivate` als MCP-Werkzeug | Ein Release gehört in die CI, nicht an ein Werkzeug, das ein Modell im Zweifel „hilfreich" auslöst |
|
||
| ❌ Befunde puffern, wenn das DC ausfällt | Eine wachsende Warteschlange in einer ohnehin auffälligen Anwendung ist genau der Schaden, den der Supervisor verhindern soll |
|
||
| ❌ Benachrichtigung je Befund | Ein Befund behauptet nicht, dass etwas kaputt ist. Wer bei jeder Auffälligkeit alarmiert, hat nach einer Woche einen Kanal, den niemand mehr liest |
|
||
| ❌ Lokale Befund-Oberfläche in den Anwendungen | Zweite Wahrheit, die nur den eigenen Ausschnitt kennt. Der Client hält keine Historie vor |
|
||
| ❌ `enforceProject()` pauschal für `dev_agent` öffnen | Hätte auch `publish` und `setup` in fremden Projekten erlaubt. Die Ausnahme wird je Aufrufstelle gesetzt |
|
||
| ❌ Feste Schwellwerte je Kennzahl als Hauptweg | Finden nur, woran vorher jemand gedacht hat. Die tragenden Detektoren vergleichen gegen eigenen Verlauf, Vorversion oder Flotte |
|
||
|
||
---
|
||
|
||
## Pflege dieser Datei
|
||
|
||
**Bis I9 abgeschlossen ist**, gilt weiterhin von Hand:
|
||
|
||
- Ein Vorhaben umgesetzt? Zeile auf ✅ setzen und die Fassung dazuschreiben.
|
||
- Etwas verworfen? Nach H, **mit Begründung**. Die Begründung ist der Wert des
|
||
Eintrags, nicht die Ablehnung.
|
||
- Etwas zurückgestellt? Nach 🧊, **mit Auslöser**. Ohne Auslöser ist es nicht
|
||
zurückgestellt, sondern vergessen.
|
||
- Ausführliche Herleitungen gehören ins Archiv, nicht hierher. Diese Datei soll
|
||
lesbar bleiben.
|
||
|
||
**Danach** gilt die Arbeitsteilung aus Abschnitt I:
|
||
|
||
| | Wahrheit | Die andere Seite hält |
|
||
|---|---|---|
|
||
| Status, Reihenfolge, Zielfassung, Bearbeiter | **Deploymentcenter** | den erzeugten Block zwischen `<!-- dc:roadmap -->`-Markern |
|
||
| Begründung, Auslöser, Verworfenes | **diese Datei**, außerhalb der Marker | den Verweis `doc_anchor` am Item |
|
||
|
||
- Ein Vorhaben entsteht **immer im DC**, nie hier. `dc_report` legt es an,
|
||
`dc_roadmap_set` hebt es auf die Roadmap, dann erst kommt die Prosa dazu.
|
||
So kann ein Punkt, der nur in einer Datei steht und den niemand angeht, gar
|
||
nicht erst entstehen.
|
||
- Zwischen den Markern **nichts von Hand ändern**. `php cli/roadmap.php --write`
|
||
überschreibt es beim nächsten Lauf.
|
||
- Vor dem Ausliefern `php cli/roadmap.php --check --project=deploymentcenter`.
|
||
Rückgabewert 1 heißt: Ein Absatz verweist auf ein Item, das es nicht gibt.
|
||
- 🧊 und ❌ behalten ihren Absatz hier. Der Statuswert allein sagt nicht, warum —
|
||
und ohne das Warum schlägt es der nächste Agent wieder vor.
|