Grundlage der generischen Kompatibilitätsschicht für Fremd-Plugins mit inoffiziellen Schnittstellen (Plan docs/superpowers/plans/2026-11-06-kompatibilitaetsschicht.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
10 KiB
Kompatibilitätsschicht für Fremd-Plugins (Phase 0–2)
Stand 2026-11-06, Branch feat/compatibility-layer. Gate 1: voller Architektur-Entwurf (Benutzerentscheidung), weil Pods künftig
komplett über den Kern laufen soll und WP Super Cache direkt folgt.
Regeln für jeden Task: zuerst ein fehlschlagender Test, dann die kleinste Änderung; nach jedem Task composer test grün und
composer lint ohne neue Befunde (zwei Warnungen bestehen schon: wp-lit-mcp.php:6, RegisteredMetaSourceTest.php:78).
DiviBoundaryTest und CoreIndependenceTest laufen immer mit. Ein roter Divi-Test heißt anhalten. Verschiebe-Tasks sind
mechanisch (Namespace + use), keine Verhaltensänderung. Keine Commits durch Umsetzungs-Agents (Gate 2 je Commit-Block).
Entscheidungen
- Kern
src/Compatibility/(NamespaceLIT\MCP\Compatibility), importiert kein Divi (CoreIndependenceTest). Capability(id(),label(),isWrite());DiviFeature implements Capability,id()=value.- Kein eigenes
RequiresCapabilities: Tools deklarieren Fähigkeits-IDs über das vorhandeneDeclaresRequirements. - Tier:
ReportOnly(nie sperren),LockOnFailure(hartes Problem sperrt, sonst frei;signatures:false),ReleasePerVersion(nur Divi; Matrix kommt per Closure ausReleaseGate::status()->matrix). ReleaseStore, Resolver-Workflow, WriteProbe, CLI, FeatureSets bleiben Divi-eigen. - Gates:
CapabilityGateüberspringt IDs vonReleasePerVersion-Profilen, prüft IDs anderer Profile überCompatibility::lockOfund sperrt IDs, die kein Profil kennt.DiviFeatureGateignoriert Nicht-Divi-IDs wieder. Umstellung atomar in 1.13. - Pods-IDs mit Präfix
pods-, WPSC mitwpsc-; Divi-IDs bleiben unpräfixiert. Eindeutigkeitstest über alle Profile. - Pods und WPSC werden
Integrationen ohne Abilities, dieProvidesCompatibilityimplementieren; leere Gruppen dürfen weder im Tools-Tab noch in den Server-Anweisungen erscheinen. - Admin: ein gemeinsamer Reiter „Compatibility“ (Slug
compatibility); Divi-Freigabe wird Sektion darin (lit_mcp_compat_sections). Kein Redirect vom alten Slugdivi,DiviTabwird nicht umbenannt. - WPSC: Hook
lit_mcp_changedinChangeLog::record(nurresult = ok, eigenes try/catch); Listener nutztwp_cache_post_editbzw.wp_cache_clear_cache(blog); keinlit/cache-clear.
Phase 0 – Sicherheitsfixes (erledigt: 8f3a4e7, 234fd1e, 691231f)
Phase 1 – Kern, Pods, Reiter
| # | Ziel und Dateien | Zuerst rot | Akzeptanz | Modell |
|---|---|---|---|---|
| 1.1 | src/Compatibility/Capability.php; DiviFeature implements Capability + id() |
DiviFeature::PageRead instanceof Capability, id()==='page-read' |
Divi-Tests grün | haiku |
| 1.2 | ReleaseState, SourceFingerprint, LineDiff nach src/Compatibility; 'Compatibility' in CORE_PATHS |
CoreIndependenceTest::testEveryScannedPathExists; verschobene Tests unter neuem Namespace |
kein Integrations\Divi-Import im Kern |
haiku |
| 1.3 | Requirement (features(): list<Capability>), Call (+accepts() aus ManifestCheck::accepts, signatureKey), ConstantRequirement, Mirror, SignatureFingerprint verschieben; ManifestCheck::accepts delegiert |
CallTest am neuen Ort; ManifestCheckTest Regression |
Divi-Suite grün | sonnet |
| 1.4 | Problem, FeatureStatus verschieben (Capability); Problem::fromArray(mixed, Closure(string): ?Capability); ReleaseResolver::cached übergibt DiviFeature::tryFrom(...); Transient-Format bleibt |
ProblemTest unbekannte ID → null; ReleaseResolverTest |
Transient-Rundlauf unverändert | sonnet |
| 1.5 | CompatibilityMatrix generisch (list<Capability>), uniform/allIncompatible mit Capabilities, fromProblems(caps, problems, ?source, automatic) aus ReleaseResolver (~89-129); SOURCE_* auf die Matrix, Aliase in ReleaseStatus; Aufrufer ReleaseGate, ReleaseStatus, ReleaseResolver, DiviCheckCommand, tests/Support |
CompatibilityMatrixTest mit Fake-Capability pods-x; fromProblems gegen bisherigen Resolver-Fall |
ReleaseResolverTest, ReleaseStatusTest unverändert grün |
sonnet |
| 1.6 | DiviAreas (PAGES, LIBRARY, THEME_BUILDER, DESIGN, CATALOG) aus Manifest |
DiviAreasTest; ManifestTest |
reine Umbenennung | haiku |
| 1.7 | Manifest (Capabilities), GlobalRequirement (isset($GLOBALS[name]), hart), ManifestCheck nach src/Compatibility, ohne Divi-Defaults, Option signatures; Divi\Release\DiviManifestCheck::create(); Aufrufer ReleaseResolver, CompatibilityCheck, DiviCompatibility, Tests mit new ManifestCheck() |
ManifestCheckTest mit signatures:false ohne reference-missing; GlobalRequirement fehlt = hartes Problem; DiviManifestCheckTest |
Kern ohne Divi; Divi-Release-Tests unverändert | sonnet |
| 1.8 | Tier, Profile (id, label, tier, capabilities, manifests, ?matrix-Closure, ?version-Closure, ?minVersion, aktiv-Prüfung), Compatibility (matrix memoisiert, lockOf, assert, usable, problems, capability(id), active) |
CompatibilityTest mit Fake-Profilen je Tier, Memoisierung, unbekannte ID → null, minVersion sperrt alles |
rein bis auf defined()/get_file_data |
sonnet |
| 1.9 | CapabilityLocked (RuntimeException implements ToolRefusal, compat_incompatible, 423, details features/problems, Fabrik für unbekannte IDs) |
CapabilityLockedTest |
analog DiviLockedTest |
sonnet |
| 1.10 | CapabilityGate implements AbilityGuard (Vorlage DiviFeatureGate), Log refused nur bei Schreibtools; noch nicht verdrahtet |
CapabilityGateTest: Pods-ID gesperrt/frei, Divi-ID ignoriert, unbekannt gesperrt |
annotate/outputSchema reichen durch | sonnet |
| 1.11 | ProvidesCompatibility, IntegrationRegistry::compatibilities() (auch nicht verfügbare), DiviProfile::profile(), DiviIntegration implements ProvidesCompatibility |
IntegrationRegistryTest, DiviIntegrationTest |
Divi neutral | sonnet |
| 1.12 | PodsFeature (pods-schema-read, pods-field-read, pods-field-write, pods-field-permissions), PodsCompatibility::profile() (LockOnFailure, PODS_VERSION, min 2.8, Calls mit Argumentzahlen gegen Pods 3.3.9.2), PodsIntegration ohne Abilities |
PodsCompatibilityTest; Registry-Test: leere Integration nicht in grouped()/labels()/Instructions |
keine leere Gruppe sichtbar | sonnet |
| 1.13 | CompatibilityComponent (3 Zustände, Zeile je Fähigkeit); EnvironmentProbe ohne Pods (TEC bleibt); Plugin: Guards [DiviFeatureGate, CapabilityGate], Komponenten per Closure aus der Registry; 0.3-Umzug (unknownIds entfällt, Test zieht in CapabilityGateTest); ID-Eindeutigkeit |
EnvironmentProbeTest; Zwei-Gate-Test über AbilityRegistrar::argsFor; PluginTest |
Reihenfolge Divi, Pods, TEC | sonnet |
| 1.14 | PodsFieldSource + Schema-Wahl über usable(PodsFeature::…); isAvailable() entfällt; Feldrechte über usable(FieldPermissions), sonst fail-closed; 0.2-Bedingung = active && ! usable(SchemaRead) |
PodsFieldSourceTest je Fähigkeit; PluginTest |
alle Pods-Tests grün | sonnet |
| 1.15 | CompatibilityTab + CompatibilitySection (Filter lit_mcp_compat_sections, lazy); Zustand (Wort + Icon) und Probleme je Fähigkeit für Nicht-ReleasePerVersion-Profile |
CompatibilityTabTest: drei Zustände, Sektion eingebettet, escaped |
CoreIndependenceTest grün |
sonnet |
| 1.16 | DiviTab implements CompatibilitySection (title() „Divi“); Slug/Redirects/requested()/Notice auf compatibility; DiviIntegration hängt über lit_mcp_compat_sections ein |
DiviTabTest, DiviIntegrationTest |
Release/Withdraw/Orphans/Render unverändert | sonnet |
| 1.17 | Links/Texte: DiviCheckRoute, ReleaseStatus:24, docs/guides/overview.md:96, divi-release-smoke.sh, Docblock DiviCheckCommand |
DiviCheckRouteTest tab=compatibility; ReleaseStatusTest „→ Compatibility“ |
DDEV-Smoke grün | haiku |
| 1.18 | Reiter in Plugin::boot registrieren (nach LogTab); Pods-Smoke erweitern |
PluginTest Tab-Liste |
DDEV: compatibility ok, Pods ohne Probleme; hohe minVersion → Pods-Felder schreibgeschützt |
sonnet |
Phase 2 – WP Super Cache 3.1.5
| # | Ziel und Dateien | Zuerst rot | Akzeptanz | Modell |
|---|---|---|---|---|
| 2.1 | Hook lit_mcp_changed(ability, objectType, objectId, logId) in ChangeLog::record, nur bei ok, auch bei fehlgeschlagenem Insert; werfender Listener → Log::failure |
ChangeLogTest |
bestehende Fälle grün | sonnet |
| 2.2 | SuperCacheFeature (wpsc-purge-post, wpsc-purge-all), SuperCacheCompatibility::profile() (LockOnFailure, WPCACHEHOME, Version per get_file_data, GlobalRequirement('cache_path')), SuperCacheIntegration ohne Abilities |
SuperCacheCompatibilityTest |
Eindeutigkeitstest umfasst wpsc- |
sonnet |
| 2.3 | SuperCacheListener an lit_mcp_changed: nur bei usable() (sonst Log-Zeile) und $GLOBALS['cache_enabled']; öffentlicher Posttyp außer attachment → wp_cache_post_edit($id); sonst wp_cache_clear_cache(is_multisite() ? get_current_blog_id() : 0); eigenes try/catch |
SuperCacheListenerTest mit injizierten Closures |
lint sauber | sonnet |
| 2.4 | Verdrahtung + Absatz in docs/guides/overview.md |
PluginTest |
lit-site-status listet WPSC |
haiku |
| 2.5 | tests/Integration/super-cache-smoke.sh (Feld-Update leert Beitrag, Einstellung leert alles; et_pb_layout öffentlich?) |
Smoke rot ohne 2.3 | DDEV grün | sonnet |
Commit-Schnitt
4 refactor(compat): Capability und DiviFeature (1.1) · 5 refactor(compat): reine Release-Klassen nach src/Compatibility
(1.2–1.4) · 6 refactor(compat): CompatibilityMatrix generisch mit fromProblems (1.5) · 7 refactor(compat): Manifest und ManifestCheck generisch, DiviAreas, DiviManifestCheck (1.6–1.7) · 8 feat(compat): Tier, Profile, Compatibility, CapabilityLocked, CapabilityGate (1.8–1.10) · 9 feat(compat): Profile aus Integrationen, Divi- und Pods-Profil (1.11–1.12) ·
10 feat(compat): Gates, Status und Pods über den Kern verdrahten (1.13–1.14) · 11 feat(admin): Reiter „Compatibility“ mit Divi als Abschnitt (1.15–1.18) · 12 feat(changelog): Hook lit_mcp_changed (2.1) · 13 feat(cache): WP Super Cache über den Kern anbinden (2.2–2.4) · 14 test(cache): Integrations-Smoke (2.5)
Risiken
Vergessene use-Zeilen in Verschiebe-Tasks (voller Testlauf je Task); Lücke bei unbekannten IDs nur, wenn CapabilityGate
fehlt (PluginTest prüft beide Guards); leere Integrationen verändern Registry-Ausgaben (1.12 prüft zuerst); signatures:false
prüft nur Existenz und Argumentzahl; wp_cache_post_edit ist keine dokumentierte API (Wegfall sperrt nur den Purge, sichtbar
im Reiter und in lit-site-status).