From 20ee173cd0f87abc659993888d873122077c6435 Mon Sep 17 00:00:00 2001 From: Jan-Niclas Loosen Date: Sun, 18 Oct 2026 22:33:10 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20Guides=20und=20Entscheidungsnotiz=20zur?= =?UTF-8?q?=20Divi-Freigabe=20je=20F=C3=A4higkeit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 --- docs/guides/divi-structure.md | 8 ++ docs/guides/overview.md | 26 ++++-- docs/guides/workflows.md | 12 +++ .../notes/2026-10-18-divi-faehigkeiten.md | 80 +++++++++++++++++++ .../Divi/Release/FeatureTextsTest.php | 59 ++++++++++++++ 5 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 docs/superpowers/notes/2026-10-18-divi-faehigkeiten.md create mode 100644 tests/Unit/Integrations/Divi/Release/FeatureTextsTest.php diff --git a/docs/guides/divi-structure.md b/docs/guides/divi-structure.md index adc8fba..3f7d69e 100644 --- a/docs/guides/divi-structure.md +++ b/docs/guides/divi-structure.md @@ -38,6 +38,14 @@ Neue Inhalte und Änderungen: siehe `divi-shortform` (Kurzform, `lit-divi-insert Divi-Builder (`edit_url`) nennen. Der Status bleibt unverändert; veröffentlichte Seiten werden live geändert (vorher entsteht eine Revision, `revision_id`). +## Wenn ein Divi-Werkzeug ablehnt + +`divi_untested` oder `divi_incompatible` heißt: eine Divi-Fähigkeit, die das Werkzeug braucht (z. B. „Seiten +schreiben“), ist für die installierte Divi-Version nicht freigegeben. Das gilt je Fähigkeit – `lit-divi-outline` +kann weiter lesen, auch wenn `lit-divi-insert` ablehnt. `lit-site-status` nennt unter `components` → `divi` → +`features` die betroffenen Fähigkeiten und Werkzeuge; den Nutzer informieren und nicht wiederholen (Vorgehen: +`lit-guide` topic `overview`, Abschnitt „Divi-Fähigkeit nicht freigegeben“). + ## Was nicht bearbeitet wird - Knoten mit „nur lesbar“ (globale Module `g…`, fremde Blöcke `x…`) lassen sich nur als Ganzes verschieben, diff --git a/docs/guides/overview.md b/docs/guides/overview.md index 68e9b6f..bc7c2ff 100644 --- a/docs/guides/overview.md +++ b/docs/guides/overview.md @@ -63,10 +63,24 @@ Für den Einstieg liefert `lit-guide` mit dem Thema „all“ alle Themen in ein `message`, `hint` (und ggf. `fields`). Dem `hint` folgen. - `confirm_required`: Nutzer fragen, dann mit `confirm: true` wiederholen. -## Divi-Version nicht freigegeben +## Divi-Fähigkeit nicht freigegeben -Antwortet ein schreibendes Divi-Werkzeug mit `divi_untested`, ist die installierte Divi-Version für LIT MCP noch nicht -geprüft; bei `divi_incompatible` hat Divi Stellen geändert, die LIT MCP nutzt. In beiden Fällen wurde nichts -geändert. Lesende Divi-Werkzeuge funktionieren weiter und melden den Zustand in `warnings`; `lit-site-status` zeigt -ihn unter `components` → `divi` → `release`. Den Nutzer bitten, unter Einstellungen → LIT MCP → Divi die Prüfung -auszuführen und die Version freizugeben (`divi_untested`) bzw. LIT MCP zu aktualisieren (`divi_incompatible`). +LIT MCP gibt jede Divi-Fähigkeit einzeln frei, z. B. „Seiten lesen“, „Seiten schreiben“, „Presets schreiben“ oder +„Theme Builder lesen“. Nach einem Divi-Update geschieht das automatisch, wenn alle Divi-Stellen, die eine Fähigkeit +nutzt, unverändert sind (geprüft wird die Aufrufform, nicht das Verhalten); sonst nach einer Prüfung durch einen +Administrator. Nur Werkzeuge, die eine nicht nutzbare Fähigkeit brauchen – lesende wie schreibende –, lehnen ab; alle +anderen Divi-Werkzeuge laufen weiter, ebenso `lit-content-create` ohne `divi`. + +Antwortet ein Werkzeug mit `divi_untested`, ist eine Fähigkeit, die es braucht, für die installierte Divi-Version noch +nicht geprüft; bei `divi_incompatible` hat Divi Stellen geändert, die LIT MCP dafür nutzt. In beiden Fällen wurde +nichts geändert. Vorgehen: + +1. Den Aufruf nicht wiederholen: er scheitert, bis ein Administrator eingreift. +2. `lit-site-status` lesen. Unter `components` → `divi` → `features` steht je Fähigkeit der Zustand (`released`, + `untested`, `incompatible`), die Quelle (`code`, `database`, `auto`), die Probleme (`problems`) und die betroffenen + Werkzeuge (`tools`). +3. Ein anderes Werkzeug nutzen, das die betroffene Fähigkeit nicht braucht – ist z. B. nur „Seiten schreiben“ + betroffen, funktioniert `lit-divi-outline` weiter, und der Nutzer kann die Änderung selbst im Divi-Builder machen. +4. Den Nutzer informieren: bei `divi_untested` soll ein Administrator unter Einstellungen → LIT MCP → Divi die + Prüfung ausführen und die Version freigeben; bei `divi_incompatible` muss LIT MCP aktualisiert werden. Die Sperre + nicht über andere Werkzeuge umgehen. diff --git a/docs/guides/workflows.md b/docs/guides/workflows.md index 999623b..691994d 100644 --- a/docs/guides/workflows.md +++ b/docs/guides/workflows.md @@ -22,6 +22,18 @@ 4. `lit-page-render-summary` prüfen, `warnings` beheben, dem Nutzer `preview_url` und `edit_url` (Divi-Builder) nennen. Veröffentlichen nur auf Wunsch (`lit-post-publish`). +## Ein Divi-Werkzeug lehnt ab + +Antwortet ein Divi-Werkzeug mit `divi_untested` oder `divi_incompatible`, ist nur eine Fähigkeit gesperrt, nicht Divi +insgesamt: + +1. `lit-site-status` lesen: `components` → `divi` → `features` nennt je Fähigkeit Zustand, Quelle, Probleme und die + betroffenen Werkzeuge. +2. Mit Werkzeugen weiterarbeiten, deren Fähigkeit `released` ist (z. B. Seiten lesen mit `lit-divi-outline`), und den + gesperrten Teil auslassen. +3. Dem Nutzer sagen, welche Fähigkeit gesperrt ist: bei `untested` muss ein Administrator unter Einstellungen → LIT + MCP → Divi die Prüfung ausführen und freigeben, bei `incompatible` muss LIT MCP aktualisiert werden. + ## Bibliothek und globale Module Vorhandene Abschnitte aus der Divi-Bibliothek zuerst suchen (`lit/library-list`) und mit `lit-library-insert` diff --git a/docs/superpowers/notes/2026-10-18-divi-faehigkeiten.md b/docs/superpowers/notes/2026-10-18-divi-faehigkeiten.md new file mode 100644 index 0000000..758aa60 --- /dev/null +++ b/docs/superpowers/notes/2026-10-18-divi-faehigkeiten.md @@ -0,0 +1,80 @@ +# Divi-Freigabe je Fähigkeit – Entscheidungen + +Stand 2026-10-18, Branch `etappe-4`. Plan: `docs/superpowers/plans/2026-10-18-divi-faehigkeiten.md`. Ersetzt die +pauschale Sperre der Divi-Absicherung (2026-09-29) durch eine Freigabe je Fähigkeit und löst den Kern von Divi. + +## Entscheidungen des Nutzers + +- **E1 Automatische Freigabe je Fähigkeit.** Eine Divi-Version ohne Freigabe wird je Fähigkeit freigegeben, wenn alle + Anforderungen dieser Fähigkeit unverändert sind: jeder Aufruf existiert und nimmt die Argumentzahl an, sein + Signatur-Fingerabdruck stimmt mit `fingerprints.json` überein, jeder Mirror-Fingerabdruck stimmt, jede Konstante + ist definiert. Der Filter `lit_mcp_divi_auto_release` (bool, Standard `true`) schaltet das ab; dann gilt für + nicht freigegebene Versionen wieder „alles ungetestet“. Eine Admin-Freigabe gibt alle Fähigkeiten ohne Probleme frei. +- **E2 Lese-Werkzeuge lehnen ebenfalls ab**, wenn eine ihrer Fähigkeiten nicht nutzbar ist (`divi_untested` bzw. + `divi_incompatible`), statt in `internal_error` zu laufen. Der frühere Hinweis in `warnings` entfällt. +- **E3 Gesperrte Werkzeuge bleiben registriert** und lehnen beim Aufruf ab. `lit-site-status` meldet je Fähigkeit + Zustand, Quelle, Probleme und betroffene Werkzeuge; der Reiter „Divi“ zeigt dieselbe Tabelle; ein Admin-Hinweis + erscheint, sobald eine Fähigkeit nicht nutzbar ist; `wp lit-mcp divi-check` gibt die Matrix aus. +- **E4 Umfang:** Kern-Entkopplung und Sperre je Fähigkeit samt Anzeige; weitere Wartbarkeit kommt später. + +## Umsetzung + +- **Elf Fähigkeiten** (`DiviFeature`): `page-read`, `page-write`, `catalog`, `dynamic-sources`, `design-read`, + `preset-write`, `library-read`, `library-write`, `roles`, `tb-read`, `tb-write`. Jeder Manifest-Eintrag (Aufruf, + Mirror, Konstante) trägt seine Fähigkeiten; geteilte Aufrufe (z. B. `remove_static_resources` für Seiten und Theme + Builder) tragen alle betroffenen, ein Bruch sperrt bewusst beide. Ein Test verlangt mindestens eine Fähigkeit je + Anforderung. +- **Werkzeuge erklären ihre Fähigkeiten** (`RequiresDiviFeatures`, `DeclaresRequirements` für `lit-content-create`, + das nur mit `divi` `page-write` braucht). `DiviFeatureGate` prüft sie vor dem Aufruf, auch im `permission_callback` + (nur bei `tools/call`, nicht beim Auflisten). Die Adapter prüfen vor jedem Schreiben zusätzlich selbst + (`assertFeature`); `DiviSaver` ergänzt je Speicherbereich `library-write` bzw. `tb-write`. +- **Ablehnung:** `divi_untested` (mindestens eine Fähigkeit ungetestet, keine inkompatibel) oder `divi_incompatible`, + HTTP 423, Details `features` (`id`, `label`, `state`, `problems`) und ein Hinweis, der die Fähigkeiten nennt und + sagt, dass andere Divi-Werkzeuge weiter funktionieren. +- **Zustand:** Code-, Signatur- und Konstanten-Prüfungen laufen je Request live. Gecacht wird nur die Mirror-Prüfung + (Transient `lit_mcp_divi_state`, Format 2: Mirror-Probleme mit Art und Fähigkeiten, ein Tag); ein Eintrag im alten + Format zählt als Miss. Ein Divi-Hotfix ohne Versionssprung wird so sofort erkannt. +- **Kern ohne Divi:** `CoreIndependenceTest` erzwingt, dass `Abilities`, `Integrations/{Core,WordPress,Media}`, `Admin` + (außer `DiviTab`), `Guides` und `Server` nichts aus `Integrations\Divi` importieren. + +## Ergänzungen bei der Umsetzung + +- **Signatur-Fingerabdruck vergleicht die Aufrufform, nie das Verhalten.** Er enthält Parameterzahl, Typen und + Rückgabetyp, aber keine Parameternamen und keine Default-Werte (die Adapter rufen Divi positional). 14 der 29 + Divi-Symbole sind untypisiert; dort sichert der Hash nur Aufrufform und Parameterzahl. Ein neuer optionaler + Parameter am Ende sperrt die Fähigkeit (fail closed, gewollt); ein geänderter Default-Wert fällt nicht auf. Die + automatische Freigabe sagt daher „Aufrufe unverändert“, nicht „funktioniert“. +- **Mirror ohne Referenz ist ein harter Befund** (Art `mirror`), auch bei freigegebener Version: sonst würde ein + Nachbau ungeprüft schreiben. „Referenz fehlt → ungetestet“ gilt nur für Aufruf-Signaturen und nur bei nicht + freigegebener Version. +- **Admin-Freigabe und Signaturen:** Die Admin-Freigabe berücksichtigt Signatur-Probleme nicht; Signaturen dienen der + Automatik für Versionen ohne Freigabe. Ein Divi-Hotfix ohne Versionssprung, der nur eine Signatur ändert, sperrt + nach einer Admin-Freigabe nicht; Aufrufe, Mirrors und Konstanten sperren weiter. +- **Registrierungs-Prüfungen** (Post-Typen, Taxonomien, Block-Typen) bleiben informativ und sperren nicht. Die + Schreibprobe bleibt der Seitenpfad und ist nur für die Admin-Freigabe nötig. +- **Protokoll:** Ablehnungen (`ChangeLog`, Ergebnis `refused`) werden nur für schreibende Werkzeuge protokolliert; eine + abgelehnte Lese-Anfrage ändert nichts. Da das Gate vor `permission()` läuft, bekommen Aufrufer ohne Recht die + Divi-Sperre statt `forbidden` und einen Protokolleintrag; es entsteht kein Leck, weil die Antwort nur Fähigkeiten + nennt. Die Eigenschaft `warnings` bleibt im Ausgabeschema der Divi-Werkzeuge. +- **Eingabeabhängige Fähigkeiten:** `lit-site-status` und der Reiter zeigen je Werkzeug die Grundmenge; je nach Eingabe + (Bibliotheks- oder Theme-Builder-Ziel, `dry_run: false`, `nodes`) kommen weitere hinzu. `dynamic-sources` ist eine + Obermenge: ein Bruch sperrt alle Werkzeuge mit Composer. +- **Exit-Code von `wp lit-mcp divi-check`:** 0 = Prüfung grün und alle Fähigkeiten nutzbar, 1 = Prüfung rot, 2 = Prüfung + grün, aber mindestens eine Fähigkeit nicht nutzbar. Skripte, die nur 0/1 kennen, lesen 2 als Fehler – gewollt. +- **Admin-Hinweis:** erscheint für Administratoren bei aktivem Divi auf allen Admin-Seiten außer dem Reiter „Divi“; er ist + nicht wegklickbar und verschwindet mit der Ursache. Die Freigabe-Formulare im Reiter richten sich weiter nach dem + Gesamtzustand; die Freigabe selbst verlangt einen vollständig grünen Prüfbericht. + +## Smoke + +`tests/Integration/divi-release-smoke.sh` simuliert eine Abweichung ohne Divi-Dateien oder `fingerprints.json` +anzufassen: Es trägt ein Mirror-Problem für `page-write` in den Cache `lit_mcp_divi_state` ein. Das kann nur +verschärfen, gilt nur für diesen Schlüssel (`stateKey()`), höchstens zehn Minuten, und der EXIT-Trap löscht den +Transient. Ein Filter im Produktionscode für die Referenz wurde verworfen: er wäre ein zusätzlicher Weg, die Sperre zu +beeinflussen, ohne dass ein Test ihn bräuchte. + +## Offen + +- Der Admin-Hinweis berechnet den Zustand auf jeder Admin-Seite (Reflection und Dateihashes je Aufruf); bei Bedarf + kurzlebig cachen. +- `DesignArea::feature()` braucht für Farben, Variablen und Theme-Optionen später eine eigene Fähigkeit (Etappe 4c/4d). diff --git a/tests/Unit/Integrations/Divi/Release/FeatureTextsTest.php b/tests/Unit/Integrations/Divi/Release/FeatureTextsTest.php new file mode 100644 index 0000000..909be64 --- /dev/null +++ b/tests/Unit/Integrations/Divi/Release/FeatureTextsTest.php @@ -0,0 +1,59 @@ + Path => content of the PHP sources and the guides. */ + private static function texts(): array + { + $root = dirname(__DIR__, 5); + $texts = []; + foreach (glob($root . '/docs/guides/*.md') ?: [] as $file) { + $texts[$file] = (string) file_get_contents($file); + } + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($root . '/src')) as $file) { + if (str_ends_with((string) $file, '.php')) { + $texts[(string) $file] = (string) file_get_contents((string) $file); + } + } + + return $texts; + } + + public function testNoTextLocksWritingAsAWhole(): void + { + $texts = self::texts(); + self::assertNotEmpty($texts); + + foreach ($texts as $path => $text) { + // Join string literals split over lines ('a ' . 'b') so a phrase cannot hide in a line break. + $text = (string) preg_replace('/\'\s*\.\s*\'/', '', $text); + foreach (self::OLD_PHRASES as $phrase) { + self::assertFalse( + stripos($text, $phrase) !== false, + sprintf('%s still says "%s" – name the feature instead', basename($path), $phrase) + ); + } + } + } +}