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>
This commit is contained in:
Jan-Niclas Loosen
2026-11-06 12:51:03 +01:00
co-authored by Claude Opus 5.5
parent c85131603b
commit 7d6a97a54e
48 changed files with 1469 additions and 647 deletions
@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Release;
use Closure;
use LIT\MCP\Compatibility\CheckStep;
use LIT\MCP\Compatibility\CompatibilityCheck;
defined('ABSPATH') || exit;
/** The check steps only Divi has (module catalog, format round trip, write test) and their labels. */
final class DiviCheckSteps
{
public const CATALOG = 'catalog';
public const FORMAT = 'format';
public const WRITE = 'write';
/** Labels of the Divi-only steps; manifest and mirrors come from CheckStep::genericLabel(). */
private const LABELS = [
self::CATALOG => 'Modulkatalog (Kurzform-Pfade)',
self::FORMAT => 'Format im Speicher (Parser und Serializer)',
self::WRITE => 'Schreibtest auf einer Wegwerfseite',
];
/** @param list<string> $problems */
public static function step(string $key, array $problems, bool $skipped = false): CheckStep
{
return new CheckStep($key, $problems, $skipped, self::LABELS[$key] ?? null);
}
/**
* The Profile::$extraSteps of Divi: module catalog, format round trip and the write test. The write test is
* skipped only when Divi functions are missing (it would fail anyway), not when only fingerprints changed – so
* --update-reference can see whether everything else still works.
*
* @param Closure(): list<string> $catalog Short-form problems against Divi's live catalog.
* @param Closure(): list<string> $probe WriteProbe::run().
* @return Closure(bool): list<CheckStep>
*/
public static function extra(Closure $catalog, FormatCheck $format, Closure $probe): Closure
{
return static fn (bool $manifestClean): array => [
self::step(self::CATALOG, CompatibilityCheck::guarded($catalog)),
self::step(self::FORMAT, CompatibilityCheck::guarded(static fn (): array => $format->problems())),
$manifestClean
? self::step(self::WRITE, CompatibilityCheck::guarded($probe))
: self::step(self::WRITE, [], true),
];
}
public static function label(CheckStep $step): string
{
// Reports saved before labels were stored have none.
return $step->label
?? self::LABELS[$step->key]
?? CheckStep::genericLabel($step->key, DiviProfile::LABEL)
?? $step->key;
}
}