feat: adapter-level Divi release lock, content-create and site status

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-30 02:04:49 +02:00
co-authored by Claude Opus 5.5
parent adfe0adfc2
commit c6a1996be6
12 changed files with 192 additions and 6 deletions
@@ -10,6 +10,7 @@ use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
use LIT\MCP\Integrations\Divi\BlockTree\Outline;
use LIT\MCP\Integrations\Divi\BlockTree\Serializer;
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
@@ -59,6 +60,13 @@ final class DiviContentComposer implements ContentComposer
return ($this->writable)();
}
public function refusal(): ?WP_Error
{
$status = ReleaseGate::status();
return $status->writable() ? null : $status->refusal();
}
public function check(string $postType, array $sections): ?WP_Error
{
if (! $this->schema->diviEnabled($postType)) {
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\Errors;
use LIT\MCP\Abilities\FollowUp;
use LIT\MCP\Abilities\Rollback;
use LIT\MCP\Abilities\WriteFailed;
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
use LIT\MCP\Integrations\WordPress\PostGuard;
use LIT\MCP\Integrations\WordPress\RevisionPoint;
@@ -69,10 +71,12 @@ class DiviSaver
/**
* @return array{revision_id: ?int, warnings: list<string>}
* @throws WriteFailed
* @throws DiviLocked When Divi is not released (spec §5.5) – before anything is written.
*/
public function save(WP_Post $post, string $content, SaveScope $scope = SaveScope::Page): array
{
$postId = (int) $post->ID;
ReleaseGate::assertWritable($postId);
$revisionId = null;
try {
@@ -138,9 +142,11 @@ class DiviSaver
*
* @return list<string> Warnings (CHANGED_ON_SAVE).
* @throws RuntimeException
* @throws DiviLocked When Divi is not released (spec §5.5) – before anything is written.
*/
public function saveNew(int $postId, string $content, SaveScope $scope = SaveScope::Page): array
{
ReleaseGate::assertWritable($postId);
$refusal = self::refusal($this->writeContent($postId, $content));
if ($refusal !== null) {
throw new RuntimeException(sprintf('wp_update_post(%d) refused the Divi layout: %s', $postId, $refusal));