diff --git a/docs/guides/divi-library.md b/docs/guides/divi-library.md index a5a35ee..07cd346 100644 --- a/docs/guides/divi-library.md +++ b/docs/guides/divi-library.md @@ -33,8 +33,25 @@ Die Divi-Bibliothek speichert Layouts, Abschnitte, Zeilen und Module zur Wiederv - `lit/library-save`: einen Abschnitt, eine Zeile oder ein Modul als neuen Eintrag speichern (`post_id`, `tree_rev`, Pfad-ID `id`, `title`, `scope: "normal"` oder `"global"`, vorhandene `categories`/`tags`). Der Knoten auf der Seite bleibt eine eigenständige Kopie – um ihn zu verknüpfen, ihn durch eine Instanz - ersetzen (siehe Ablauf unten). Ein Knoten, der selbst ein globales Modul ist oder eines enthält, lässt sich - nicht als globaler Eintrag speichern. + ersetzen (siehe Ablauf unten). Ein Knoten, der selbst ein globales Modul ist oder auf einen Eintrag verweist + (auch als Divi-4-Shortcode mit `global_module` in einem Text), lässt sich nicht als globaler Eintrag speichern. +- `lit/library-find-similar`: Knoten finden, die wie ein Knoten (`post_id` und `id`) oder ein Eintrag + (`library_id`) aufgebaut sind. `match: "identical"` = gleicher Inhalt einschließlich aller Texte (nur + Admin-Labels ausgenommen), `"structure"` = gleicher Aufbau (Modultypen, Spalten, Presets) mit anderen Inhalten. + Durchsucht werden Einträge der Divi-Inhaltstypen (optional nur `post_type`), nie Bibliothekseinträge oder + Theme-Builder-Layouts; nur Einträge, die das Konto bearbeiten darf. Höchstens 200 Einträge je Aufruf + (`limit`), weiter mit `next_cursor`; bei sehr vielen Treffern endet ein Aufruf früher und sagt das in `note`. + Jeder Treffer nennt `tree_rev`. +- `lit/library-make-global`: einen Knoten einer Seite oder eines Beitrags in ein globales Modul umwandeln + (`post_id`, `tree_rev`, `id`, `title`, optional `categories`/`tags`): neuer globaler Eintrag mit genau diesem + Inhalt, der Knoten wird durch die Instanz ersetzt – alles oder nichts. Weitere, inhaltsgleiche Vorkommen + ersetzen: `library_id` und `targets` (je `post_id`, `tree_rev`, `ids` der Treffer `"identical"`; höchstens 20 + Seiten). Alle Ziele werden vorher geprüft; ohne `confirm` ist das ein Probelauf (`confirm_required` mit + `affected`), dann `confirm: true`. Jede Seite bekommt eine Revision (`pages`). Nur Seiten und Beiträge + (Inhaltstypen `page` und `post`), die das Konto bearbeiten darf – keine Bibliothekseinträge und keine + Theme-Builder-Layouts, auch nicht als Quelle. Knoten, die auf einen Eintrag verweisen, werden kein globales + Modul. Schlägt eine Seite fehl, bleiben die vorher ersetzten Seiten ersetzt (je mit Revision), die übrigen + unverändert; der Fehler nennt alle drei Gruppen (`changed_posts`, `failed_post`, `unchanged_posts`). - `lit/divi-node-copy`: einen Knoten von einem Eintrag an eine Position eines anderen kopieren (`source_post_id`, `source_id`, `source_tree_rev` aus `lit-divi-outline` der Quelle – Pflicht, weil Pfad-IDs nur für diesen Stand gelten; Ziel mit `post_id`, `tree_rev`, Position). Quelle und Ziel dürfen @@ -84,6 +101,9 @@ wird leer; ein globaler Eintrag enthält keine globalen Module. Nur aktive Eintr `lit-page-render-summary` zeigt globale Module nicht (über die Schnittstelle rendert Divi sie nicht) und nennt sie in `notes`; ihren Inhalt mit `lit-divi-outline` und der ID lesen. +Fügt eine Divi-Änderung einen Abschnitt ein, der wie ein Abschnitt der Bibliothek aufgebaut ist, nennt +`warnings` den Eintrag – dann `lit-library-insert` erwägen. + ## Rechte - WordPress: die Bibliothek nutzen = Beiträge bearbeiten dürfen; einen Eintrag lesen oder ändern = diesen @@ -96,10 +116,8 @@ sie in `notes`; ihren Inhalt mit `lit-divi-outline` und der ID lesen. Hinweis. - Einstellungen → LIT MCP → Tools: Gruppe „Divi-Bibliothek“ auf „nur lesen“ sperrt jeden Schreibzugriff auf Bibliothekseinträge, auch über die Divi-Werkzeuge; deaktiviert gilt jeder Eintrag als nicht vorhanden. - Grenze: Die Einträge selbst sind dann nicht lesbar und nicht änderbar, aber `lit-divi-outline`, - `lit-divi-node-get` und `lit-page-render-summary` einer Seite nennen die ID eines dort verwendeten globalen - Moduls weiterhin (auch ohne das Recht „Divi-Bibliothek“). Diese ID mit den Divi-Werkzeugen zu öffnen, - antwortet `not_found`; dann nicht weiter versuchen. + Ohne das Recht „Divi-Bibliothek“ oder mit deaktivierter Gruppe nennen `lit-divi-outline`, `lit-divi-node-get` + und `lit-page-render-summary` globale Module nur als solche, ohne ihre ID. `lit-library-insert` und `lit/divi-node-copy` sind außerdem gesperrt, wenn `lit-divi-insert` gesperrt ist; `lit/divi-node-copy` mit einem Bibliothekseintrag als Quelle auch, wenn `lit-library-insert` gesperrt ist. - Ohne das Recht `unfiltered_html` überträgt LIT MCP beim Kopieren, Einfügen und Speichern (`lit/divi-node-copy`, @@ -113,13 +131,12 @@ sie in `notes`; ihren Inhalt mit `lit-divi-outline` und der ID lesen. ## Ablauf: globale Module vorschlagen -1. Die Seiten lesen (`lit-divi-outline`) und wiederkehrende Abschnitte suchen (gleiche Admin-Labels oder - Texte, z. B. Kontakt, Öffnungszeiten, Call-to-Action). -2. Dem Nutzer vorschlagen, welche davon globale Module werden sollen, und erklären: eine Änderung wirkt - danach auf allen Seiten. -3. Nach Zustimmung den Abschnitt einer Seite mit `lit/library-save` und `scope: "global"` speichern. -4. Auf jeder Seite (auch der ersten) die Instanz mit `lit-library-insert` direkt vor dem bisherigen Abschnitt - einfügen und den bisherigen Abschnitt nach Rückfrage mit `lit-divi-delete` entfernen. +1. Wiederkehrende Abschnitte suchen: `lit/library-find-similar` mit einem typischen Abschnitt (`post_id`, `id`) + – z. B. Kontakt, Öffnungszeiten, Call-to-Action. +2. Dem Nutzer die Treffer zeigen und erklären: eine Änderung wirkt danach auf allen Seiten mit dem Modul. + Treffer mit `match: "structure"` unterscheiden sich im Inhalt – vorher klären, welche Fassung gilt, und die + übrigen angleichen (`lit-divi-update`) oder weglassen. +3. Nach Zustimmung `lit/library-make-global` mit dem gewählten Abschnitt. +4. Die inhaltsgleichen Vorkommen mit `lit/library-make-global` (`library_id`, `targets` mit der `tree_rev` aus + `lit/library-find-similar`) ersetzen: Probelauf zeigen, dann `confirm: true`. 5. Den Nutzer bitten, das Ergebnis im Divi-Builder anzusehen. - -Unterscheiden sich die Abschnitte in Details, vorher mit dem Nutzer klären, welche Fassung gilt. diff --git a/docs/guides/divi-placeholders.md b/docs/guides/divi-placeholders.md index 8145596..9ec277d 100644 --- a/docs/guides/divi-placeholders.md +++ b/docs/guides/divi-placeholders.md @@ -33,12 +33,16 @@ beginnt (geschützte Meta-Daten), sind nicht erlaubt. In Link-Feldern (`url`, `button_url` …) für interne Links immer `{{link:}}` verwenden statt fester Adressen wie `/?page_id=…`. Der Eintrag muss existieren und für das Konto lesbar sein; Einträge im Papierkorb, -automatische Entwürfe und Medien (Anhänge – dafür die Adresse aus der Mediathek) lehnt das Werkzeug ab, -ebenso `{{link:…}}` außerhalb von Link-Feldern. Solange das Ziel ein Entwurf oder privat ist, zeigt Divi +automatische Entwürfe, Einträge der Divi-Bibliothek und Medien (Anhänge – dafür die Adresse aus der Mediathek) +lehnt das Werkzeug ab – wie eine unbekannte ID –, ebenso `{{link:…}}` außerhalb von Link-Feldern. Solange das Ziel ein Entwurf oder privat ist, zeigt Divi Besuchern nur die Adresse `?page_id=` (kein Titel); nach dem Veröffentlichen die normale Adresse. Sonst nimmt ein Link-Feld jeden dynamischen Inhalt an; sinnvoll sind nur Werte, die eine Adresse ergeben (`{{post:url}}`, ein Feld mit einer URL, eine Link-Variable). +Dieselben Regeln gelten für die Vollform `post_link_url_` mit `post_id`: das Ziel muss lesbar sein, darf +nicht im Papierkorb liegen, kein Anhang und kein Bibliothekseintrag sein und muss genau den Typ im Namen haben +(`post_link_url_page` nur für Seiten). `{{link:}}` wählt den passenden Namen selbst. + Welche dynamischen Quellen und Felder es für einen Inhaltstyp gibt, liefert `lit/divi-dynamic-sources` (über `mcp-adapter-execute-ability`): Divis Quellen mit Platzhalter und die Felder, die sich als `{{field:…}}` eignen. Gelistet werden nur textartige Felder; Beziehungs- und Dateifelder (Divi zeigt sie nur diff --git a/docs/guides/overview.md b/docs/guides/overview.md index a41a34b..b32d854 100644 --- a/docs/guides/overview.md +++ b/docs/guides/overview.md @@ -23,9 +23,9 @@ Direkt sichtbar: `lit-guide`, `lit-site-status`, `lit-content-types`, `lit-conte `lit-divi-outline`, `lit-divi-node-get`, `lit-divi-catalog`, `lit-divi-design-system`, `lit-divi-insert`, `lit-divi-update`, `lit-divi-move`, `lit-divi-delete`, `lit-library-insert`. -Die Tools sind nach Integration gruppiert (Grundlagen, WordPress, Medien, Divi, Divi-Bibliothek). Jede Gruppe hat unter -Einstellungen → LIT MCP → Tools eine eigene Einstellung (direkt/indirekt/deaktiviert), die ihre Tools übernehmen -(„wie Gruppe“). Eine Einstellung am einzelnen Tool geht vor; die Gruppe zeigt dann „gemischt“. „nur lesen“ +Die Tools sind nach Integration gruppiert (Grundlagen, WordPress, Medien, Divi, Divi-Bibliothek, +Divi Theme Builder). Jede Gruppe hat unter Einstellungen → LIT MCP → Tools eine eigene Einstellung +(direkt/indirekt/deaktiviert), die ihre Tools übernehmen („wie Gruppe“). Eine Einstellung am einzelnen Tool geht vor; die Gruppe zeigt dann „gemischt“. „nur lesen“ schaltet alle schreibenden Tools der Gruppe ab – auch solche mit eigener Einstellung. `lit-guide` bleibt immer direkt; `lit-media-preview`/`lit-media-download` bleiben bei Gruppe „indirekt“ direkt. Ab mehr als 25 direkten Tools warnt die Seite (Kontextkosten im Assistenten). Änderungen gelten ab der nächsten Verbindung. @@ -37,13 +37,17 @@ Status (`lit/post-unpublish`, `lit/post-schedule`, `lit/post-trash`), Kopien (`l (`lit/menu-list`, `lit/menu-get`, `lit/menu-create`, `lit/menu-set-items`, `lit/menu-assign-location`), Einstellungen (`lit/wp-settings-get`, `lit/wp-settings-update`), Medien (`lit/media-get`, `lit/media-upload`, `lit/media-update`, `lit/media-delete`), Divi (`lit/divi-duplicate-node`, `lit/divi-replace-text`, -`lit/divi-node-copy`, `lit/divi-dynamic-sources`), Divi-Bibliothek (`lit/library-list`, `lit/library-save`). +`lit/divi-node-copy`, `lit/divi-dynamic-sources`), Divi-Bibliothek (`lit/library-list`, `lit/library-save`, +`lit/library-find-similar`, `lit/library-make-global`), Divi Theme Builder (`lit/tb-list`, +`lit/tb-create-template`, `lit/tb-assign`, `lit/tb-activate`). Die `lit-divi-…`-Werkzeuge gibt es nur, wenn der Divi-5-Builder aktiv ist. Sie arbeiten auch auf Einträgen -der Divi-Bibliothek (ID als `post_id`); globale Module: `lit-guide` topic `divi-library`. +der Divi-Bibliothek und auf Layouts des Theme Builders (ID als `post_id`); globale Module: `lit-guide` topic +`divi-library`, Vorlagen: `lit-guide` topic `theme-builder`. Weitere Themen: `lit-guide` mit `topic` = `content-types`, `workflows`, `media`, `divi-structure`, -`divi-shortform`, `divi-attrs`, `divi-placeholders`, `divi-design-system` oder `divi-library`. +`divi-shortform`, `divi-attrs`, `divi-placeholders`, `divi-design-system`, `divi-library` oder +`theme-builder`. Für den Einstieg liefert `lit-guide` mit dem Thema „all“ alle Themen in einem Aufruf. diff --git a/docs/guides/theme-builder.md b/docs/guides/theme-builder.md new file mode 100644 index 0000000..f6475bf --- /dev/null +++ b/docs/guides/theme-builder.md @@ -0,0 +1,117 @@ +# Divi Theme Builder + +Der Theme Builder legt fest, wie Kopfzeile, Inhalt und Fußzeile für bestimmte Seiten aussehen – z. B. für alle +Einträge eines eigenen Inhaltstyps. Eine **Vorlage** hat Bedingungen („gilt für alle Personen“) und bis zu drei +**Layouts** (Kopfzeile, Inhalt, Fußzeile). Die **Standardvorlage** gilt überall, wo keine andere greift; ihre +Kopf- und Fußzeile heißen „global“, weil andere Vorlagen sie mitbenutzen. + +## Grundregel: nichts wird ohne Freigabe sichtbar + +- Neue Vorlagen legt LIT MCP immer **deaktiviert** an – Besucher sehen nichts davon. +- Aktivieren und Deaktivieren gibt es nur mit `lit/tb-activate`, und immer so: Probelauf (Bedingungen, Layouts, + andere aktive Vorlagen mit denselben oder verwandten Bedingungen unter `overlaps`/`possible_overlaps`) → + Nutzer fragen → dieselbe Anfrage mit `confirm: true`. +- Auch alles andere, was Besucher sofort sähen, ist zuerst ein Probelauf (`confirm_required`) und braucht + `confirm: true`: Bedingungen einer aktiven Vorlage ändern (`lit/tb-assign`) und ein Layout ändern, das eine + aktive Vorlage zeigt (die `lit-divi-…`-Werkzeuge; die Antwort nennt die Vorlagen unter `templates`). Vor dem + Speichern eines sichtbaren Layouts entsteht eine Revision; sind Revisionen abgeschaltet, eine + Sicherungskopie im Papierkorb (`backup_id`). +- `lit/divi-replace-text` ändert sichtbare Layouts nicht; solche Änderungen mit `lit-divi-update` und + `confirm: true` vornehmen. +- Die Standardvorlage ändert LIT MCP nicht (nur im Theme Builder). + +## Werkzeuge (über `mcp-adapter-execute-ability`) + +- `lit/tb-list`: alle Vorlagen mit `enabled`, `live` (für Besucher wirksam), Bedingungen (`use_on`, + `exclude_from` und Beschriftungen), Layouts (`id`, Titel, `shared_with` = andere Vorlagen mit demselben + Layout) und `template_rev`. `template_id`: nur diese Vorlage. `conditions: true` liefert alle Bedingungen, + die Divi anbietet; eine ID, die auf „:“ endet, braucht ein Objekt am Ende, z. B. + `singular:post_type:page:id:42`. `detached` zeigt Vorlagen, die ein Speichern im Theme Builder entfernt hat + (siehe unten); `draft_pending` zeigt ungespeicherte Änderungen im Theme Builder. +- `lit/tb-create-template`: `title`, je Bereich (`header`, `body`, `footer`) `source`: + `"new"` (neues Layout; optional `nodes` wie bei `lit-divi-insert` und `title`), `"global"` (Kopf-/Fußzeile + der Standardvorlage mitbenutzen; nicht für `body`), `"default"` (nichts Eigenes, Standard bei fehlender + Angabe) oder `"hidden"` (Bereich ausblenden). Optional `use_on`/`exclude_from`. Alles oder nichts: schlägt + ein Schritt fehl, entfernt LIT MCP alles wieder. Antwort: `template_id`, `template_rev`, `enabled: false`, + `layouts`. +- `lit/tb-assign`: Bedingungen ersetzen (`template_id`, `template_rev`, `use_on`). Fehlt `exclude_from`, + bleiben die bisherigen Ausnahmen; `[]` entfernt sie. Der Probelauf einer aktiven Vorlage zeigt vorher/nachher + (`before`, `after`) und Überschneidungen. Die Antwort nennt die bisherigen Bedingungen unter `previous`. +- `lit/tb-activate`: `enabled: true` oder `false` (`template_id`, `template_rev`). Deaktivieren ist der + schnelle Weg zurück. Zum Aktivieren müssen alle Layouts der Vorlage noch aktiv sein. +- Layouts bearbeiten: `lit-divi-outline`, `lit-divi-node-get`, `lit-divi-insert`, `lit-divi-update`, + `lit-divi-move`, `lit-divi-delete` … mit der Layout-ID als `post_id` (aus `lit/tb-list`). Benutzt eine + andere Vorlage dasselbe Layout (`shared_with`), wirkt die Änderung auch dort. Das Modul „Beitragsinhalt“ + (`post-content`) gibt es nur im Inhalt-Layout, nicht in Kopf- oder Fußzeile. + +## Bedingungen + +Erlaubt sind nur die Bedingungen, die Divi selbst anbietet (`lit/tb-list` mit `conditions: true`), höchstens 50 +je Liste. Ein Objekt am Ende (Seite, Beitrag, Begriff, Person) muss existieren und für das Konto lesbar bzw. +zuweisbar sein; sonst lautet die Antwort wie bei einer unbekannten ID. Bedingungen für Autoren +(`archive:user:id:…`) verlangen das Recht, Benutzer aufzulisten (`list_users`) – strenger als Divi. + +## Felder im Inhalt-Layout (Dynamic Content) + +Im Inhalt-Layout zeigen Platzhalter die Daten des jeweiligen Eintrags: `{{post:title}}`, `{{post:excerpt}}`, +`{{post:date}}` und Felder als `{{field:}}`. Welche Felder ein Inhaltstyp hat und welche Divi als Text +zeigt, liefert `lit/divi-dynamic-sources` mit `post_type`. Nur textartige Felder eignen sich: Bei Auswahlfeldern +zeigt Divi den gespeicherten Wert, nicht die Beschriftung; Beziehungs- und Dateifelder zeigen nur IDs, Pods mit +Tabellen-Speicherung gar nichts. + +LIT MCP prüft die Felder eines geänderten Inhalt-Layouts gegen die Inhaltstypen aus den Bedingungen +(`singular:post_type::…`) der Vorlagen, die das Layout benutzen, und warnt (`warnings`) – gespeichert wird +trotzdem. Das gilt für die Kurzform `{{field:…}}` und für Felder, die im Divi-Builder über „Benutzerdefiniertes +Feld“ gewählt wurden. Bei einem sichtbaren Layout stehen die Warnungen schon im Probelauf. Ohne solche Bedingung +bleiben die Felder ungeprüft (die Antwort sagt das). Kopf- und Fußzeile werden nicht geprüft. + +## Wenn der Theme Builder gerade offen ist + +- Hat der Theme Builder ungespeicherte Änderungen (Entwurf, `draft_pending`), lehnen `lit/tb-create-template`, + `lit/tb-assign` und das Aktivieren ab: erst dort speichern oder verwerfen. +- Deaktivieren (`lit/tb-activate` mit `enabled: false`) geht immer – auch dann, und auch bei einer aktiven + Vorlage im Papierkorb. Die Antwort warnt: Speichert jemand ein offenes Theme-Builder-Fenster, kann Divi + seinen eigenen Stand wiederherstellen; danach mit `lit/tb-list` prüfen. +- Speichert jemand in einem Theme-Builder-Fenster, das vor dem Anlegen einer Vorlage geöffnet wurde, entfernt + Divi die neue Vorlage wieder aus der Liste und löscht sie 7 Tage später. `lit/tb-list` zeigt sie dann unter + `detached` (mit `marked_unused`). Nur auf ausdrücklichen Wunsch: `lit/tb-assign` mit `reattach: true` ordnet + sie wieder zu – immer deaktiviert, und nur, wenn ihre Layouts noch aktiv sind. + +## Rechte + +- WordPress: „Beiträge anderer bearbeiten“ (`edit_others_posts`) und „Design bearbeiten“ + (`edit_theme_options`); je Vorlage und Layout das Recht, sie zu bearbeiten; zum Anlegen zusätzlich + „veröffentlichen“ (Divi legt Vorlagen und Layouts sofort aktiv an). +- Divi → Rollen-Editor: „Theme Builder“ – standardmäßig nur für Administratoren. +- Fehlt eines davon, gibt es für dieses Konto keine Vorlagen und Layouts (`not_found` wie bei einer unbekannten + ID bzw. `forbidden`). Vorlagen, die das Konto nicht bearbeiten darf, erscheinen nirgends; aktive davon nur als + Anzahl (`hidden_live` in `lit/tb-list`, `hidden_overlaps` im Probelauf). +- Einstellungen → LIT MCP → Tools: Gruppe „Divi Theme Builder“ auf „nur lesen“ sperrt jedes Schreiben, auch über + die `lit-divi-…`-Werkzeuge; deaktiviert gibt es keine Vorlagen und Layouts. + +## Globale Module im Theme Builder + +`lit/library-make-global` wandelt keine Knoten in Theme-Builder-Layouts um. Stattdessen den Abschnitt mit +`lit/library-save` (`scope: "global"`) speichern und mit `lit-library-insert` (`mode: "global"`) einfügen +(`lit-guide` topic `divi-library`). + +## Rückgängig machen + +Vorlagen haben keine Revisionen: `lit/tb-assign` nennt die bisherigen Bedingungen (`previous`), `lit/tb-activate` +schaltet zurück; jede Änderung steht im Protokoll. Layouts erhalten wie Divi-Seiten eine Revision. Neu angelegte +Vorlagen im Divi Theme Builder löschen. + +## Ablauf: Vorlage für einen Inhaltstyp (custom-post-type-vorlage) + +1. Inhaltstyp und Felder klären: `lit-content-types`, dann `lit/divi-dynamic-sources` mit `post_type`. +2. `lit/tb-list` lesen: gibt es schon eine Vorlage für den Typ? Gibt es eine globale Kopf-/Fußzeile? +3. Mit dem Nutzer den Aufbau abstimmen (welche Felder, welche Reihenfolge, Kopf-/Fußzeile global oder eigen). +4. `lit/tb-create-template` mit `use_on: ["singular:post_type::all"]`, `header`/`footer` meist + `{"source": "global"}`, `body` mit `source: "new"` und `nodes` (Überschrift `{{post:title}}`, Texte mit + `{{field:…}}`, das Modul `post-content`, wenn der Eintrag eigenen Inhalt hat). Warnungen zu Feldern beachten. +5. Das Inhalt-Layout bei Bedarf mit `lit-divi-outline`/`lit-divi-update` verfeinern (Layout-ID als `post_id`; + solange die Vorlage deaktiviert ist, ohne Probelauf). +6. Den Nutzer bitten, die Vorlage im Theme Builder anzusehen (Vorschau eines Eintrags ist erst nach dem + Aktivieren möglich). +7. Erst auf ausdrücklichen Wunsch: `lit/tb-activate` mit `enabled: true` – Probelauf zeigen, dann + `confirm: true`. diff --git a/docs/guides/workflows.md b/docs/guides/workflows.md index 87734f8..d13faf8 100644 --- a/docs/guides/workflows.md +++ b/docs/guides/workflows.md @@ -26,8 +26,9 @@ Vorhandene Abschnitte aus der Divi-Bibliothek zuerst suchen (`lit/library-list`) und mit `lit-library-insert` einfügen, statt sie neu zu bauen. Einen gelungenen Abschnitt für später speichern: `lit/library-save`. -Abschnitte zwischen Seiten kopieren: `lit/divi-node-copy`. Globale Module ändern und neue vorschlagen: -`lit-guide` topic `divi-library`. +Abschnitte zwischen Seiten kopieren: `lit/divi-node-copy`. Wiederkehrende Abschnitte finden und zu globalen +Modulen machen: `lit/library-find-similar`, `lit/library-make-global`. Globale Module ändern und neue +vorschlagen: `lit-guide` topic `divi-library`. ## Text auf vielen Seiten ersetzen @@ -68,3 +69,9 @@ geändert, sondern in `skipped_nodes` genannt – sie im Bibliothekseintrag änd 1. `lit-content-types` mit `post_type` → Pflichtfelder, Auswahlwerte, Beziehungsziele. 2. `lit-content-create` mit allen Pflichtfeldern in `fields`. 3. Beziehungen über IDs (vorher mit `lit-content-query` suchen). + +## Vorlage für einen Inhaltstyp (Theme Builder) + +Wie Einträge eines Inhaltstyps (z. B. Personen) auf der Website aussehen, legt eine Theme-Builder-Vorlage fest. +Ablauf und Regeln: `lit-guide` topic `theme-builder`. Neue Vorlagen sind deaktiviert; aktiviert wird nur auf +ausdrücklichen Wunsch mit `lit/tb-activate`. diff --git a/docs/superpowers/notes/2026-09-27-etappe-3-entscheidungen-entwurf.md b/docs/superpowers/notes/2026-09-27-etappe-3-entscheidungen-entwurf.md index 9ff14d8..11feafb 100644 --- a/docs/superpowers/notes/2026-09-27-etappe-3-entscheidungen-entwurf.md +++ b/docs/superpowers/notes/2026-09-27-etappe-3-entscheidungen-entwurf.md @@ -220,3 +220,46 @@ Quellen der Web-Recherche: [Divi AI Agent – Ankündigung](https://www.elegantt Divi-Katalog beim Standard von 128M nicht mehr in den Speicher passt. - Server-Instructions: Zeile „Divi-Bibliothek: …“ nur bei aktiver, beschreibbarer Gruppe; MCP-Prompts gibt es noch nicht, der Ablauf „globale Module vorschlagen“ steht im Guide `divi-library` (E14). + +## 7. Umsetzung Etappe 3b (Plan 2026-09-27-etappe-3b-theme-builder.md) + +Rulings Q1–Q25: `.superpowers/sdd/2026-09-27-etappe-3b-theme-builder/progress.md`. + +- E7 präzisiert: Layouts und neue Vorlagen über `et_theme_builder_insert_layout`/`et_theme_builder_store_template` + mit Rechteprüfung davor und `wp_die`-Sperre währenddessen; Zuordnung zur Live-Liste, Bedingungen und + `_et_enabled` als Nachbildung von Divis Meta-Schreibweise (store_template würde bei bestehenden Vorlagen auch + Standard-Kennzeichen, Titel und Onboarding-Meta neu schreiben). Nach dem Anlegen Rücklesen; Abweichung = + alles zurücknehmen, auch Posts, die Divi vor einem Fehler schon eingefügt hatte (Q19). +- E8/Antwort F1 umgesetzt als eigenes Tool `lit/tb-activate` (statt `enabled` in `lit/tb-assign`); neue Vorlagen + sind immer deaktiviert. Jede andere Änderung, die Besucher sofort sähen (Bedingungen aktiver Vorlagen, Layouts + aktiver Vorlagen), ist zuerst ein Probelauf und braucht `confirm`; Layouts mit der Sicherung aus + `VisibleEdits` (Q2, Q9). Aktiv = zugeordnet und `_et_enabled`, unabhängig vom Post-Status (Q8). +- Der Ausschalter (`lit/tb-activate` mit `enabled: false`) geht immer: auch bei TB-Entwurf, dann mit Warnung + (Q20), und bei einer aktiven Vorlage im Papierkorb (Q16). +- TB-Editor: Ablehnung bei TB-Entwurf; neue Vorlagen hängen sofort an der Live-Liste; `lit/tb-list` zeigt vom + Theme Builder entfernte Vorlagen (`detached`), `lit/tb-assign` mit `reattach` ordnet sie deaktiviert wieder zu + (nur mit aktiven Layouts, Q8/B10). Befunde 10–12: `tests/Fixtures/divi/stage3b/README.md`. +- E3 für den Theme Builder: `edit_others_posts`, `edit_theme_options` (Q15) und Divis Rollen-Recht + „Theme Builder“, je Vorlage/Layout `edit_post`, zum Anlegen die Veröffentlichen-Rechte. Nicht bearbeitbare + Vorlagen antworten wie fehlende (Q18); aktive davon nur als Anzahl in Liste und Probeläufen + von `lit/tb-assign`/`lit/tb-activate` (Q21; für die Probeläufe der Layout-Änderungen folgt Q22 in der + Schlussrunde). +- Bedingungen nur aus Divis Katalog; Objekte lesbar (Begriffe: `assign_term`); strenger als Divi: + Autoren-Bedingungen (`archive:user:id:`) nur mit `list_users` (Q10). +- E9: eigene Gruppe „Divi Theme Builder“ (`divi-theme-builder`); alle neuen Tools indirekt, 22 direkte Tools. +- E10/E11 umgesetzt mit `Fingerprint` (Struktur/Inhalt). „Inhaltsgleich“ heißt gleiche Bytes einschließlich + Textteilen zwischen Blöcken und Inhalt von Core-Blöcken, nur Admin-Labels ausgenommen (Q25); ersetzt wird nur + auf Seiten und Beiträgen (`page`, `post`), die das Konto bearbeiten darf – Theme-Builder-Layouts auch nicht als + Quelle (Q24). Globale Einträge enthalten keinen Verweis auf einen Eintrag in irgendeiner Schreibweise (Q7). + D10-Semantik beim Speichern mehrerer Seiten: Abbruch bei der ersten gescheiterten Seite, Fehler nennt + geänderte, gescheiterte und unveränderte Seiten. +- E12: Feldprüfung im Inhalt-Layout als Warnung gegen die Inhaltstypen der Vorlagen-Bedingungen, beide + Feldformen (Q11). +- P13 (vollständiges Ausblenden der Bibliotheks-IDs, auch im Suchen-und-Ersetzen) und P10 (Zielregeln der + Vollform `post_link_url_*`, Bibliothekseinträge und Typen ohne Divi-Linkoption wie fehlende IDs, Q14) + umgesetzt. +- Restrisiken: P25 (ungewöhnliche Schreibweisen globaler Verweise), dazu Divis erneutes Auswerten von Blöcken in + Shortcode-Modulen und WooCommerce-Textmodulen (dokumentiert im Guide `divi-library`); das Präfilter-Orakel von + `lit/divi-replace-text` (Q13) und die Race-Bedingungen zwischen Prüfen und Schreiben bleiben für Etappe U. +- Server-Instructions: Zeile „Divi Theme Builder: …“ nur bei aktiver, beschreibbarer Gruppe; der Ablauf + „custom-post-type-vorlage“ steht im Guide `theme-builder`. diff --git a/docs/superpowers/specs/2026-09-25-wp-lit-mcp-design.md b/docs/superpowers/specs/2026-09-25-wp-lit-mcp-design.md index 5647575..6f21a62 100644 --- a/docs/superpowers/specs/2026-09-25-wp-lit-mcp-design.md +++ b/docs/superpowers/specs/2026-09-25-wp-lit-mcp-design.md @@ -114,7 +114,7 @@ Ob dieser Aufbau stabil funktioniert, entscheidet Etappe 0 (§12). - **Direkte Tools (~20):** mit vollem Schema sofort sichtbar; nur direkte Tools können Bilder (`ImageContent`) zurückgeben. Standard-Set: `lit/guide`, `lit/content-types`, `lit/content-query`, `lit/content-get`, `lit/content-create`, `lit/content-update`, `lit/post-publish`, `lit/media-search`, `lit/media-preview`, `lit/media-upload-from-url`, `lit/divi-outline`, `lit/divi-node-get`, `lit/divi-insert`, `lit/divi-update`, `lit/divi-move`, `lit/divi-delete`, `lit/divi-design-system`, `lit/divi-catalog`, `lit/library-insert`, `lit/page-render-summary`. -- **Stand nach Etappe 2 (Entscheidung D2, 2026-09-26):** 21 direkte Tools – das Standard-Set oben ohne `lit/library-insert` (kommt mit Etappe 3), dazu `lit/site-status` (leeres Eingabeschema, Anker der Verbindungstests) und `lit/media-download` (eingebettete Ressource, funktioniert nur direkt). `lit/divi-duplicate-node` und `lit/divi-replace-text` sind indirekt. Mit Etappe 3 sind es 22; das Budget wird dort erneut geprüft (Kosten entstehen vor allem durch große Eingabeschemas, nicht durch die Zahl). **Stand nach Etappe 3a:** 22 direkte Tools (dazu `lit/library-insert`); indirekt neu `lit/library-list`, `lit/library-save`, `lit/divi-node-copy`, `lit/divi-dynamic-sources`. Neue Tool-Gruppe „Divi-Bibliothek“ (`lit/library-*`); `lit/divi-node-copy` und `lit/divi-dynamic-sources` gehören zur Gruppe „Divi“. +- **Stand nach Etappe 2 (Entscheidung D2, 2026-09-26):** 21 direkte Tools – das Standard-Set oben ohne `lit/library-insert` (kommt mit Etappe 3), dazu `lit/site-status` (leeres Eingabeschema, Anker der Verbindungstests) und `lit/media-download` (eingebettete Ressource, funktioniert nur direkt). `lit/divi-duplicate-node` und `lit/divi-replace-text` sind indirekt. Mit Etappe 3 sind es 22; das Budget wird dort erneut geprüft (Kosten entstehen vor allem durch große Eingabeschemas, nicht durch die Zahl). **Stand nach Etappe 3a:** 22 direkte Tools (dazu `lit/library-insert`); indirekt neu `lit/library-list`, `lit/library-save`, `lit/divi-node-copy`, `lit/divi-dynamic-sources`. Neue Tool-Gruppe „Divi-Bibliothek“ (`lit/library-*`); `lit/divi-node-copy` und `lit/divi-dynamic-sources` gehören zur Gruppe „Divi“. **Stand nach Etappe 3b:** weiterhin 22 direkte Tools; indirekt neu `lit/tb-list`, `lit/tb-create-template`, `lit/tb-assign`, `lit/tb-activate` (neue Tool-Gruppe „Divi Theme Builder“; „nur lesen“ sperrt auch Schreibzugriffe der Divi-Werkzeuge auf Theme-Builder-Layouts, deaktiviert gelten Vorlagen und Layouts als nicht vorhanden) sowie `lit/library-find-similar`, `lit/library-make-global` (Gruppe „Divi-Bibliothek“). - **Alle übrigen Abilities:** über die Meta-Tools des Adapters (`discover-abilities`, `get-ability-info`, `execute-ability`). - In den Einstellungen änderbar, welche Abilities direkt, indirekt oder deaktiviert sind. - Ability-Namen: `lit/-`. Der Adapter bildet daraus Tool-Namen (`lit--`). @@ -159,7 +159,7 @@ tests/Unit, tests/Integration, tests/Fixtures 1. **Verbinden:** mcp-oauth-Autorisierung (jeder eingeloggte Benutzer). 2. **Nutzen:** Capability `lit_mcp_use` (nur freigegebene Rollen) – geprüft über Adapter-Filter und in jeder Ability. -3. **Handeln:** konkrete Prüfung pro Ability, z. B. `edit_post` für die Ziel-ID, `publish_post` fürs Veröffentlichen, `upload_files`, `edit_theme_options` für Divi-Designsystem und Menüs, `manage_options` für WP-Einstellungen, `edit_others_posts` für Theme Builder (Divi-Anforderung). +3. **Handeln:** konkrete Prüfung pro Ability, z. B. `edit_post` für die Ziel-ID, `publish_post` fürs Veröffentlichen, `upload_files`, `edit_theme_options` für Divi-Designsystem und Menüs, `manage_options` für WP-Einstellungen, `edit_others_posts`, `edit_theme_options` und Divis Rollen-Recht „Theme Builder“ für den Theme Builder (Divi-Anforderung und Gate von Divis Theme-Builder-Seite; Etappe 3b), dazu `edit_post` je Vorlage/Layout; Vorlagen ohne `edit_post` antworten wie fehlende IDs, aktive davon erscheinen nur als Anzahl. ## 5. Divi-Kern @@ -229,7 +229,7 @@ Jede Schreib-Rückmeldung enthält Warnungen zu: - leeren Modulen, - Sprüngen in der Überschriftenhierarchie, - Verwendung des Code-Moduls, -- ähnlichen, bereits existierenden Abschnitten (Hinweis auf `lit/library-find-similar`) – ab Etappe 3 zusammen mit `lit/library-find-similar` (D6). +- ähnlichen, bereits existierenden Abschnitten (Hinweis auf `lit-library-insert` und `lit/library-find-similar`) – verglichen wird nur ein neu eingefügter Abschnitt mit den Abschnitten der Divi-Bibliothek (Struktur-Fingerabdruck, höchstens 200 Einträge, je Anfrage einmal gelesen), nur mit Bibliothekszugang (Gruppe nicht deaktiviert, Recht „Divi-Bibliothek“; P13) und nicht bei `lit/library-insert` selbst (Etappe 3b, E11). Kurzform setzt Admin-Labels automatisch (` – `), sofern nicht angegeben. @@ -238,7 +238,7 @@ Kurzform setzt Admin-Labels automatisch (` – `), sofern nich 1. Rechte prüfen (`edit_post`), `tree_rev` prüfen. 2. Änderung auf dem BlockTree ausführen, validieren (alles oder nichts). 3. Serialisieren, `wp_slash()`, `wp_update_post()` – Status unverändert, vorher Wiederherstellungspunkt (Revision). Für Benutzer ohne `unfiltered_html` wird kses für genau diesen Aufruf abgeschaltet: `filter_block_content()` würde sonst jeden unveränderten Block neu serialisieren (Byte-Identität, globale Module; in DDEV nachgewiesen). Das ist nur vertretbar, weil keine client-gelieferte Zeichenkette ungeprüft in `post_content` gelangt (D7): Klartext-Werte werden je Feldtyp bereinigt (Text: `sanitize_text_field`; Rich-Text: `wp_kses_post`, abhängig von `unfiltered_html`; URLs: `esc_url_raw`, geroutet über die Attribut-Metadaten des Katalogs, ersatzweise über den Schlüsselnamen). Werte mit `$variable(...)$` – ob aus Platzhaltern erzeugt oder unverändert aus `lit/divi-node-get` zurückgegeben – werden geparst, streng geprüft (zulässiger Typ, existierende gcid-/gvid-/Dynamic-Content-Quellennamen, whitelisted Settings-Schlüssel, String-Settings bereinigt) und vom Plugin neu serialisiert; alles andere wird mit `validation_failed` abgelehnt. Ob Divi das Dynamic-Content-`before`/`after` bei der Ausgabe selbst escaped, wird in Etappe 2b im Divi-Quellcode verifiziert; die Bereinigung gilt unabhängig davon (Verteidigung in der Tiefe, R2). -4. Post-Meta `_et_pb_use_divi_5=on`, `_et_pb_use_builder=on` setzen. +4. Post-Meta `_et_pb_use_divi_5=on`, `_et_pb_use_builder=on` setzen (Seiten und Theme-Builder-Layouts; Bibliothekseinträge nicht). 5. `ET_Core_PageResource::remove_static_resources($post_id, 'all', true)`; bei globalen Library-Elementen und Theme-Builder-Änderungen `('all', 'all', true)` sowie `et_theme_builder_clear_wp_cache('all')`. 6. Protokolleintrag, `ToolResult` zurückgeben. @@ -262,11 +262,12 @@ Kurzform setzt Admin-Labels automatisch (` – `), sofern nich | `lit/library-save` | schreiben | Knoten als Library-Eintrag speichern (normal oder global; global braucht Divis „Globale Bibliothekselemente bearbeiten“, P7); Knoten auf der Seite bleibt unverändert; StoredNodeGuard (E6) | | `lit/library-insert` | schreiben | Library-Eintrag als Kopie oder globale Instanz im Format des Visual Builders (`localAttrs`-Schnappschuss, `globalParent`) einfügen; direkt | | `lit/divi-node-copy` | schreiben | Knoten von Eintrag A nach Eintrag B kopieren (Seiten und Bibliothekseinträge; byte-gleich, `source_tree_rev` Pflicht, S7/S26-Prüfung E6) | -| `lit/library-make-global` | schreiben | Knoten in globales Modul umwandeln; optional gleichartige Vorkommen ersetzen | -| `lit/library-find-similar` | lesen | ähnliche Abschnitte seitenübergreifend (Struktur-Fingerabdruck: Modultypen, Aufbau, Presets) | -| `lit/tb-list` | lesen | Vorlagen, Bedingungen, Layouts | -| `lit/tb-create-template` | schreiben | Vorlage mit Header/Body/Footer-Layouts anlegen (`et_theme_builder_insert_layout`, `et_theme_builder_store_template`, Meta `_et_template`) | -| `lit/tb-assign` | schreiben | Bedingungen (`_et_use_on`/`_et_exclude_from`, z. B. `singular:post_type:person:all`) setzen | +| `lit/library-make-global` | schreiben | Knoten in globales Modul umwandeln (alles oder nichts); optional gleichartige Vorkommen ersetzen: gleichartig = inhaltsgleich einschließlich aller Texte (Inhalts-Fingerabdruck und normalisierte Bytes), `library_id` + `targets`, Probelauf + `confirm`, P8a, Revision je Seite; Seite N scheitert → vorherige bleiben ersetzt, Fehler nennt geänderte/gescheiterte/unveränderte Seiten (E10). Nur Inhaltstypen `page` und `post` – keine Bibliothekseinträge, keine Theme-Builder-Layouts, auch nicht als Quelle; Knoten mit Verweis auf einen Eintrag (jede Schreibweise) werden kein globales Modul | +| `lit/library-find-similar` | lesen | ähnliche Abschnitte seitenübergreifend (Struktur-Fingerabdruck: Modultypen, Aufbau, Presets) und Inhalts-Fingerabdruck (`identical`); höchstens 200 Einträge je Aufruf, `cursor`, nur bearbeitbare Einträge, nie Bibliothekseinträge oder Theme-Builder-Layouts (E11) | +| `lit/tb-list` | lesen | Vorlagen, Bedingungen (Divis Beschriftungen, Objekte nur als ID), Layouts (`shared_with`), `template_rev`; `detached` = von einem veralteten Theme-Builder-Fenster entfernte Vorlagen; optional Divis Bedingungskatalog; nicht bearbeitbare Vorlagen fehlen, aktive nur als Anzahl | +| `lit/tb-create-template` | schreiben | Vorlage mit Header/Body/Footer-Layouts anlegen (`et_theme_builder_insert_layout`, `et_theme_builder_store_template`, Meta `_et_template`); immer deaktiviert (Antwort F1); je Bereich neu, global (Standardvorlage), leer oder ausgeblendet; alles oder nichts; abgelehnt, solange der Theme Builder einen Entwurf hat | +| `lit/tb-assign` | schreiben | Bedingungen (`_et_use_on`/`_et_exclude_from`, z. B. `singular:post_type:person:all`) setzen – nur Divis eigene, Objekte lesbar, Autoren nur mit `list_users`; aktive Vorlage nur nach Probelauf und `confirm`; `reattach` für vom Theme Builder entfernte Vorlagen (bleiben deaktiviert) | +| `lit/tb-activate` | schreiben | Vorlage aktivieren/deaktivieren – einzige Stelle, die eine Vorlage sichtbar macht; immer Probelauf, dann `confirm` (Antwort F1, Etappe 3b); Deaktivieren geht immer, auch bei Theme-Builder-Entwurf (mit Warnung) und im Papierkorb | ## 6. WordPress-Basis @@ -403,6 +404,7 @@ Dynamisch pro Seite erzeugt (Server-Beschreibung → `instructions`), ca. 15 Zei - Kernregeln: vor dem Schreiben `lit/divi-outline` und `lit/divi-design-system` lesen; Variablen/Presets vor festen Werten; native Module vor Code-Modul; Status nie ändern ohne ausdrücklichen Wunsch; immer `rev` (bei Divi-Änderungen `tree_rev`) mitgeben, - Verweis auf `lit/guide`. - Etappe 3a: Zeile „Divi-Bibliothek: …“ (globale Module im Bibliothekseintrag ändern, Probelauf und `confirm: true`, Guide `divi-library`), nur wenn die Gruppe „Divi-Bibliothek“ aktiv und beschreibbar ist. +- Etappe 3b: Zeile „Divi Theme Builder: …“ (neue Vorlagen deaktiviert, Aktivieren nur mit `lit/tb-activate`, Guide `theme-builder`), nur bei aktiver, beschreibbarer Gruppe „Divi Theme Builder“. ### 9.2 `lit/guide(topic)` @@ -412,7 +414,7 @@ Themen: `overview`, `divi-structure`, `divi-shortform`, `divi-attrs`, `divi-plac ### 9.3 MCP-Prompts `corporate-design-uebernehmen`, `neue-website-aufsetzen`, `seite-pruefen`, `globale-module-vorschlagen`, `custom-post-type-vorlage`. -(Stand Etappe 3a: noch keine MCP-Prompts im Plugin; `globale-module-vorschlagen` steht als Ablauf im Guide `divi-library`.) +(Stand Etappe 3b: noch keine MCP-Prompts im Plugin; `globale-module-vorschlagen` steht als Ablauf im Guide `divi-library`, `custom-post-type-vorlage` im Guide `theme-builder`.) ## 10. Sicherheit @@ -466,7 +468,7 @@ Referenz: https://modelcontextprotocol.io/specification | **0 – Anbindung testen** | Plugin-Gerüst, Composer, mcp-oauth + Adapter, Rollen-Gate, App-Password-Scope-Filter, eigener Server mit direkten Tools, `lit/guide` (overview), ein Test-Tool; claude.ai-Connector über `ddev share`/Staging; MCP Inspector; Test: The Events Calendar-Eintrag generisch anlegen | Entscheidung: mcp-oauth bleibt oder Wechsel zu mcp-connect; Events-Erweiterungspunkt nötig ja/nein | | **1 – WordPress-Basis** | Schema-Erkennung inkl. Pods, Content-Tools, Status/Kopie/Austausch, Revisionen, Medien, Menüs, WP-Einstellungen, `ToolResult`, Protokoll, Einstellungsseite | Seiten/Beiträge/Pods-Einträge pflegen, Medien verwalten, Websites mit Struktur und Menü aufsetzen | | **2 – Divi-Seiten** | BlockTree, Katalog, Kurz-/Vollform, Platzhalter, Outline/Insert/Update/Move/Delete/Duplicate/Replace, Warnungen, `page-render-summary`, Divi-Guides (umgesetzt in 2a: lesen, 2b: schreiben) | Divi-Seiten mit dem KI-Assistenten bauen und pflegen | -| **3 – Library & Theme Builder** | Library-Tools, Node-Copy, Make-Global, Find-Similar, Theme-Builder-Tools, Dynamic Content | CPT-Vorlagen bauen, globale Module einführen | +| **3 – Library & Theme Builder** | Library-Tools, Node-Copy, Make-Global, Find-Similar, Theme-Builder-Tools, Dynamic Content | CPT-Vorlagen bauen, globale Module einführen (3a Bibliothek, 3b Theme Builder und Konsolidierung) | | **4 – Designsystem** | Farben, Variablen, Presets, Theme-Optionen inkl. SEO, Snapshots, Prompts | Corporate Design in einem Rutsch übernehmen | | **U – Auslieferung & Updates** (nach Etappe 1) | **OFFEN – bewusst noch nicht spezifiziert.** Bekannt: Build mit `composer install --no-dev` (~3,3 MB vendor), Updates nur anzeigen (manueller Klick), `plugin-update-checker`; Hosting (Gitea / GitHub / eigene Subdomain mit `update.json`) und Signaturprüfung werden später entschieden | – | @@ -491,6 +493,8 @@ Kann-Kriterien nach Etappe 4 oder bei freier Kapazität. | `.well-known`/POST auf `/wp-json/` durch Hoster/WAF blockiert | Site-Health-Test, Fehlersuche-Doku | | Design-Qualität neuer Abschnitte ohne Vorlagen | Library-first-Arbeitsweise, Designsystem-Platzhalter, Guides, Warnungen | | Parallele Bearbeitung im Builder | `tree_rev`-Sperre | +| Veraltetes Theme-Builder-Fenster speichert und entfernt neue Vorlagen | Ablehnung bei Theme-Builder-Entwurf, `detached` in `lit/tb-list`, `reattach` (deaktiviert); Warnung in jeder Anlege-Antwort (Etappe 3b) | +| Ungewöhnliche Schreibweisen globaler Verweise (P25), z. B. ein maskierter `divi/global-layout`-Block in einem Modulwert, den Divi in Shortcode-Modulen und WooCommerce-Textmodulen erneut auswertet | bekanntes Restrisiko, dokumentiert im Guide `divi-library`; braucht Bearbeitungsrechte auf der verweisenden Seite; `UsageMatcher` erkennt die übrigen Schreibweisen fail-closed | | Datenformate Designsystem nur aus Code abgeleitet (lokal keine Daten) | vor Etappe 4 echte Daten im Builder anlegen und als Fixtures sichern | ## 15. Offene Punkte (in Etappen zu klären) diff --git a/readme.txt b/readme.txt index b239810..de0129e 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: mcp, ai, divi, pods, oauth Requires at least: 6.9 Tested up to: 7.1 Requires PHP: 8.1 -Stable tag: 0.4.0 +Stable tag: 0.5.0 License: GPL-2.0-or-later License URI: https://www.gnu.org/licenses/gpl-2.0.html @@ -14,8 +14,9 @@ MCP-Server für WordPress, Divi 5 und Pods – mit OAuth für KI-Assistenten. WP-LIT-MCP stellt einen MCP-Server bereit, über den ein KI-Assistent (ein MCP-fähiger Client mit OAuth) diese Website pflegt: Inhalte aller Inhaltstypen inkl. Pods-Feldern, Status, Kopien, Revisionen, Menüs, freigegebene -WordPress-Einstellungen, die Mediathek sowie Divi-Seiten und die Divi-Bibliothek (auch globale Module). Jede Änderung läuft mit den Rechten des verbundenen -WordPress-Benutzers und wird protokolliert. +WordPress-Einstellungen, die Mediathek sowie Divi-Seiten, die Divi-Bibliothek (auch globale Module) und den +Divi Theme Builder. Jede Änderung läuft mit den Rechten des verbundenen WordPress-Benutzers und wird +protokolliert. Einstellungen: Einstellungen → LIT MCP (Verbindung, Zugriff, Tools, Protokoll, Limits). @@ -75,8 +76,23 @@ Einstellungen: Einstellungen → LIT MCP (Verbindung, Zugriff, Tools, Protokoll, privaten oder geplanten Eintrag, der das Modul zeigt, nicht bearbeiten darf. * Divis Rollen-Editor gilt zusätzlich zu den WordPress-Rechten: ohne „Divi-Bibliothek“, „In der Bibliothek speichern“, „Aus der Bibliothek hinzufügen“ bzw. „Globale Bibliothekselemente bearbeiten“ lehnt LIT MCP ab. +* Divi Theme Builder: neue Vorlagen legt LIT MCP deaktiviert an (über Divis eigene Funktionen, mit Layouts für + Kopfzeile, Inhalt und Fußzeile); sichtbar werden sie nur über lit/tb-activate nach Probelauf und confirm. + Änderungen an Bedingungen aktiver Vorlagen und an Layouts, die Besucher sehen, verlangen ebenfalls Probelauf + und confirm (Layouts vorher mit Revision bzw. Sicherungskopie). Deaktivieren geht immer. Der Theme Builder + verlangt „Beiträge anderer bearbeiten“, „Design bearbeiten“ (edit_theme_options) und das Divi-Recht + „Theme Builder“; Vorlagen, die der Benutzer nicht bearbeiten darf, nennt LIT MCP nicht (aktive nur als + Anzahl). Solange der Theme Builder ungespeicherte Änderungen hat, ändert LIT MCP keine Vorlagen (außer + Deaktivieren). Speichert ein Theme-Builder-Fenster, das vor dem Anlegen geöffnet wurde, entfernt Divi die neue + Vorlage wieder; lit/tb-list zeigt sie dann unter detached. +* lit/library-make-global legt globale Einträge an und ersetzt inhaltsgleiche Vorkommen auf Seiten und + Beiträgen erst nach Probelauf und confirm, jede Seite mit eigener Revision; Theme-Builder-Layouts und + Bibliothekseinträge ändert es nicht. +* Ohne Zugang zur Divi-Bibliothek (Recht „Divi-Bibliothek“ oder Tools-Gruppe deaktiviert) nennt LIT MCP keine + Bibliotheks-IDs, auch nicht bei globalen Modulen auf Seiten. * Interne Links über {{link:}} nutzen Divis eigenen dynamischen Inhalt „ Link“: die Adresse wird beim Anzeigen ermittelt. Für Entwürfe und private Ziele zeigt Divi Besuchern nur ?page_id= (ohne Titel). + Dieselben Zielregeln gelten für die Vollform post_link_url_; Bibliothekseinträge sind kein Linkziel. * lit-site-status prüft, ob die von LIT MCP genutzten Divi-Funktionen vorhanden sind, und nennt nach einem Divi-Update fehlende unter problems. * Pods-Felder: Die Feldrechte von Pods gelten auch über LIT MCP. „Verborgen“ und für den Benutzer gesperrte @@ -109,7 +125,11 @@ Es gibt keine allgemeine "Rückgängig"-Funktion; was sich wie zurücksetzen lä lit/revision-restore. Beim seitenübergreifenden Ersetzen erhält jede geänderte Seite eine eigene Revision. * Bibliothekseinträge: jede Änderung legt vorher eine Revision an (revision_id), bei abgeschalteten Revisionen eine Sicherungskopie im Papierkorb (backup_id); zurück über WordPress (Eintrag der Divi-Bibliothek - bearbeiten → Revisionen). Neu angelegte Einträge (lit/library-save) in der Divi-Bibliothek löschen. + bearbeiten → Revisionen). Neu angelegte Einträge (lit/library-save, lit/library-make-global) in der + Divi-Bibliothek löschen; durch Instanzen ersetzte Knoten über die Revision der jeweiligen Seite zurückholen. +* Theme Builder: Vorlagen haben keine Revisionen. lit/tb-assign nennt die bisherigen Bedingungen (previous) und + schreibt sie ins Protokoll; lit/tb-activate schaltet zurück. Layouts erhalten wie Divi-Seiten eine Revision. + Neu angelegte Vorlagen und Layouts im Divi Theme Builder löschen. * Original durch eine Kopie ersetzen (lit/post-replace-with-copy): vorher legt das Werkzeug eine Revision und eine vollständige Sicherung des bisherigen Originals im Papierkorb an (backup_id in der Antwort) – von dort in WordPress wiederherstellbar. @@ -169,6 +189,22 @@ Bibliothekseintrags. == Changelog == += 0.5.0 = +* Divi Theme Builder: Vorlagen, Bedingungen und Layouts auflisten (lit/tb-list), Vorlagen mit Kopfzeile, + Inhalt und Fußzeile anlegen – immer deaktiviert (lit/tb-create-template) –, Bedingungen setzen + (lit/tb-assign, auch vom Theme Builder entfernte Vorlagen wieder zuordnen), ausdrücklich aktivieren oder + deaktivieren (lit/tb-activate). +* Die Divi-Werkzeuge bearbeiten Theme-Builder-Layouts; sichtbare Layouts erst nach Probelauf und confirm. + Felder im Inhalt-Layout ({{field:…}} und im Divi-Builder gewählte Felder) werden gegen den Inhaltstyp der + Vorlage geprüft (nur Warnungen). +* Ähnliche Abschnitte finden (lit/library-find-similar); Knoten in globale Module umwandeln und + inhaltsgleiche Vorkommen ersetzen (lit/library-make-global); Divi-Änderungen weisen auf gleich aufgebaute + Abschnitte der Bibliothek hin. +* Tools-Gruppe „Divi Theme Builder“; lit-site-status prüft die genutzten Theme-Builder-Funktionen. +* Sicherheit: Bibliotheks-IDs bleiben ohne Bibliothekszugang verborgen; interne Links in der Vollform + (post_link_url_*) folgen denselben Zielregeln wie {{link:ID}}; globale Einträge enthalten keine Verweise auf + andere Einträge, in keiner Schreibweise. + = 0.4.0 = * Divi-Bibliothek: Einträge auflisten und lesen (lit/library-list), Knoten als normalen oder globalen Eintrag speichern (lit/library-save), als Kopie oder globale Instanz einfügen (lit-library-insert, direkt). diff --git a/src/Guides/InstructionsBuilder.php b/src/Guides/InstructionsBuilder.php index f90d223..60ef8fe 100644 --- a/src/Guides/InstructionsBuilder.php +++ b/src/Guides/InstructionsBuilder.php @@ -19,6 +19,9 @@ final class InstructionsBuilder /** Tool group of the Divi Library (LibraryAccess::GROUP); its rule needs a writable group. */ private const LIBRARY_GROUP = 'divi-library'; + /** Tool group of the Divi Theme Builder (ThemeBuilderAccess::GROUP); its rule needs a writable group. */ + private const THEME_BUILDER_GROUP = 'divi-theme-builder'; + /** @var (callable(): list)|null */ private $postTypeNames; @@ -75,6 +78,15 @@ final class InstructionsBuilder ] : []; + $themeBuilder = str_contains(', ' . $active . ',', ', ' . self::THEME_BUILDER_GROUP . ',') + && $this->policy->groupWritable(self::THEME_BUILDER_GROUP) + ? [ + '- Divi Theme Builder: neue Vorlagen entstehen deaktiviert; aktivieren nur auf ausdrücklichen ' + . 'Wunsch mit lit/tb-activate (Probelauf, dann confirm: true); ' + . 'Ablauf: lit-guide topic "theme-builder".', + ] + : []; + return implode("\n", array_merge($lines, [ 'Regeln:', '- Vor dem ersten Arbeitsschritt lit-guide (ohne Topic) aufrufen; Details je Thema über lit-guide ' @@ -86,6 +98,6 @@ final class InstructionsBuilder '- Beim Bearbeiten immer den rev-Wert aus dem letzten Lesevorgang mitgeben (Pflicht).', '- Löschen und Ersetzen erst nach Rückfrage beim Nutzer (confirm: true).', '- Fehler enthalten einen hint – ihm folgen, statt blind zu wiederholen.', - ], $divi, $library)); + ], $divi, $library, $themeBuilder)); } } diff --git a/src/Integrations/Divi/Pages/DiviSchema.php b/src/Integrations/Divi/Pages/DiviSchema.php index bf6f97c..48f169c 100644 --- a/src/Integrations/Divi/Pages/DiviSchema.php +++ b/src/Integrations/Divi/Pages/DiviSchema.php @@ -20,8 +20,9 @@ final class DiviSchema ], 'confirm' => [ 'type' => 'boolean', - 'description' => 'Bei globalen Bibliothekseinträgen (und beim Löschen): true erst, nachdem der Nutzer ' - . 'den Probelauf (confirm_required mit den betroffenen Seiten) bestätigt hat.', + 'description' => 'Bei globalen Bibliothekseinträgen, bei Theme-Builder-Layouts aktiver Vorlagen (und ' + . 'beim Löschen): true erst, nachdem der Nutzer den Probelauf (confirm_required mit den ' + . 'betroffenen Seiten bzw. Vorlagen) bestätigt hat.', ], ]; } diff --git a/src/Plugin.php b/src/Plugin.php index 54fd99b..4c08b39 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -45,7 +45,7 @@ defined('ABSPATH') || exit; */ final class Plugin { - public const VERSION = '0.4.0'; + public const VERSION = '0.5.0'; private static string $pluginFile = ''; private static ?SettingsPage $settingsPage = null; diff --git a/tests/Unit/Guides/InstructionsBuilderTest.php b/tests/Unit/Guides/InstructionsBuilderTest.php index 723b0a4..e907967 100644 --- a/tests/Unit/Guides/InstructionsBuilderTest.php +++ b/tests/Unit/Guides/InstructionsBuilderTest.php @@ -104,6 +104,58 @@ final class InstructionsBuilderTest extends TestCase } } + private function themeBuilder(): Integration + { + $group = Mockery::mock(Integration::class); + $group->allows('id')->andReturn('divi-theme-builder'); + $group->allows('isAvailable')->andReturn(true); + $activate = $this->ability('lit/tb-activate', false); + $activate->allows('annotations')->andReturn(['readonly' => false]); + $group->allows('abilities')->andReturn([$activate]); + + return $group; + } + + public function testAddsTheThemeBuilderRuleOnlyWhenItsGroupCanWrite(): void + { + $core = $this->coreWith($this->ability('lit/guide', true)); + $registry = new IntegrationRegistry($core, $this->themeBuilder()); + + $with = (new InstructionsBuilder($registry))->build(); + $without = (new InstructionsBuilder(new IntegrationRegistry($core)))->build(); + + self::assertStringContainsString('Divi Theme Builder: neue Vorlagen entstehen deaktiviert', $with); + self::assertStringContainsString('lit/tb-activate', $with); + self::assertStringContainsString('confirm: true', $with); + self::assertStringContainsString('topic "theme-builder"', $with); + self::assertStringNotContainsString('Divi Theme Builder:', $without); + self::assertLessThan(2000, strlen($with)); + + foreach ([['@readonly:divi-theme-builder' => true], ['@group:divi-theme-builder' => 'disabled']] as $settings) { + $policy = (new ExposurePolicy($settings))->withGroups($registry->groupMap()); + + $text = (new InstructionsBuilder($registry, null, $policy))->build(); + + self::assertStringNotContainsString('Divi Theme Builder:', $text, (string) json_encode($settings)); + } + } + + public function testAllRulesTogetherStayShort(): void + { + $divi = Mockery::mock(Integration::class); + $divi->allows('id')->andReturn('divi'); + $divi->allows('isAvailable')->andReturn(true); + $divi->allows('abilities')->andReturn([$this->ability('lit/divi-outline', true)]); + $core = $this->coreWith($this->ability('lit/guide', true)); + $registry = new IntegrationRegistry($core, $divi, $this->library(), $this->themeBuilder()); + + $text = (new InstructionsBuilder($registry, static fn (): array => ['page', 'post']))->build(); + + self::assertStringContainsString('Divi-Bibliothek:', $text); + self::assertStringContainsString('Divi Theme Builder:', $text); + self::assertLessThan(2000, strlen($text)); + } + public function testListsPostTypesWhenAProviderIsGiven(): void { $core = $this->coreWith($this->ability('lit/guide', true)); diff --git a/tests/Unit/Integrations/Divi/Pages/DiviSchemaTest.php b/tests/Unit/Integrations/Divi/Pages/DiviSchemaTest.php new file mode 100644 index 0000000..036acca --- /dev/null +++ b/tests/Unit/Integrations/Divi/Pages/DiviSchemaTest.php @@ -0,0 +1,22 @@ +