Der eigene Divi-Reiter entfällt. DiviAdminExtras behält Admin-Hinweis, Orphan-Bereinigung vor der Ausgabe (lit_mcp_compat_profile_load), Hinweis zum nächsten Schritt und zur privaten Testseite (lit_mcp_compat_profile_intro), Zustandstexte mit Quelle (lit_mcp_compat_explanation), Automatik-Notiz und Visual-Builder-Hinweis (lit_mcp_compat_profile_extra) sowie die Spalten Quelle, Probleme und Betroffene Tools über die neue, gegen fehlerhafte Callbacks abgesicherte Erweiterung lit_mcp_compat_capability_columns. Texte, Doku, CSS (lit-mcp-compat-*) und Smoke auf den neuen Reiter umgestellt, tote divi_*-Hinweise entfernt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Die generische CheckRoute (POST lit-mcp/v1/<id>-check, für Divi weiter /divi-check) ersetzt DiviCheckRoute: Lock je Profil mit Besitzer-Token, Bericht je Profil, Rücksprung auf den neuen Reiter und Hook lit_mcp_compat_changed (Divi lädt darauf seinen Freigabe-Status neu). Der Reiter „Compatibility“ zeigt je Plugin Zustand (Wort und Icon), Hinweis zur Stufe, Fähigkeiten, getestete und freigegebene Versionen und den letzten Bericht, mit Prüfen, Freigeben und Zurückziehen (Recht manage_options, Allowlist der Profil-ID, Nonce je Profil). Freigeben serverseitig nur mit frischem grünem Bericht. Der Load-Hook lit_mcp_compat_profile_load bereitet den Abbau des DiviTab vor, der bis dahin parallel läuft.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neu: Tier, Profile, Compatibility, CapabilityLocked, CapabilityGate, CompatibilityComponent, ProvidesCompatibility, DiviProfile sowie PodsFeature, PodsCompatibility und PodsIntegration. Das CapabilityGate sperrt gesperrte und unbekannte Fähigkeits-IDs (übernimmt die Sperre unbekannter IDs vom DiviFeatureGate) und delegiert nur Divi ausdrücklich. Pods-Schema, -Lesen, -Schreiben und -Feldrechte laufen über usable(PodsFeature::…); Schreiben verlangt FieldRead und FieldWrite, damit ein Rollback keine Werte verliert. lit-site-status meldet Pods über die CompatibilityComponent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WordPress „Zusätzliches CSS“ (in Divi „Eigenes CSS“) über die Design-Pipeline: Probelauf mit Zeilen-Diff,
design_rev, Bestätigung, Snapshot, Rollback und Wiederherstellen (Bereich custom_css). Der Guard lehnt </style,
<script, expression(, javascript: und neue @import ab und warnt bei fremden Hosts; nur Neues zählt, Bestehendes
blockiert keine Änderung. Erfordert edit_css und die Divi-Rolle Theme-Anpassung.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
GlobalUsages gets the Theme Builder access injected as a closure
(ThemeBuilderAccess::usageState(), wired at both construction sites through
DiviIntegration::globalUsages()). Theme Builder posts are named only while
the Theme Builder is visible to the account, otherwise only counted (also
in blocked_ids); a global edit that changes them needs canUse(), a writable
"Divi Theme Builder" group and edit_post. Without an injected access the
fail-safe default checks what canUse() checks. The duplicate
THEME_BUILDER_TYPES list gives way to DiviThemeBuilder::postTypes().
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
- NewLibraryEntry: spec and creation of a new library entry, shared by
lit/library-save and lit/library-make-global (NewDraft, P7, StoredNodeGuard)
- UsageMatcher::referencesAny() (ruling Q7): a global entry never names any
entry in any spelling Divi renders (P23/P24 forms, Divi 4 shortcodes inside
Divi 5 values, values casting to 0); used by library-save scope global and
make-global
- make-global: entry created, node replaced by GlobalInstance::of, page through
DiviWriter::commit; refused or rolled-back page deletes the entry, a partial
page write keeps it (the page may show it); sources are pages and posts only
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
Fingerprint::structure()/content() (E11) and lit/library-find-similar
(indirect, group Divi-Bibliothek): at most 200 posts per call (cursor),
editable entries only (own posts without edit_others_posts), contents
primed in chunks of 50, stops at 200 matches or 5000 compared nodes with
a note; library entries and Theme Builder layouts are never scanned.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- only _et_enabled; dry run in both directions lists conditions, exclusions,
layouts, overlaps and possible overlaps (B9); confirm: true switches
- enabling needs conditions and published layouts (B10); a detached
template needs reattach first; the default template is refused
- the off-switch reaches an attached, enabled template outside publish,
e.g. in the trash (ruling Q16); result names the fast way back
- every switch in the change log; failed switch rolled back
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- ThemeBuilderAccess::changeableTemplate(): rights (Q18 not_found), group gate,
no TB draft, never the default template, current template_rev
- omitted exclude_from stays, [] clears (Q3); live dry run shows use_on and
exclude_from before/after, overlaps and possible overlaps (B9)
- reattach only with published layouts (B10) and a live TB post; always
disabled, unmarks template and layouts; failure restores everything
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Outline, node-get, write outlines, the render summary and replace-text's
opaque-node match name no library ID unless the library group is visible
and the user has divi_library; read-only still names them.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Reuses NewDraft for insert and rollback (P6), requires edit_global_library
for scope global (P7), refuses opaque and global roots before wrapping (P11)
and checks the node with StoredNodeGuard. The source page is never written.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- tests/Support/FakeChangeLog extends ChangeLog: records record()/recordPartial()
calls, increasing ids, optional failure; new FakeChangeLog(id) / partialsOnly() /
any(id) / forbidden() mirror what the replaced mocks allowed. assertRecorded() /
assertPartials() check count and the named arguments. Calls a fake does not allow
throw and are also verified in TestCase::tearDown (one assertion per test that
uses a fake), so swallowed change-log calls still fail like a never() expectation.
- All ChangeLog mocks of ability/integration tests replaced (the admin tests that
stub query/purge/clear keep their mocks); expectException tests that checked the
partial log now catch and assert.
- SchemaFixture::managed(?divi) replaces the 21 isManaged-only ContentSchema mocks;
DiviFixtures::schema() uses it.
Tests 1397 -> 1404 (FakeChangeLogTest); no test has fewer assertions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
New input divi (1-30 sections, short form like lit-divi-insert) builds a Divi 5
layout in one divi/placeholder. The whole description is checked before the
insert (Divi's map for "no entry yet"); the draft is inserted with its normal
WordPress fields only, then DiviContentComposer composes again bound to the new
entry and stores it via DiviSaver::saveNew (same kses window as save(), strict
DiviFlags). A refusal or failure deletes the draft. Result adds tree_rev and the
outline.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TextReplacer replaces only in plain-text segments (S8 split), outside
script/style bodies, inserts the replacement cleaned per field kind and
refuses any result whose tags, entities or references differ from the
original plus the inserted text. Unchanged strings are never cleaned.
Per page all or nothing with the tree_rev lock; Throwables are reported
per page (S10).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
Adds per-path attribute kind (text/richtext/code/url/image/color/enum/
onoff/number/list/icon), derived from Divi's field component metadata
where an attribute path names one unambiguously (module.paths() itself
is unchanged; kinds() is a new, separate lookup exposed as path_kinds
on lit/divi-catalog's module detail). This is not in the task-4 brief;
it is added because 2b's sanitization routing (ruling R3) needs a
metadata-derived field kind per attribute path. Verified live against
the full 100-module catalog (564/4358 paths resolve a kind; the rest
default to "unknown" and fall back to 2b's key-name routing).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7