Files
WP-LIT-MCP/docs/superpowers/plans/2026-11-06-kompatibilitaetsschicht.md
T
Jan-Niclas LoosenandClaude Opus 5.5 7d6a97a54e refactor(compat): Freigabe-Bausteine generisch
ReleaseStore, CheckReportStore, CheckReport, CheckStep und CompatibilityCheck liegen im Kern und arbeiten je Profil (Optionen lit_mcp_<id>_releases|_check_report; Divi behält Namen und Schlüssel divi_version). Divi hängt Katalog-, Format- und Schreibtest über Profile::extraSteps an. Ein roter Prüfbericht für den aktuellen Stand sperrt LockOnFailure-Profile bis zur nächsten grünen Prüfung; Sperrgründe nennen nur Schritt-Labels, Ausnahmen gehen ins Error-Log. Profile bekommt testedVersions, stateKey, extraSteps, manifestCheck und reportVersionKey und wird mit benannten Argumenten gebaut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:51:03 +01:00

13 KiB
Raw Blame History

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/ (Namespace LIT\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 vorhandene DeclaresRequirements.
  • Tier: ReportOnly (nie sperren), LockOnFailure (hartes Problem sperrt, sonst frei; signatures:false), ReleasePerVersion (nur Divi; Matrix kommt per Closure aus ReleaseGate::status()->matrix). ReleaseStore, Resolver-Workflow, WriteProbe, CLI, FeatureSets bleiben Divi-eigen.
  • Gates: CapabilityGate überspringt IDs von ReleasePerVersion-Profilen, prüft IDs anderer Profile über Compatibility::lockOf und sperrt IDs, die kein Profil kennt. DiviFeatureGate ignoriert Nicht-Divi-IDs wieder. Umstellung atomar in 1.13.
  • Pods-IDs mit Präfix pods-, WPSC mit wpsc-; Divi-IDs bleiben unpräfixiert. Eindeutigkeitstest über alle Profile.
  • Pods und WPSC werden Integrationen ohne Abilities, die ProvidesCompatibility implementieren; 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 Slug divi, DiviTab wird nicht umbenannt.
  • WPSC: Hook lit_mcp_changed in ChangeLog::record (nur result = ok, eigenes try/catch); Listener nutzt wp_cache_post_edit bzw. wp_cache_clear_cache(blog); kein lit/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
Erledigt 1.1–1.14: 9beb55e, b511ef6, c851316.

Neu-Zuschnitt 1.15–1.25 (Gate 1 vom 2026-11-06): Prüfen und Freigeben sind für alle Profile im Reiter „Compatibility“ gleich; die Wirkung regelt das Tier (ReleasePerVersion = Pflicht, LockOnFailure = dokumentiert, Nutzung automatisch solange grün, ReportOnly = nur Status). Optionen lit_mcp_<id>_releases|_check_report|_check_lock – für divi exakt die heutigen Namen. Divi behält auch das Datenformat: Store und Bericht bekommen den Versionsschlüssel als Parameter (Divi divi_version, neue Profile version) – keine Migration, Rollback-sicher. Profil-ID aus POST nur nach Allowlist (Compatibility::profile()) in Optionsnamen.

| 1.15 | Profile: testedVersions, stateKey, extraSteps (Closure(bool $manifestClean): list), manifestCheck; DiviProfile + active, testedVersions=DiviReleases::TESTED, stateKey=ReleaseResolver::stateKey; Pods testedVersions=['3.3.9.2'] | ProfileTest, DiviProfileTest, PodsCompatibilityTest | Gates grün | sonnet (mit 1.16–1.18) | | 1.16 | CheckStep, CheckReport, CheckReportStore(profileId, versionKey) nach src/Compatibility; Label mitgespeichert; Divi-Schrittkonstanten in DiviCheckSteps | CheckReportTest (Divi-Rundlauf unverändert, Option je ID) | Divi-Suite grün | sonnet | | 1.17 | ReleaseStore(profileId, versionKey) nach src/Compatibility | ReleaseStoreTest (Divi-Format unverändert, Option je ID) | ReleaseResolverTest grün | sonnet | | 1.18 | CompatibilityCheck generisch (Manifest, Fingerabdrücke nur mit Mirrors, dann extraSteps); Compatibility::check(Profile); Divi liefert Katalog/Format/Schreibtest als extraSteps | CompatibilityCheckTest, DiviCheckStepsTest | DiviCheckCommandTest grün, Divi-Schrittfolge gleich | sonnet | | 1.18a | Review-Befunde (Architektur-Review 2026-11-06): roter gespeicherter Bericht für den aktuellen Stand sperrt LockOnFailure-Fähigkeiten bis zur nächsten grünen Prüfung; gefangene Ausnahmen in Compatibility per Log::failure protokollieren; Profile nur mit benannten Argumenten bauen | CompatibilityTest (roter/grüner/veralteter/kein Bericht) | Divi unverändert | sonnet | | 1.19 | Admin\CheckRoute je Profil (/<id>-check, Lock je Profil, Redirect tab=compatibility, do_action('lit_mcp_compat_changed', $id); Divi invalidiert darauf ReleaseGate) | CheckRouteTest, DiviIntegrationTest | Lock-Tests portiert | sonnet | | 1.20 | Admin\CompatibilityTab read-only (Sektion je Profil, Zustand Wort+Icon, Tier-Hinweis, Fähigkeiten, Versionen, Bericht, Hook lit_mcp_compat_profile_extra; inaktiv ohne matrix()) | CompatibilityTabTest inkl. Escaping | CoreIndependenceTest grün | sonnet | | 1.21 | Formulare + admin-post lit_mcp_compat_release|withdraw (guard, Allowlist, Nonce je Profil) | CompatibilityTabTest (frischer Bericht, unbekanntes Profil, Nonce/403, Tier-Sichtbarkeit) | Release/Withdraw-Fälle aus DiviTabTest portiert | sonnet | | 1.22 | Reiter in Plugin::boot (nach LimitsTab), Hilfe-Tab | PluginTest, SettingsPageTest | grün | sonnet | | 1.23 | DiviTab → DiviAdminExtras (Notice, Orphans, Zusatzhinweise); TABS_FILTER-Eintrag entfällt | DiviAdminExtrasTest, DiviIntegrationTest | Boundary/Core grün | sonnet | | 1.24 | Texte/CSS (lit-mcp-divi-* → lit-mcp-compat-*), ReleaseStatus:24, docs/guides/overview.md, Uninstaller (lit_mcp_pods_*), divi-release-smoke.sh | ReleaseStatusTest, UninstallerTest | DDEV Divi-Smoke grün | sonnet | | 1.25 | Pods-Smoke: /pods-check, Freigabe schreibt lit_mcp_pods_releases ohne Sperrwirkung, hohe minVersion sperrt | Smoke rot ohne 1.19–1.21 | DDEV Pods- und Divi-Smoke grün | 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) · 11a refactor(compat): Freigabe-Bausteine generisch (1.15–1.18) · 11b feat(compat): Prüfroute je Profil (1.19) · 11c feat(admin): Reiter „Compatibility“ für alle Profile (1.20–1.22) · 11d refactor(divi): DiviTab geht im Reiter auf (1.23–1.24) · 11e test(compat): Smokes (1.25) · 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).