refactor: DiviWriteAbility base and shared DiviErrors (H4)

The five Divi write tools extend DiviWriteAbility (final permission and
execute, change() per tool, shared output schema). DiviErrors holds the
unknown-node, position and compose-error mapping; DiviContentComposer uses
the same mapping (ledger T9). ToolNamingTest skips abstract classes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
2026-09-26 18:22:51 +02:00
co-authored by Claude Opus 5.5
parent 9da236b0e3
commit ecfece719d
12 changed files with 141 additions and 187 deletions
@@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Pages;
use LIT\MCP\Abilities\Ability;
use LIT\MCP\Abilities\ToolResult;
use WP_Error;
/**
* The frame of the Divi write tools (spec §5.6): permission and execute both load the page
* through DiviWriter::page() (rights, Divi layout, tree_rev lock – execute never trusts state
* from permission), the tool changes the tree in change() – only when its whole input
* validated, all or nothing (ruling S39) – and DiviWriter::save() stores it and builds the
* result. The composition is bound to the page (DiviWriter::composition(), ruling S22).
*/
abstract class DiviWriteAbility implements Ability
{
public function __construct(protected DiviWriter $writer)
{
}
/**
* Changes the tree of $page, or returns why nothing is written. Client values enter the
* tree only through $composition (Composer / TreeEditor).
*
* @param array<string, mixed> $input
*/
abstract protected function change(DiviPage $page, array $input, DiviComposition $composition): DiviChange|WP_Error;
public function outputSchema(): ?array
{
return ToolResult::schema(['tree_rev' => ['type' => 'string']], ['tree_rev']);
}
public function isDirect(): bool
{
return true;
}
final public function permission(array $input): bool|WP_Error
{
$page = $this->writer->page($input);
return $page instanceof WP_Error ? $page : true;
}
final public function execute(array $input): mixed
{
$page = $this->writer->page($input);
if ($page instanceof WP_Error) {
return $page;
}
$change = $this->change($page, $input, $this->writer->composition($page));
if ($change instanceof WP_Error) {
return $change;
}
return $this->writer->save($this->name(), $page, $change, $input);
}
}