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>
299 lines
11 KiB
Markdown
299 lines
11 KiB
Markdown
# Roadmap ins Deploymentcenter übernehmen
|
|
|
|
**Für Agenten und Entwickler in den angebundenen Projekten.** Diese Anleitung
|
|
beschreibt, wie eine vorhandene `ROADMAP.md`, `TODO.md`, `PLAN.md` oder eine
|
|
Sammlung von Entwurfsdokumenten in das Roadmap-System des Deploymentcenters
|
|
überführt wird — einmalig, pro Projekt.
|
|
|
|
Verfügbar ab **2.7.0**. Voraussetzung: Migration `016_roadmap.sql` ist auf dem
|
|
Server gelaufen.
|
|
|
|
---
|
|
|
|
## Warum überhaupt
|
|
|
|
Vorhaben lagen bisher in Markdown-Dateien: Status, Reihenfolge und
|
|
Zuständigkeit von Hand gepflegt, neben einem Bugtracker, der genau diese drei
|
|
Dinge bereits führt. Zwei Pfleger für dasselbe Feld — Drift war keine
|
|
Möglichkeit, sondern eine Frage der Zeit.
|
|
|
|
Konkret ging dabei verloren:
|
|
|
|
- Ein Punkt stand als offen in der Datei, obwohl der Code ihn längst erledigt
|
|
hatte. Wer die Datei las, arbeitete an etwas Fertigem.
|
|
- Zwei Agenten nahmen sich dasselbe Vorhaben vor, weil die Datei nicht sagen
|
|
kann, dass jemand daran sitzt.
|
|
- Ein verworfener Vorschlag kam nach drei Monaten wieder, weil die Begründung
|
|
in einem Entwurfsdokument stand, das niemand mehr aufschlug.
|
|
|
|
## Die Arbeitsteilung
|
|
|
|
**Kein Feld hat zwei Pfleger.** Das ist die ganze Regel; alles Weitere folgt
|
|
daraus.
|
|
|
|
| | Wahrheit | Die andere Seite hält |
|
|
|---|---|---|
|
|
| Status, Reihenfolge, Zielfassung, Bearbeiter | **Deploymentcenter** | eine maschinell erzeugte Kopie zwischen Markern |
|
|
| Begründung, Auslöser, Verworfenes, Herleitung | **Die Datei** | nur einen Verweis (`doc_anchor`) |
|
|
|
|
Die Datei verschwindet also **nicht**. Sie verliert nur die Hälfte, die sie
|
|
ohnehin nie zuverlässig getragen hat.
|
|
|
|
## Die Kennung
|
|
|
|
Handvergebene Kennungen (`A12`, `TODO-7`) sind der Grund für die schlimmste
|
|
Fehlerart: Beide Seiten sind für sich stimmig und meinen Verschiedenes, weil
|
|
die Kennung nach einer Löschung neu vergeben wurde. Niemand bemerkt das.
|
|
|
|
Deshalb ist die Kennung die **Item-ID** aus dem Deploymentcenter.
|
|
AUTO_INCREMENT vergibt nie zweimal dieselbe Nummer; eine gelöschte Zeile
|
|
hinterlässt eine hängende Referenz, und die *meldet* der Abgleich, statt sie
|
|
stillschweigend umzudeuten.
|
|
|
|
Der Themenbuchstabe bleibt — aber nur als Gruppe:
|
|
|
|
```markdown
|
|
### [A] #142 — Symbol-Upload und dc_symbolicate
|
|
```
|
|
|
|
---
|
|
|
|
## Übernahme in sechs Schritten
|
|
|
|
### 1. Bestandsaufnahme
|
|
|
|
Sortiere jeden Eintrag deiner Datei in genau eine der vier Kisten:
|
|
|
|
| Kiste | Kennzeichen | Wohin |
|
|
|---|---|---|
|
|
| **Vorhaben** | hat einen Zustand, jemand könnte es übernehmen | Item im DC |
|
|
| **Zurückgestellt** | bewusst nicht jetzt, mit benanntem Anlass | Item (`deferred`) + Absatz |
|
|
| **Verworfen** | geprüft und abgelehnt, mit Begründung | Item (`rejected`) + Absatz |
|
|
| **Erledigt** | schon ausgeliefert | Item (`resolved`) — oder ersatzlos streichen |
|
|
|
|
Was in keine Kiste passt, ist meist ein Gedanke und kein Vorhaben. Der gehört
|
|
in die Prosa, nicht in die Datenbank. **Faustregel:** Wenn niemand es
|
|
übernehmen kann, ist es kein Item.
|
|
|
|
### 2. Themenbereiche anlegen
|
|
|
|
Die Abschnitte deiner Datei werden Themenbereiche. Kurzes Kürzel, sprechender
|
|
Titel:
|
|
|
|
```bash
|
|
curl -X POST "https://dc.mhdf.de/api/bugtracker/v1/roadmap.php?action=epic" \
|
|
-H "Authorization: Bearer $DC_TOKEN" -H "Content-Type: application/json" \
|
|
-d '{"project_slug":"meinprojekt","epic":"A","title":"Handelslogik","sort_order":10}'
|
|
```
|
|
|
|
Oder im WebUI unter **Roadmap → Themenbereiche**.
|
|
|
|
Halte die Zahl klein. Fünf bis zehn Bereiche sind übersichtlich, zwanzig sind
|
|
eine zweite Ablage, die selbst wieder sortiert werden will.
|
|
|
|
### 3. Vorhaben anlegen
|
|
|
|
Jedes Vorhaben wird ein Item. Mit MCP-Adapter:
|
|
|
|
```
|
|
dc_report(title: "Symbol-Upload und dc_symbolicate",
|
|
type: "feature_request",
|
|
description: "…",
|
|
client_ref: "roadmap-a4")
|
|
```
|
|
|
|
`client_ref` immer setzen: Ein wiederholter Lauf legt dann kein Duplikat an —
|
|
und bei einer Übernahme von zwanzig Einträgen läuft irgendetwas immer zweimal.
|
|
|
|
Ohne MCP:
|
|
|
|
```bash
|
|
curl -X POST "https://dc.mhdf.de/api/bugtracker/v1/report" \
|
|
-H "Authorization: Bearer $DC_TOKEN" -H "Content-Type: application/json" \
|
|
-d '{"project_slug":"meinprojekt","type":"feature_request",
|
|
"title":"…","description":"…","client_ref":"roadmap-a4"}'
|
|
```
|
|
|
|
### 4. Auf die Roadmap heben
|
|
|
|
Ein Vorhaben steht auf der Roadmap, **sobald es einen Themenbereich hat**. Das
|
|
ist das einzige Kennzeichen — ein zweites Flag daneben gäbe es zwei Angaben,
|
|
die dasselbe behaupten und auseinanderlaufen können.
|
|
|
|
```
|
|
dc_roadmap_set(id: 142, epic: "A", roadmap_rank: 10, target_build: "2.7.0",
|
|
doc_anchor: "docs/ROADMAP.md#142-symbol-upload")
|
|
```
|
|
|
|
Zur Reihenfolge: **Zehnerschritte.** Die Lücken sind Absicht — ein Eintrag
|
|
lässt sich später auf Rang 15 dazwischenschieben, ohne dass alle folgenden neu
|
|
nummeriert werden müssen.
|
|
|
|
Zurückgestelltes braucht den Auslöser, sonst wird der Aufruf abgelehnt:
|
|
|
|
```
|
|
dc_roadmap_set(id: 147, epic: "A", status: "deferred",
|
|
defer_trigger: "sobald Logauszüge strukturiert hereinkommen")
|
|
```
|
|
|
|
Ohne benannten Anlass ist ein Vorhaben nicht zurückgestellt, sondern vergessen.
|
|
Genau deshalb ist das Feld Pflicht und nicht bloß empfohlen.
|
|
|
|
### 5. Die Datei umbauen
|
|
|
|
Drei Änderungen:
|
|
|
|
**a) Zustandstabellen raus.** Jede von Hand gepflegte Tabelle mit Status-Spalte
|
|
wird ersatzlos gelöscht. Sie kommt gleich erzeugt zurück.
|
|
|
|
**b) Überschriften auf Item-IDs umstellen.**
|
|
|
|
```markdown
|
|
### [A] #142 — Symbol-Upload und dc_symbolicate
|
|
|
|
Der Packager lädt beim `publish` die PDB mit hoch, verknüpft mit `commit_sha`.
|
|
Ausgeliefert wird ein gestripptes Binary. …
|
|
```
|
|
|
|
Kein Status in der Überschrift, kein Häkchen, keine Zielfassung — das steht
|
|
alles im erzeugten Block und wäre hier eine zweite Wahrheit.
|
|
|
|
**c) Den Block einsetzen.** Beim ersten Lauf wird er ans Dateiende gehängt;
|
|
verschiebe ihn samt Markern dorthin, wo er stehen soll. Künftige Läufe finden
|
|
ihn dort wieder.
|
|
|
|
```bash
|
|
php cli/roadmap.php --write --project=meinprojekt --file=/pfad/zu/ROADMAP.md
|
|
```
|
|
|
|
Liegt das Projekt auf einer anderen Maschine als das Deploymentcenter, holst du
|
|
den Block über die API:
|
|
|
|
```bash
|
|
curl -s "https://dc.mhdf.de/api/bugtracker/v1/roadmap.php?action=render&project_slug=meinprojekt" \
|
|
-H "Authorization: Bearer $DC_TOKEN" | jq -r .markdown
|
|
```
|
|
|
|
### 6. Abgleich einrichten
|
|
|
|
```bash
|
|
php cli/roadmap.php --check --project=meinprojekt --file=/pfad/zu/ROADMAP.md
|
|
```
|
|
|
|
Was geprüft wird — nur die **Prosa**, denn der erzeugte Block kann nicht
|
|
abweichen:
|
|
|
|
| Befund | Bedeutung | Grad |
|
|
|---|---|---|
|
|
| `unknown_item` | Absatz nennt `#142`, das Item gibt es nicht | Fehler |
|
|
| `foreign_item` | `#142` gehört einem anderen Projekt | Fehler |
|
|
| `not_on_roadmap` | Absatz vorhanden, aber kein Themenbereich gesetzt | Warnung |
|
|
| `title_drift` | Überschrift und Item-Titel haben nichts mehr gemeinsam | Warnung |
|
|
| `decision_undocumented` | zurückgestellt/verworfen, aber keine Begründung in der Datei | Warnung |
|
|
|
|
Rückgabewert 0 heißt in Ordnung (Warnungen erlaubt), 1 heißt Fehler. Damit
|
|
lässt sich der Aufruf in einen Deploy-Schritt oder Pre-Commit-Hook hängen.
|
|
|
|
Ein Item **ohne** Absatz ist bewusst kein Befund: Nicht jedes Vorhaben braucht
|
|
eine Herleitung, die meisten sind eine Zeile wert und mehr nicht.
|
|
|
|
---
|
|
|
|
## Nach der Übernahme: die Regeln im Alltag
|
|
|
|
**Ein Vorhaben entsteht immer im DC, nie in der Datei.** `dc_report` legt das
|
|
Item an → `--write` schreibt die Zeile → *danach* schreibst du die Begründung
|
|
darunter. So kann ein Eintrag, der nur in der Datei steht, gar nicht erst
|
|
entstehen — und damit auch kein offener Punkt, den niemand angeht.
|
|
|
|
**Die Arbeitsschlange ist die Wahrheit über Arbeit.** Was nicht über
|
|
`?action=next` ausgegeben wird, macht niemand — unabhängig davon, wie es in
|
|
einer Datei markiert ist. Ein Eintrag, der etwas werden soll, muss ein Item
|
|
sein.
|
|
|
|
**Vor dem Anfangen `dc_roadmap` aufrufen.** Es beantwortet „was ist als
|
|
Nächstes dran" und „arbeitet schon jemand daran". Beides, bevor du beginnst.
|
|
|
|
**Vor dem Wiedervorschlagen die Begründung lesen.** Steht ein Vorhaben auf
|
|
`rejected` oder `deferred`, führt `doc_anchor` zu dem Absatz, der sagt warum.
|
|
Ein erneuter Vorschlag braucht ein Argument, das dort noch nicht steht.
|
|
|
|
**Der erzeugte Block darf altern.** Er ist eine Kopie, und Kopien altern. Der
|
|
Live-Stand kommt aus `dc_roadmap`; der Block ist für Menschen, die die Datei
|
|
aufschlagen. `--check` weist auf einen Block hin, der älter als ein Tag ist.
|
|
|
|
---
|
|
|
|
## Was nicht ins DC gehört
|
|
|
|
Der Umzug ist keine Einladung, alles in die Datenbank zu kippen.
|
|
|
|
- **Architekturentscheidungen mit Herleitung** bleiben in der Datei. Ein
|
|
Absatz, der eine Abwägung erklärt, überlebt keine Tabellenzelle.
|
|
- **Verworfenes mit Begründung** bleibt in der Datei. Der Wert des Eintrags ist
|
|
die Begründung, nicht die Ablehnung. Im DC steht nur der Status daneben.
|
|
- **Lose Gedanken** gehören weder hierhin noch dorthin. Wenn niemand sie
|
|
übernehmen kann, sind sie kein Vorhaben — im Zweifel als Notiz ins Archiv.
|
|
- **Alte Entwurfsdokumente** nach `docs/archiv/` verschieben, nicht löschen.
|
|
Sie enthalten die ausführliche Begründung, aber keinen gültigen Stand mehr.
|
|
Ein Hinweis darauf gehört an den Kopf der Roadmap-Datei.
|
|
|
|
---
|
|
|
|
## Werkzeuge im Überblick
|
|
|
|
| Werkzeug | Wofür |
|
|
|---|---|
|
|
| `dc_roadmap` | lesen: was ist dran, wer sitzt dran (MCP) |
|
|
| `dc_roadmap_set` | Bereich, Rang, Zielfassung, Anker setzen (MCP) |
|
|
| `GET /api/bugtracker/v1/roadmap.php?action=list` | dasselbe über REST |
|
|
| `?action=render` | den Markdown-Block holen |
|
|
| `?action=check` | Abgleich mit mitgeschickter Datei (`content`) |
|
|
| `php cli/roadmap.php --write\|--check\|--list` | von der DC-Maschine aus |
|
|
| WebUI → **Roadmap** | Übersicht, Filter, Reihenfolge, Aufnahmeliste |
|
|
|
|
Token braucht `bugtracker:read` zum Lesen und `bugtracker:manage` zum
|
|
Schreiben. Ein Werkbank-Token (`dev_agent`) hat beides.
|
|
|
|
---
|
|
|
|
## Beispiel: eine Datei vorher und nachher
|
|
|
|
**Vorher** — Zustand und Begründung durcheinander, beides von Hand:
|
|
|
|
```markdown
|
|
## A — Supervisor
|
|
|
|
| | Vorhaben | Stand |
|
|
|---|---|---|
|
|
| A4 | Symbol-Upload | 📋 geplant für 2.7.0 |
|
|
| A5 | Logzeilen-Schablonen | 🧊 später |
|
|
|
|
### A4 — Symbol-Upload
|
|
Der Packager lädt die PDB mit hoch…
|
|
```
|
|
|
|
**Nachher** — Zustand erzeugt, Begründung von Hand, verbunden über die ID:
|
|
|
|
```markdown
|
|
<!-- dc:roadmap stand=2026-08-29T14:02Z items=7 projekt=deploymentcenter -->
|
|
|
|
### A — Supervisor und Befunde
|
|
|
|
| | Vorhaben | Stand | Ziel |
|
|
|---|---|---|---|
|
|
| #142 | Symbol-Upload und dc_symbolicate | 📋 Offen | `2.7.0` |
|
|
| #143 | novel.log_template | 🧊 Zurückgestellt — Auslöser: sobald Logauszüge strukturiert hereinkommen | — |
|
|
|
|
<!-- /dc:roadmap -->
|
|
|
|
## Begründungen
|
|
|
|
### [A] #142 — Symbol-Upload
|
|
Der Packager lädt die PDB mit hoch, verknüpft mit `commit_sha`. Ausgeliefert
|
|
wird ein gestripptes Binary. Der Kunde bekommt `at 0x4a2f`, du bekommst
|
|
`UserAuthService.cs:42` — ohne dass Quelltext das Haus verlässt.
|
|
```
|
|
|
|
Die Statuszeile stimmt jetzt, weil sie niemand mehr pflegt.
|