feat: divi-check gibt die Matrix je Fähigkeit aus (Exit 2 bei nicht nutzbarer Fähigkeit); Texte nennen Fähigkeiten statt pauschal gesperrt

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-18 22:29:38 +02:00
co-authored by Claude Sonnet 5.5
parent 2aef6e1154
commit a4faeda326
4 changed files with 204 additions and 45 deletions
+76 -5
View File
@@ -9,6 +9,7 @@ use LIT\MCP\Integrations\Divi\Release\CheckReport;
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
use LIT\MCP\Integrations\Divi\Release\CheckStep;
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
use LIT\MCP\Integrations\Divi\Release\DiviEnvironment;
use LIT\MCP\Integrations\Divi\Release\DiviReference;
@@ -22,7 +23,14 @@ defined('ABSPATH') || exit;
/**
* wp lit-mcp divi-check (spec §7): the admin check from the command line, for a developer checking a new Divi
* version. Never releases anything – a green version goes into DiviReleases::TESTED by hand.
* version. Never releases anything – a green version goes into DiviReleases::TESTED by hand. After the report it
* prints the compatibility matrix (E3).
*
* Exit codes: 0 = report green and every feature usable; 1 = report red (or the check could not run, or
* --update-reference refused); 2 = report green but a feature is not usable. The 2 is for a version that is
* checked but not yet released (not in DiviReleases::TESTED, automatic release off or a reference missing): the
* checks passed, yet LIT MCP would still refuse the affected tools. A script that only cares about "usable" tests
* for ≠ 0. --update-reference keeps its own code: it runs before the new reference is part of any release.
*/
final class DiviCheckCommand
{
@@ -37,6 +45,7 @@ final class DiviCheckCommand
* @param (Closure(): ?string)|null $sourceDir null = DiviReference::sourceDir().
* @param (Closure(): array<string, string>)|null $signatures "sig:<symbol>" => sha256 of every Divi call in the
* running process; null = DiviReference::currentSignatures().
* @param (Closure(): CompatibilityMatrix)|null $matrix null = the release gate's matrix, computed again.
*/
public function __construct(
private Closure $check,
@@ -45,7 +54,8 @@ final class DiviCheckCommand
private ?Closure $themeDir = null,
private ?string $expectedFile = null,
private ?Closure $sourceDir = null,
private ?Closure $signatures = null
private ?Closure $signatures = null,
private ?Closure $matrix = null
) {
$this->out = $out ?? static function (string $line): void {
\WP_CLI::line($line);
@@ -62,7 +72,9 @@ final class DiviCheckCommand
/**
* Prüft die installierte Divi-Version wie der Reiter „Divi“: Manifeste, Fingerabdrücke, Modulkatalog, Format
* und Schreibtest auf einer Wegwerfseite. Gibt nichts frei.
* und Schreibtest auf einer Wegwerfseite. Gibt danach den Zustand je Fähigkeit aus und gibt nichts frei.
* Exit-Code 0: Prüfung grün und alle Fähigkeiten nutzbar; 1: Prüfung rot; 2: Prüfung grün, aber mindestens
* eine Fähigkeit nicht nutzbar (z. B. Version noch nicht in DiviReleases::TESTED).
*
* ## OPTIONS
*
@@ -111,10 +123,69 @@ final class DiviCheckCommand
$this->diff();
}
if (isset($assoc['update-reference'])) {
return $this->updateReference($report);
$code = $this->updateReference($report);
$this->printMatrix();
return $code;
}
return $report->green() ? 0 : 1;
$unusable = $this->printMatrix();
if (! $report->green()) {
return 1;
}
return $unusable > 0 ? 2 : 0;
}
/**
* Prints one line per feature (✓ released, ✗ incompatible, – untested) with label and state, the problems
* indented below.
*
* @return int The number of features that are not usable.
*/
private function printMatrix(): int
{
$matrix = $this->currentMatrix();
($this->out)('Fähigkeiten:');
foreach ($matrix->toArray() as $row) {
($this->out)(sprintf(
'%s %s – %s',
match ($row['state']) {
'released' => '✓',
'incompatible' => '✗',
default => '–',
},
$row['label'],
self::stateLabel($row['state'], $row['source'])
));
foreach ($row['problems'] as $problem) {
($this->out)(' ' . $problem);
}
}
return count($matrix->unusable());
}
/** The check just ran, so the state is computed again instead of read from a cache older than the report. */
private function currentMatrix(): CompatibilityMatrix
{
if ($this->matrix !== null) {
return ($this->matrix)();
}
delete_transient(ReleaseResolver::CACHE);
ReleaseGate::forget();
return ReleaseGate::status()->matrix;
}
private static function stateLabel(string $state, ?string $source): string
{
return match ($state) {
'released' => 'freigegeben (' . ($source ?? '?') . ')',
'incompatible' => 'inkompatibel',
default => 'ungetestet',
};
}
private function diff(): void
+12 -19
View File
@@ -20,16 +20,19 @@ final class ReleaseStatus
public const SOURCE_DATABASE = 'database';
public const SOURCE_AUTO = 'auto';
private const UNTESTED = 'Achtung: %s ist auf dieser Website noch nicht für LIT MCP freigegeben. Schreibende '
. 'Divi-Werkzeuge sind gesperrt, bis ein Administrator unter Einstellungen → LIT MCP → Divi die Prüfung '
. 'ausführt und die Version freigibt. Es wurde nichts geändert.';
private const UNTESTED = 'Achtung: %s ist auf dieser Website noch nicht für LIT MCP freigegeben. Dieses '
. 'Werkzeug braucht Divi-Fähigkeiten, die noch nicht geprüft sind; andere Divi-Werkzeuge laufen weiter. '
. 'Ein Administrator kann unter Einstellungen → LIT MCP → Divi die Prüfung ausführen und die Version '
. 'freigeben. Es wurde nichts geändert.';
private const UNTESTED_HINT = 'Den Nutzer bitten, die Divi-Prüfung auszuführen und die Version freizugeben; '
. 'lesende Divi-Werkzeuge funktionieren weiter.';
private const INCOMPATIBLE = '%s hat Stellen geändert, die LIT MCP nutzt. Schreibende Divi-Werkzeuge sind '
. 'gesperrt, bis LIT MCP aktualisiert wurde. Es wurde nichts geändert.';
private const INCOMPATIBLE_HINT = 'Den Nutzer informieren, dass LIT MCP aktualisiert werden muss; lesende '
. 'Divi-Werkzeuge funktionieren weiter.';
private const NOTICE = 'Achtung: %s ist für LIT MCP %s; Lesen funktioniert, Schreiben ist gesperrt.';
. 'bis dahin ein Werkzeug ohne die betroffene Fähigkeit nutzen. lit-site-status zeigt unter components → '
. 'divi → features, welche Fähigkeiten und Werkzeuge betroffen sind.';
private const INCOMPATIBLE = '%s hat Stellen geändert, die LIT MCP für dieses Werkzeug nutzt; andere '
. 'Divi-Werkzeuge laufen weiter. Die betroffenen Werkzeuge bleiben gesperrt, bis LIT MCP aktualisiert '
. 'wurde. Es wurde nichts geändert.';
private const INCOMPATIBLE_HINT = 'Den Nutzer informieren, dass LIT MCP aktualisiert werden muss; bis dahin '
. 'ein Werkzeug ohne die betroffene Fähigkeit nutzen. lit-site-status zeigt unter components → divi → '
. 'features, welche Fähigkeiten und Werkzeuge betroffen sind.';
private const FEATURE_UNTESTED = 'Achtung: %1$s ist auf dieser Website für %2$s noch nicht für LIT MCP '
. 'freigegeben. Das ist gesperrt, bis ein Administrator unter Einstellungen → LIT MCP → Divi die Prüfung '
. 'ausführt und die Version freigibt. Es wurde nichts geändert.';
@@ -158,16 +161,6 @@ final class ReleaseStatus
);
}
/** The warning a reading Divi tool carries while writes are locked. */
public function notice(): string
{
return sprintf(
self::NOTICE,
$this->versionLabel(),
$this->state === ReleaseState::Incompatible ? 'inkompatibel' : 'ungetestet'
);
}
/**
* "„Seiten schreiben“", "„A“ und „B“", "„A“, „B“ und „C“".
*