Bis hierher galt eine Zweiteilung: Zustand im Deploymentcenter, Begruendung in docs/ROADMAP.md, verbunden ueber doc_anchor. Die Beschreibung der uebernommenen Eintraege sagte es woertlich - "Die Begruendung steht weiterhin in der Datei - hier steht nur der Zustand." Zwei Folgen, die erst im Betrieb sichtbar wurden: 1. Die Roadmap-Tafel kann die Begruendung nicht zeigen. Sie sieht die Datenbank; die Datei liegt auf einem Entwicklungsrechner. Im Seitenpanel stand deshalb nur doc_anchor als nicht anklickbarer Text mit dem Hinweis, er zeige auf etwas, das das WebUI nie zu sehen bekommt. 2. Schwerer: Die Beschreibung von dc_roadmap wies Agenten an, vor dem erneuten Vorschlagen eines zurueckgestellten Vorhabens "diesen Absatz" zu lesen. Ein Agent in polytrader oder clawddotnet kann ihn nicht lesen - er liegt in einem fremden Repository. Die Anweisung war nicht befolgbar. Dazu kam, dass cli/roadmap.php --check PHP braucht und auf dem Windows-Arbeitsplatz keines liegt: Die Haelfte der Pflegemaschinerie, die die Zweiteilung zusammenhalten sollte, lief dort nie. == Was sich aendert == bugtracker_items und roadmap_epics tragen rationale (Migration 020). Ein EIGENES Feld neben description, nicht statt dessen: description sagt, was gemeldet wurde, und kommt oft von einer fremden Maschine; rationale sagt, warum wir uns so entschieden haben. Zusammengelegt haette jede redaktionelle Ueberarbeitung den urspruenglichen Wortlaut der Meldung ueberschrieben, also die Grundlage, auf der entschieden wurde. Der Verlauf vermerkt nur, DASS die Begruendung sich geaendert hat und um wie viele Zeichen. Der ganze Absatz ein zweites Mal im Verlauf haette ihn nach der fuenften Ueberarbeitung unlesbar gemacht. == Der Weg herauf, einmalig == ?action=import_rationale liest eine mitgeschickte Roadmap-Datei. Drei Formen werden erkannt: Bereichsabschnitte, Vorhabensabschnitte und Tabellenzeilen. Die dritte ist kein Beiwerk - der Abschnitt "Verworfen" fuehrt seine zwoelf Ablehnungen als Tabelle, und ohne sie bliebe ausgerechnet das nicht am Item auffindbar, was am haeufigsten gebraucht wird: warum etwas schon einmal abgelehnt wurde. Ohne overwrite=true bleibt stehen, was im DC schon steht. == Der Weg herunter, dauerhaft == Ein zweites Markerpaar dc:rationale neben dc:roadmap. Bewusst ein zweites und keine Erweiterung des ersten: Zwischen den beiden steht in jeder gewachsenen Roadmap-Datei Handgeschriebenes - Einleitung, Leitlinie, Statuszeichen -, und ein einziger Block haette das beim naechsten Erzeugen verschluckt. ?action=render_file setzt beide Bloecke serverseitig ein, damit die Markersuche nur einmal umgesetzt ist. Sie hat eine Feinheit, die zweimal umgesetzt zweimal verschieden waere: Ein im Fliesstext ERWAEHNTER Marker darf nicht gefunden werden - die Einleitung dieser Datei erwaehnt jetzt beide. == Werkzeuge == scripts/dc.py roadmap-import und roadmap-write, in Python und nicht in cli/roadmap.php - sonst waeren sie auf dem Arbeitsplatz wieder nicht aufrufbar. roadmap-write behaelt die Zeilenenden der Datei bei. == Bestand == 35 Vorhaben und 6 Bereiche aus docs/ROADMAP.md uebernommen, 476 Zeilen handgepflegte Prosa durch den erzeugten Block ersetzt. Gegengeprueft auf Wortebene: Aus dem Fliesstext fehlt nichts, die einzigen Abweichungen sind die ersetzten Ueberschriften und die alte Einleitung. Kaertchen ohne hinterlegte Begruendung tragen auf der Tafel eine dezente Marke - erledigte nicht, dort waere sie ein Vorwurf ohne Adressaten. MCP-Adapter auf 1.3.0: dc_roadmap_set nimmt rationale, und die Beschreibung von dc_roadmap verweist nicht mehr auf eine Datei, die der Agent nicht erreichen kann. Geprueft: 7 neue Testfaelle, Suite gesamt 179 von 179. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
767 lines
43 KiB
Markdown
767 lines
43 KiB
Markdown
# Roadmap
|
||
|
||
Die Begründungen zu allem Geplanten, Zurückgestellten und bewusst Verworfenen.
|
||
|
||
**Diese Datei wird erzeugt.** Seit 2.9.1 gilt das nicht mehr nur für den
|
||
Zustand, sondern auch für die Begründungen. Beides steht im Deploymentcenter —
|
||
WebUI → Roadmap, oder `dc_roadmap` über den MCP-Adapter — und wird von dort
|
||
hierher geschrieben:
|
||
|
||
```bash
|
||
python scripts/dc.py roadmap-write --project deploymentcenter
|
||
```
|
||
|
||
Zwischen den `<!-- dc:roadmap -->`- und den `<!-- dc:rationale -->`-Markern
|
||
also **nichts von Hand ändern**; der nächste Lauf überschreibt es. Alles
|
||
außerhalb der Marker bleibt unberührt — diese Einleitung etwa, und der
|
||
Abschnitt „Pflege dieser Datei" am Ende.
|
||
|
||
Bis 2.9.0 stand die Begründung ausschließlich hier. Das hatte zwei Folgen, die
|
||
erst im Betrieb auffielen: Die Roadmap-Tafel im WebUI konnte sie nicht zeigen —
|
||
sie sieht nur die Datenbank, und diese Datei liegt auf einem
|
||
Entwicklungsrechner. Und die Beschreibung von `dc_roadmap` wies Agenten an, vor
|
||
dem erneuten Vorschlagen eines Zurückgestellten „diesen Absatz" zu lesen; ein
|
||
Agent in einem anderen Projekt konnte ihn gar nicht erreichen. Die Anweisung
|
||
war nicht befolgbar.
|
||
|
||
Bis 2.6.0 lagen diese Angaben über mehrere Entwurfsdokumente verstreut, bis
|
||
2.7.0 standen Zustand und Begründung nebeneinander in dieser Datei — beides mit
|
||
derselben Folge: Ein Punkt galt als offen, obwohl der Code ihn längst erledigt
|
||
hatte. Seither hat kein Feld zwei Pfleger.
|
||
|
||
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 |
|
||
|
||
---
|
||
|
||
<!-- dc:roadmap stand=2026-09-20T16:57Z items=65 projekt=deploymentcenter -->
|
||
|
||
<!-- ERZEUGT - nicht von Hand aendern. Dieser Block wird bei jedem Lauf von
|
||
`python scripts/dc.py roadmap-write` ueberschrieben. Der Zustand wird
|
||
im Deploymentcenter gepflegt, nicht hier - und seit 2.9.1 auch die
|
||
Begruendungen, die im Block dc:rationale weiter unten stehen. -->
|
||
|
||
### Als Naechstes
|
||
|
||
1. **[B] #69 — Befunde im WebUI: Liste, Filter nach Detektor, Einstufen**
|
||
2. **[G] #93 — dc-testkit supervisor — prüfen, ob eine Anbindung wirklich meldet**
|
||
3. **[G] #96 — Testartefakt oder echter Befund? — die offene Frage**
|
||
4. **[A] #65 — Symbol-Upload und dc_symbolicate**
|
||
|
||
### A — Supervisor und Befunde
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #65 | Symbol-Upload und dc_symbolicate | 📋 Offen | — |
|
||
| #62 | Detektor-Katalog mit stabilen Namen (Modules/Supervisor/Catalog.php) | ✅ Erledigt | `2.6.0` |
|
||
| #63 | Fünf serverseitige Detektoren im Tick: novel.error_signature, silence.heartbeat, deviation.self, deviation.fleet, reg... | ✅ Erledigt | `2.6.0` |
|
||
| #64 | Supervisor-Client für .NET und PHP | ❌ Verworfen | — |
|
||
| #66 | novel.log_template — Logzeilen-Schablonen, die noch nie auftraten | 🧊 Zurueckgestellt — Ausloeser: sobald Logauszüge strukturiert hereinkommen. Heute liefert nichts sie in einer Form, aus der sich Schablonen bilden l... | — |
|
||
| #67 | Längsschnitt für regression.build | 🧊 Zurueckgestellt — Ausloeser: wenn Fehlzuordnungen auffallen. Nötig wäre eine Historie der app_version je Monitor; das Feld wird heute überschrieben. | — |
|
||
| #68 | Schwellen der serverseitigen Detektoren an echten Daten nachprüfen | 📋 Offen | — |
|
||
|
||
### B — Oberflaeche
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #69 | Befunde im WebUI: Liste, Filter nach Detektor, Einstufen | 📋 Offen | — |
|
||
| #70 | Fremdmeldungen sichtbar (triage_external in Filter, Abzeichen, Bearbeiten) | ✅ Erledigt | `2.6.0` |
|
||
| #71 | Monitoren ein Projekt zuweisen | 📋 Offen | — |
|
||
|
||
### C — Projektlandschaft
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #72 | Projektübergreifend melden (dev_agent, evidence, triage_external, affects) | ✅ Erledigt | `2.6.0` |
|
||
| #73 | Beziehungen zwischen Projekten (dc_project_links, integrated_version) | ✅ Erledigt | `2.6.0` |
|
||
| #74 | Rückkanal: „was du gemeldet hast, ist behoben" | ✅ Erledigt | `2.6.1` |
|
||
| #75 | Agent-Prompt-Vorlage in den Projekten durch MCP ablösen | ✅ Erledigt | `2.7.0` |
|
||
|
||
### D — Werkzeuganbindung (MCP)
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #76 | stdio-Adapter ohne Fremdabhängigkeiten | ✅ Erledigt | `2.6.0` |
|
||
| #77 | Fremddaten im Werkzeugergebnis abgegrenzt kennzeichnen | ✅ Erledigt | `2.6.0` |
|
||
| #78 | Abgleich: Werkzeugliste gegen openapi.php | 📋 Offen | — |
|
||
| #79 | Entfernter MCP-Server unter /mcp mit OAuth | 🧊 Zurueckgestellt — Ausloeser: wenn mehrere Maschinen oder Personen dranhängen. Dann aber mit OAuth statt Bearer-Token in einer Konfigurationsdatei ... | — |
|
||
| #80 | dc_roadmap und dc_roadmap_set — Planungsstand als Werkzeug | ✅ Erledigt | `2.7.0` |
|
||
|
||
### E — Betrieb
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #81 | Migrationen 013 und 014 auf dem Server ausführen | ✅ Erledigt | `2.7.0` |
|
||
| #82 | PHP-Seite prüfen — die Testinstanz tut das jetzt bei jedem Deployment | ✅ Erledigt | `2.7.0` |
|
||
| #83 | Monitoren ein Projekt zuordnen (watchdog_monitors.project_slug) | 📋 Offen | — |
|
||
| #84 | Je Projekt ein Werkbank-Token (dev_agent) anlegen | 📋 Offen | — |
|
||
| #85 | Supervisor-Vorbereitungen in den Projekten zurückbauen | 📋 Offen | — |
|
||
| #666 | WebUI-Anmeldung: Hardwarekey (WebAuthn) als zweite Stufe, Notfalltoken als Ersatzweg, Konten umbenennbar machen | 🔨 In Arbeit | `2.9.0` |
|
||
|
||
### F — Quelltext-Zugriff
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #86 | Stufe 0 — Diagnose-Agent läuft auf eigener Maschine mit lokalem Checkout | ✅ Erledigt | — |
|
||
| #87 | Stufe 1 — Quelltext-Index im DC, nur Ausschnitte | 🧊 Zurueckgestellt — Ausloeser: wenn ein Agent autonom rund um die Uhr laufen soll, ohne dass eine eigene Maschine läuft. Solange Claude Code den Che... | — |
|
||
| #88 | Stufe 2 — nur Metadaten: Signaturen, Aufrufgraph, keine Rümpfe | 🧊 Zurueckgestellt — Ausloeser: falls selbst Ausschnitte zu viel sind. Signaturen, Aufrufgraph und Doc-Kommentare ohne Methodenkörper reichen zur Tri... | — |
|
||
|
||
### G — Testumgebung
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #93 | dc-testkit supervisor — prüfen, ob eine Anbindung wirklich meldet | 📋 Offen | — |
|
||
| #96 | Testartefakt oder echter Befund? — die offene Frage | 📋 Offen | — |
|
||
| #89 | Kopfloser Installationsmodus fuer den update-agent | ✅ Erledigt | `2.8.2` |
|
||
| #90 | DEV-Lizenzschluessel zur Selbstbedienung (POST /api/license/v1/dev-key, Scope license:dev) | ✅ Erledigt | `2.6.1` |
|
||
| #91 | dc-testkit — ein Weg fuer Lizenz, Auslieferung und Meldung | ✅ Erledigt | `2.6.1` |
|
||
| #92 | Werkbank-Token je Projekt auf der Test-VM hinterlegen | 📋 Offen | — |
|
||
| #94 | Test-Monitore aus dem Flottenvergleich heraushalten | 📋 Offen | — |
|
||
| #95 | Befunde tragen die Umgebung, ausserhalb production eine Stufe niedriger | ✅ Erledigt | `2.6.1` |
|
||
| #97 | Nachpruefung als Arbeitsschlange (awaiting_verification, in_verification, fix_insufficient) | ✅ Erledigt | `2.6.1` |
|
||
| #98 | Auswertung über meta_json: wie oft fällt ein Fix durch die Prüfung? | 🧊 Zurueckgestellt — Ausloeser: wenn die Frage „wie oft trägt ein Fix nicht?" tatsächlich gestellt wird. Seit 2.6.1 schreibt jeder Statuswechsel stru... | — |
|
||
|
||
### I — Roadmap im Deploymentcenter
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #107 | Diese Datei selbst übernehmen — Einträge A1–H als Items anlegen, Kennungen auf Item-IDs umstellen | ✅ Erledigt | `2.7.0` |
|
||
| #99 | Migration 016: epic, roadmap_rank, target_build, defer_trigger, doc_anchor, Status deferred, Tabelle roadmap_epics | ✅ Erledigt | `2.7.0` |
|
||
| #100 | Modules/Bugtracker/Roadmap.php — Sicht, Reihenfolge, Erzeugung, Abgleich | ✅ Erledigt | `2.7.0` |
|
||
| #101 | /api/bugtracker/v1/roadmap.php — list, epics, next, active, render, check, set, move, reorder, epic | ✅ Erledigt | `2.7.0` |
|
||
| #102 | WebUI-Modul Roadmap: Übersicht, Liste, Aufnahmeliste, Themenbereiche | ✅ Erledigt | `2.7.0` |
|
||
| #103 | cli/roadmap.php --write/--check/--list | ✅ Erledigt | `2.7.0` |
|
||
| #104 | dc_roadmap, dc_roadmap_set im MCP-Adapter | ✅ Erledigt | `2.7.0` |
|
||
| #105 | Übernahmeleitfaden für die anderen Projekte | ✅ Erledigt | `2.7.0` |
|
||
| #106 | Migration 016 auf dem Server ausführen | ✅ Erledigt | `2.7.0` |
|
||
| #108 | Die anderen Projekte übernehmen (myapp, polytrader, predictalytics) | 📋 Offen | — |
|
||
| #109 | --check in scripts/deploy.py einhängen | 📋 Offen | — |
|
||
| #110 | Auswertung: wie lange steht ein Vorhaben in welcher Lage? | 🧊 Zurueckgestellt — Ausloeser: wenn die Frage „warum dauert das so lange?" tatsächlich gestellt wird. status_changed_at und das strukturierte meta_j... | — |
|
||
| #177 | roadmap_rank ist bereichslokal und projektweit zugleich: nextUp sortiert global, reorder zaehlt je Bereich neu ab 10 | 🔨 In Arbeit | `2.9.0` |
|
||
| #664 | Roadmap-Tafel: Zeitstrahl nach Prioritaet aus den Items je Projekt erzeugen, mit klickbaren Eintraegen und Kommentar ... | 🔨 In Arbeit | `2.9.0` |
|
||
| #667 | Erzeugter Markdown-Block und Roadmap-Tafel benutzen verschiedene Phaseneinteilungen | 📋 Offen | — |
|
||
|
||
### H — Verworfen
|
||
|
||
| | Vorhaben | Stand | Ziel |
|
||
|---|---|---|---|
|
||
| #111 | Supervisor-Beobachter im ausgelieferten Programm (auch regelbasiert, ohne Sprachmodell) | ❌ Verworfen | — |
|
||
| #112 | Sprachmodell-Supervisor auf der Kundenmaschine | ❌ Verworfen | — |
|
||
| #113 | Quelltext mit dem Client ausliefern, auch verschlüsselt | ❌ Verworfen | — |
|
||
| #114 | Deploy-Key oder Repo-Token im Client | ❌ Verworfen | — |
|
||
| #115 | Obfuskation als Schutz einplanen | ❌ Verworfen | — |
|
||
| #116 | MCP-Werkzeuge 1:1 aus OpenAPI erzeugen | ❌ Verworfen | — |
|
||
| #117 | publish, provision, deactivate als MCP-Werkzeug | ❌ Verworfen | — |
|
||
| #118 | Befunde puffern, wenn das DC ausfällt | ❌ Verworfen | — |
|
||
| #119 | Benachrichtigung je Befund | ❌ Verworfen | — |
|
||
| #120 | Lokale Befund-Oberfläche in den Anwendungen | ❌ Verworfen | — |
|
||
| #121 | enforceProject() pauschal für dev_agent öffnen | ❌ Verworfen | — |
|
||
| #122 | Feste Schwellwerte je Kennzahl als Hauptweg | ❌ Verworfen | — |
|
||
|
||
<!-- /dc:roadmap -->
|
||
|
||
---
|
||
|
||
## Begründungen
|
||
|
||
<!-- dc:rationale stand=2026-09-20T16:57Z items=39 projekt=deploymentcenter -->
|
||
|
||
> **Erzeugt — hier nicht von Hand aendern.** Die Begruendungen stehen im
|
||
> Deploymentcenter und werden von dort geschrieben: in der Roadmap-Tafel am
|
||
> Kaertchen oder ueber `dc_roadmap_set`. Der naechste
|
||
> `python scripts/dc.py roadmap write` ueberschreibt diesen Abschnitt.
|
||
>
|
||
> Der Grund fuer die Umstellung: Solange die Begruendung nur hier stand, war
|
||
> sie fuer die Tafel unsichtbar und fuer jeden Agenten ausserhalb dieses
|
||
> Repositorys unerreichbar.
|
||
|
||
## 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.
|
||
|
||
### [A] #65 — 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.
|
||
|
||
### [A] #64 — Supervisor-Client für .NET und PHP ❌
|
||
|
||
Verworfen. Die Begründung steht in Abschnitt H, beim Beobachter im
|
||
ausgelieferten Programm — dieser Client wäre sein Einbauteil gewesen und fällt
|
||
mit ihm weg.
|
||
|
||
### [A] #66 — novel.log_template — Logzeilen-Schablonen, die noch nie auftraten 🧊
|
||
|
||
**Auslöser:** sobald Logauszüge strukturiert hereinkommen. Heute liefert nichts
|
||
sie in einer Form, aus der sich Schablonen bilden ließen.
|
||
|
||
### [A] #67 — 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.
|
||
|
||
### [A] #68 — Schwellen der serverseitigen Detektoren an echten Daten 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 — Oberflaeche
|
||
|
||
### [B] #69 — Befunde im WebUI: Liste, Filter nach Detektor, Einstufen 📋
|
||
|
||
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.
|
||
|
||
### [B] #71 — 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 #81.
|
||
|
||
## C — Projektlandschaft
|
||
|
||
### [C] #74 — Rückkanal: „was du gemeldet hast, ist behoben" ✅
|
||
|
||
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`: „Das Item, das du
|
||
gemeldet hast, ist in 2.7.0 erledigt."
|
||
|
||
Das schließt den Kreis, den #72 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.
|
||
|
||
### [C] #75 — Agent-Prompt-Vorlage in den Projekten durch MCP ablösen ✅
|
||
|
||
[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)
|
||
|
||
### [D] #78 — Abgleich: Werkzeugliste gegen openapi.php 📋
|
||
|
||
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.
|
||
|
||
### [D] #79 — Entfernter MCP-Server unter /mcp mit OAuth 🧊
|
||
|
||
**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.
|
||
|
||
|
||
**#83 ist Voraussetzung für `deviation.fleet` und `regression.build`.** Ohne
|
||
Zuordnung überspringen beide Detektoren die betroffenen Monitore; die übrigen
|
||
drei laufen weiter.
|
||
|
||
**#84 vor #85.** Ohne Werkbank-Token laufen `dc_link_project` und `dc_report` aus
|
||
den Projekten heraus ins Leere.
|
||
|
||
**#82 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
|
||
```
|
||
|
||
**#85 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).
|
||
|
||
### [E] #666 — WebUI-Anmeldung: Hardwarekey (WebAuthn) als zweite Stufe, Notfalltoken als Ersatzweg, Konten umbenennbar machen 🔨
|
||
|
||
Das Verwaltungskonto hing an einem einzigen Geheimnis. Wer das Passwort hat, hat Tokens, Lizenzen, Monitore und die Release-Strecke aller angebundenen Projekte - und ein Passwort wandert: in Passwortspeicher, in Zwischenablagen, gelegentlich in einen Chat.
|
||
|
||
Ein Hardwarekey behebt genau das und nichts anderes. Er laesst sich nicht kopieren, nicht abtippen und nicht per Fernzugriff abgreifen, und er ist an die Adresse gebunden, unter der er registriert wurde - eine nachgebaute Anmeldeseite laeuft deshalb ins Leere, auch wenn das Passwort dort eingegeben wird.
|
||
|
||
== Warum die Pflicht am Schluessel haengt und nicht an einem Schalter ==
|
||
Ein Schalter "zweiter Faktor erforderlich" waere die naheliegende Bauart und die gefaehrlichere: Wer ihn umlegt, bevor ein Schluessel registriert ist, sperrt sich aus der eigenen Verwaltung aus - und zwar aus derjenigen, in der man den Schalter zuruecknehmen wuerde. So herum kann das nicht passieren: Wer einen Schluessel registriert hat, hat ihn auch in der Hand.
|
||
|
||
Der Preis ist, dass die zweite Stufe stillschweigend unwirksam bleibt, solange niemand registriert. Deshalb steht in der Benutzerverwaltung "nur Passwort" an jedem Konto ohne Schluessel, statt dass dort nichts steht.
|
||
|
||
== Warum ohne Fremdbibliothek ==
|
||
Das Projekt hat bewusst kein Composer und kein vendor/. Ein Server, der sich ueber FTP aktualisieren laesst, soll nicht von einem Abhaengigkeitsbaum abhaengen, den niemand mehr liest. CBOR-Leser, COSE-nach-DER-Wandlung und Signaturpruefung sind zusammen rund fuenfhundert Zeilen - weniger, als eine Bibliothek an Pflege kostet, und pruefbar gegen einen Software-Authenticator.
|
||
|
||
== Der Notfalltoken ist ein Zugestaendnis, kein Komfort ==
|
||
Ein zweiter Faktor ohne Ersatzweg ist ein Einzelpunktversagen mit Ansage: kaputter Stick, verlorener Schluessel, und die Verwaltung ist zu. Der Token ist deshalb absichtlich unbequem - einmal angezeigt, einmal verwendbar, danach weg. Er soll die Ausnahme bleiben und nicht der bequemere Hauptweg werden.
|
||
|
||
Dass er als gewoehnliches Formular ohne JavaScript laeuft, ist kein Zufall: Ein Ersatzweg mit denselben Voraussetzungen wie der Hauptweg ist keiner.
|
||
|
||
## F — Quelltext-Zugriff
|
||
|
||
Die Software bleibt geschlossen. Es gibt keine öffentliche Stelle, an der
|
||
Quelltext zu sehen ist. Drei Stufen, in aufsteigender Preisgabe:
|
||
|
||
### [F] #87 — Stufe 1 — Quelltext-Index im DC, nur Ausschnitte 🧊
|
||
|
||
**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".
|
||
|
||
### [F] #88 — Stufe 2 — nur Metadaten: Signaturen, Aufrufgraph, keine Rümpfe 🧊
|
||
|
||
**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
|
||
|
||
Die geteilte Linux-Test-VM. Anleitung: **[TESTUMGEBUNG.md](./TESTUMGEBUNG.md)** — dort
|
||
steht auch, was auf der Maschine belegt ist.
|
||
|
||
### [G] #93 — dc-testkit supervisor — prüfen, ob eine Anbindung wirklich meldet 📋
|
||
|
||
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 #96: 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).
|
||
|
||
### [G] #96 — Testartefakt oder echter Befund? — die offene Frage 📋
|
||
|
||
**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".
|
||
|
||
### [G] #89 — Kopfloser Installationsmodus fuer den update-agent ✅
|
||
|
||
`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`.
|
||
|
||
### [G] #92 — Werkbank-Token je Projekt auf der Test-VM hinterlegen 📋
|
||
|
||
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
|
||
#84 — dasselbe Token traegt beides.
|
||
|
||
### [G] #94 — Test-Monitore aus dem Flottenvergleich heraushalten 📋
|
||
|
||
`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.
|
||
|
||
### [G] #95 — Befunde tragen die Umgebung, ausserhalb production eine Stufe niedriger ✅
|
||
|
||
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.
|
||
|
||
### [G] #98 — Auswertung über meta_json: wie oft fällt ein Fix durch die Prüfung? 🧊
|
||
|
||
**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.
|
||
|
||
## 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.**
|
||
|
||
### [I] #107 — Diese Datei selbst übernehmen — Einträge A1–H als Items anlegen, Kennungen auf Item-IDs umstellen ✅
|
||
|
||
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 #106 (Migration), dann #107, dann #109 (Abgleich im Deploy).
|
||
#108 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.
|
||
|
||
### [I] #99 — Migration 016: epic, roadmap_rank, target_build, defer_trigger, doc_anchor, Status deferred, Tabelle roadmap_epics ✅
|
||
|
||
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.
|
||
|
||
### [I] #110 — Auswertung: wie lange steht ein Vorhaben in welcher Lage? 🧊
|
||
|
||
**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.
|
||
|
||
### [I] #177 — roadmap_rank ist bereichslokal und projektweit zugleich: nextUp sortiert global, reorder zaehlt je Bereich neu ab 10 🔨
|
||
|
||
Dieselbe Spalte wurde an drei Stellen verschieden gelesen: nextUp() sortierte projektweit, reorder() zaehlte je Bereich ab 10 neu durch, und die Werkzeugbeschreibung sagte "Reihenfolge im Bereich". Von aussen liess sich der Rang deshalb nicht so vergeben, dass alle drei Lesarten zugleich stimmten.
|
||
|
||
Entschieden wurde fuer PROJEKTWEIT. Die Gegenrichtung waere gewesen, nextUp() nach (epic.sort_order, rank) sortieren zu lassen - dann haengt die Dringlichkeit eines Vorhabens aber an der Sortiernummer seines Bereichs, und eine Sicherheitsluecke in Bereich G stuende hinter jeder Kleinigkeit aus Bereich A. Das ist nicht die Aussage, die eine Prioritaetenliste treffen soll.
|
||
|
||
Ausserdem gab die gemeldete Beobachtung den Ausschlag: eine durchgehende Reihenfolge ueber sieben Abschnitte hinweg, in der Sicherheit, Betrieb und Faehigkeiten abwechseln. So eine Liste ist nur projektweit abbildbar.
|
||
|
||
Die Folge fuer reorder() ist die interessantere Haelfte. Es zaehlt jetzt nicht mehr durch, sondern vertauscht ausschliesslich die Raenge, die die genannten Eintraege ohnehin halten - ihre Plaetze in der projektweiten Reihenfolge bleiben als Menge unveraendert, nur wer auf welchem sitzt, aendert sich. Vorher hatte eine Geste innerhalb eines Bereichs eine projektweite Wirkung, die niemand angefordert hatte.
|
||
|
||
### [I] #664 — Roadmap-Tafel: Zeitstrahl nach Prioritaet aus den Items je Projekt erzeugen, mit klickbaren Eintraegen und Kommentar ... 🔨
|
||
|
||
Eine Liste beantwortet "was gibt es", eine Tafel beantwortet "was ist als Naechstes dran und warum in dieser Reihenfolge". Das sind verschiedene Fragen, und die zweite wird oefter gestellt.
|
||
|
||
== Warum der Server die Gliederung liefert ==
|
||
Der naheliegende Weg waere gewesen, die Items als Liste zu holen und im Browser zu schneiden. Dann schneidet aber das WebUI anders als die CLI, und ein spaeterer Export ein drittes Mal anders - aus denselben Daten entstuenden drei Wahrheiten ueber dieselbe Planung. Deshalb liefert der Server unter ?action=board die fertige Struktur, und die Darstellung liest nur daraus.
|
||
|
||
== Warum die Phasengrenzen nicht im Code stehen ==
|
||
roadmap_rank wird je Projekt frei vergeben. Wer in Zehnern zaehlt, hat andere Abstaende als jemand, der in Hundertern zaehlt. Eine Grenze im Code waere fuer genau ein Projekt richtig und fuer jedes andere falsch. Gepflegt werden sie in roadmap_phases; ist dort nichts hinterlegt, schneidet die Tafel an den groessten Luecken der Rangfolge - und sagt dazu, dass die Grenzen geraten sind. Eine geratene Grenze, die wie eine Entscheidung aussieht, waere schlimmer als gar keine.
|
||
|
||
== Nachpruefung ist ein eigener Zustand ==
|
||
awaiting_verification, in_verification und fix_insufficient als "erledigt" zu zeichnen waere bequem und falsch: Ein Fix, der nicht getragen hat, ist keine Erledigung. Im Projekt clawddotnet stand deshalb in der Bastelloesung eine von Hand danebengeschriebene Marke "Status pruefen". Genau die faellt jetzt weg.
|
||
|
||
== Das Seitenpanel ist der eigentliche Gewinn ==
|
||
Der Weg zurueck war gebrochen: Wer in der Uebersicht etwas bemerkte, musste sich die Nummer merken und im Bugtracker-Tab danach suchen. Ein Umweg, den man ein paarmal geht und danach nicht mehr - die Anmerkung unterbleibt dann einfach. Bemerken und anmerken gehoeren an dieselbe Stelle.
|
||
|
||
== Was das Ziehen voraussetzte ==
|
||
Ohne #177 waere es nicht zu bauen gewesen: Solange roadmap_rank gleichzeitig projektweit und bereichslokal gelesen wurde, haette jede Verschiebung auf der Tafel gegen die vorhandene Sortierlogik gearbeitet. Der Client schickt deshalb nur die beiden Nachbarn; den Rang rechnet der Server, der als Einziger weiss, was sonst noch zwischen ihnen liegt.
|
||
|
||
### [I] #667 — Erzeugter Markdown-Block und Roadmap-Tafel benutzen verschiedene Phaseneinteilungen 📋
|
||
|
||
Seit 2.9.1 gibt es zwei erzeugte Sichten auf dieselbe Planung, und sie ordnen verschieden: Die Tafel schneidet Spalten aus roadmap_rank, der Markdown-Block gliedert nach Themenbereich. Wer docs/ROADMAP.md aufschlaegt und wer die Tafel ansieht, bekommt denselben Bestand in zwei Gliederungen.
|
||
|
||
Beide sind fuer sich richtig - das ist der Grund, warum es nicht dringend ist. Es ist aber genau die Sorte Abweichung, die die Umstellung auf eine erzeugte Datei beseitigen sollte: Der Zustandsteil wird nicht mehr gepflegt, aber er wird zweimal verschieden erzeugt, und irgendwann haelt das jemand fuer einen Fehler.
|
||
|
||
Vorschlag: renderBlock() RoadmapBoard::build() als Quelle nehmen lassen und daraus Ueberschriften je Phase erzeugen, mit den Bereichen als Unterpunkte. Dann ist die Phaseneinteilung an genau einer Stelle umgesetzt - und die geratenen Grenzen stehen auch in der Datei als geraten drin, statt dort wie eine Entscheidung auszusehen.
|
||
|
||
## 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.
|
||
|
||
### [H] #111 — 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
|
||
|
||
### [H] #112 — 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
|
||
|
||
### [H] #113 — Quelltext mit dem Client ausliefern, auch verschlüsselt ❌
|
||
|
||
Der Client muss entschlüsseln können, also kann es der Kunde auch
|
||
|
||
### [H] #114 — Deploy-Key oder Repo-Token im Client ❌
|
||
|
||
Dekompiliert in Minuten
|
||
|
||
### [H] #115 — Obfuskation als Schutz einplanen ❌
|
||
|
||
Verzögert, verhindert nicht
|
||
|
||
### [H] #116 — 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
|
||
|
||
### [H] #117 — 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
|
||
|
||
### [H] #118 — 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
|
||
|
||
### [H] #119 — 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
|
||
|
||
### [H] #120 — Lokale Befund-Oberfläche in den Anwendungen ❌
|
||
|
||
Zweite Wahrheit, die nur den eigenen Ausschnitt kennt. Der Client hält keine Historie vor
|
||
|
||
### [H] #121 — enforceProject() pauschal für dev_agent öffnen ❌
|
||
|
||
Hätte auch `publish` und `setup` in fremden Projekten erlaubt. Die Ausnahme wird je Aufrufstelle gesetzt
|
||
|
||
### [H] #122 — Feste Schwellwerte je Kennzahl als Hauptweg ❌
|
||
|
||
Finden nur, woran vorher jemand gedacht hat. Die tragenden Detektoren vergleichen gegen eigenen Verlauf, Vorversion oder Flotte
|
||
|
||
<!-- /dc:rationale -->
|
||
|
||
---
|
||
|
||
## Pflege dieser Datei
|
||
|
||
Seit 2.9.1 hat diese Datei **keinen** von Hand gepflegten Inhaltsteil mehr.
|
||
Die Arbeitsteilung lautet:
|
||
|
||
| | Wahrheit | Diese Datei hält |
|
||
|---|---|---|
|
||
| Status, Reihenfolge, Zielfassung, Bearbeiter | **Deploymentcenter** | den erzeugten Block zwischen `<!-- dc:roadmap -->`-Markern |
|
||
| Begründung, Auslöser, Verworfenes | **Deploymentcenter**, Feld `rationale` | den erzeugten Block zwischen `<!-- dc:rationale -->`-Markern |
|
||
| Einleitung, dieser Abschnitt | **diese Datei** | sich selbst, außerhalb aller Marker |
|
||
|
||
- Ein Vorhaben entsteht **immer im DC**, nie hier. `dc_report` legt es an,
|
||
`dc_roadmap_set` hebt es auf die Roadmap und trägt auch die Begründung ein.
|
||
So kann ein Punkt, der nur in einer Datei steht und den niemand angeht, gar
|
||
nicht erst entstehen.
|
||
- **Geschrieben wird im Deploymentcenter**, am bequemsten in der Roadmap-Tafel:
|
||
Kärtchen anklicken, Begründung ins Seitenpanel tippen, speichern. Danach
|
||
`python scripts/dc.py roadmap-write`, damit diese Datei nachzieht.
|
||
- Zwischen den Markern **nichts von Hand ändern** — es wird beim nächsten Lauf
|
||
überschrieben.
|
||
- 🧊 und ❌ behalten ihre Begründung. Der Statuswert allein sagt nicht, warum —
|
||
und ohne das Warum schlägt es der nächste Agent wieder vor. Sie steht jetzt
|
||
am Item selbst und ist damit auch für Agenten außerhalb dieses Repositorys
|
||
lesbar; das war der Anlass der Umstellung.
|
||
- `python scripts/dc.py roadmap-import` ist der Weg **herauf** und war einmalig
|
||
gedacht. Er überschreibt nichts, was im DC schon steht, außer mit
|
||
`--overwrite`.
|
||
- Ausführliche Herleitungen gehören ins Archiv, nicht hierher. Diese Datei soll
|
||
lesbar bleiben.
|
||
- **Keine erfundenen Item-Nummern im Fließtext.** Bei der Übernahme stand im
|
||
Rückkanal-Absatz eine ausgedachte Beispielnummer — und die gab es wirklich, in
|
||
`predictalytics`. Der Abgleich hat es gemeldet; ein Mensch hätte es nie
|
||
bemerkt. Für Beispiele deshalb „das Item" schreiben, nicht „Item Nummer x". |