# 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 ### 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 | — | ## 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.