feat(2.7.0): Roadmap im DC, Testinstanz mit Testtor, Supervisor und MCP

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>
This commit is contained in:
Deploymentcenter Bot
2026-08-29 21:59:20 +02:00
co-authored by Claude Opus 5
parent 9d0261306c
commit 1d5ac92051
52 changed files with 15261 additions and 103 deletions
@@ -0,0 +1,99 @@
-- Migration 013: Projektuebergreifendes Melden und Projektbeziehungen
--
-- Additive Migration. Der Migrator toleriert 1050/1060/1061/1062/1091
-- ("existiert bereits"), sodass sie auf einer teilweise migrierten Datenbank
-- durchlaeuft.
--
-- Hintergrund: Einige Projekte arbeiten stark verzahnt, das Deploymentcenter
-- am staerksten. Ein Agent, der das SDK in Projekt X integriert und dabei
-- einen Fehler im Deploymentcenter findet, muss ihn dort ablegen koennen.
-- Bisher verweigerte ApiAuth::enforceProject() genau das - obwohl die
-- Agenten-Prompt-Vorlage es ausdruecklich verlangt.
--
-- Siehe docs/SUPERVISOR_MCP_DESIGN.md, Abschnitt 5.
-- ---------------------------------------------------------------------------
-- 1. Herkunft einer Meldung
-- ---------------------------------------------------------------------------
-- Aus welchem Projekt heraus wurde gemeldet? Das ist keine Buchhaltung,
-- sondern das wertvollste Signal im Vorgang: melden drei Projekte unabhaengig
-- dieselbe Sache gegen das Deploymentcenter, ist das kein "low" mehr.
ALTER TABLE bugtracker_items
ADD COLUMN reported_from VARCHAR(64) NULL AFTER created_by;
-- Begruendungspflicht bei Fremdmeldungen: was wurde beobachtet, und warum
-- liegt die Ursache dort und nicht hier. Ein Agent in Projekt X kann kaum
-- unterscheiden, ob das Deploymentcenter kaputt ist oder ob X das SDK falsch
-- benutzt; die Voreinstellung eines hilfsbereiten Modells ist im Zweifel
-- "melde es". Etwas ausformulieren zu muessen kostet einen Reflex fast immer
-- den Kopf.
ALTER TABLE bugtracker_items
ADD COLUMN evidence TEXT NULL AFTER reported_from;
ALTER TABLE bugtracker_items
ADD KEY ix_bt_reported_from (reported_from, status);
-- ---------------------------------------------------------------------------
-- 2. Eigener Eingang fuer Fremdmeldungen
-- ---------------------------------------------------------------------------
-- Fremdmeldungen landen nicht im offenen Backlog, sondern in 'triage_external'
-- und zaehlen erst nach Bestaetigung in die Statistik.
--
-- Das ist kein Misstrauen gegen den meldenden Agenten, sondern Schutz der
-- Auswertung: die Detektoren aus dem Supervisor-Entwurf (Neuheit, Abweichung,
-- Flottenvergleich) kalibrieren auf diesen Zahlen. Ein Detektor, der auf
-- Fehlmeldungen kalibriert, ist wertlos.
--
-- 'triage_external' gilt bewusst NICHT als aktiver Status - open_items und
-- critical_items in getProjects() bleiben dadurch unveraendert sauber.
ALTER TABLE bugtracker_items
MODIFY COLUMN status
ENUM('open','planned','in_progress','resolved','closed','rejected','ignored','triage_external')
NOT NULL DEFAULT 'open';
-- ---------------------------------------------------------------------------
-- 3. Wer ist betroffen?
-- ---------------------------------------------------------------------------
-- Statt drei Items fuer denselben SDK-Fehler entsteht eines mit wachsender
-- Betroffenenliste. Die Buendelung laeuft ueber den dedup_key des Items,
-- nicht ueber client_ref - der ist nur je Melder eindeutig.
CREATE TABLE IF NOT EXISTS bugtracker_item_affects (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
item_id BIGINT NOT NULL,
project_slug VARCHAR(64) NOT NULL,
report_count INT NOT NULL DEFAULT 1,
first_reported_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
last_reported_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY ux_affects (item_id, project_slug),
KEY ix_affects_project (project_slug),
FOREIGN KEY (item_id) REFERENCES bugtracker_items(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ---------------------------------------------------------------------------
-- 4. Beziehungen zwischen Projekten
-- ---------------------------------------------------------------------------
-- dc_projects kannte bisher Slug, Name und Notiz - aber nicht, welches
-- Projekt auf welchem aufsetzt. Damit war die Frage "welche meiner Projekte
-- sind von diesem SDK-Fehler betroffen?" nicht beantwortbar.
--
-- integrated_version loest nebenbei ein Wartungsproblem: die von Hand
-- gepflegte Zeile "Deploymentcenter-Anbindung: SDK 2.5.1" in jeder
-- Projekt-CLAUDE.md wandert hierher. Sie veraltet dort schweigend, sobald
-- jemand sie einmal vergisst.
--
-- Bewusst kein Fremdschluessel auf dc_projects.slug: ein Projekt darf eine
-- Beziehung eintragen, bevor das Gegenstueck angelegt ist. Genauso haelt es
-- bugtracker_items.project_slug.
CREATE TABLE IF NOT EXISTS dc_project_links (
id INT AUTO_INCREMENT PRIMARY KEY,
from_slug VARCHAR(64) NOT NULL,
to_slug VARCHAR(64) NOT NULL,
kind ENUM('uses_sdk','depends_on','shares_code') NOT NULL DEFAULT 'uses_sdk',
integrated_version VARCHAR(32) NULL,
integrated_at DATETIME NULL,
notes VARCHAR(255) NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY ux_link (from_slug, to_slug, kind),
KEY ix_link_to (to_slug, kind)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;