aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-rpc/php/runtime/Shirabe/RustCommandStub.php
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-05 03:58:03 +0900
committernsfisis <nsfisis@gmail.com>2026-08-05 03:58:03 +0900
commit9b444a9a879b75a6af3d3c7ba8b9a4294574c3ec (patch)
treeb1041b55bc3ed36a391370cc2f5ececc8cb386b2 /crates/shirabe-php-rpc/php/runtime/Shirabe/RustCommandStub.php
parentbe3458128ef09b3d1074b134f2822162e077e165 (diff)
downloadphp-shirabe-9b444a9a879b75a6af3d3c7ba8b9a4294574c3ec.tar.gz
php-shirabe-9b444a9a879b75a6af3d3c7ba8b9a4294574c3ec.tar.zst
php-shirabe-9b444a9a879b75a6af3d3c7ba8b9a4294574c3ec.zip
feat(plugin): run plugin-provided commands in a worker-side application
A same-FQCN Composer\Console\Application, hand-written under the new php/runtime/ tree, hosts CommandProvider commands inside the PHP worker: PhpCommandProxy overrides run() and forwards the stringified input, so the real Symfony machinery binds, validates and executes against the live command object, while help/list render Rust-side from a definition read back at construction. Reverse \Shirabe\RustCommandStub rows let a plugin command invoke built-in commands back in the Rust process, keeping every command on the side whose helper set it was written for. Composer\EventDispatcher\Event moves from a generated stub to a dual-mode runtime class: the real BaseCommand::initialize constructs a PreCommandRunEvent natively in the worker, which a proxy-only constructor guard rejected. Its PRE_COMMAND_RUN dispatch reaches a new EventDispatcher stub whose dispatch supports the observably-no-op no-listener case and fails explicitly otherwise. The stub generator now accepts runtime-provided classes as stub bases (never as targets) and cross-checks the Application handoff property table against the real class. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-php-rpc/php/runtime/Shirabe/RustCommandStub.php')
-rw-r--r--crates/shirabe-php-rpc/php/runtime/Shirabe/RustCommandStub.php34
1 files changed, 34 insertions, 0 deletions
diff --git a/crates/shirabe-php-rpc/php/runtime/Shirabe/RustCommandStub.php b/crates/shirabe-php-rpc/php/runtime/Shirabe/RustCommandStub.php
new file mode 100644
index 00000000..23ebfc04
--- /dev/null
+++ b/crates/shirabe-php-rpc/php/runtime/Shirabe/RustCommandStub.php
@@ -0,0 +1,34 @@
+<?php
+
+// Worker-side stand-in for a Rust-implemented (built-in) command: it carries only the list
+// metadata, and running it forwards the raw input line back to the Rust process, where the
+// real implementation executes against its own application state (helper set included). This
+// is how a plugin command that invokes a built-in command crosses back over the process
+// boundary; each command always runs on the side that owns its implementation, so a helper
+// lookup always resolves against the helper set of the world the command was written for.
+
+namespace Shirabe;
+
+use Composer\Command\BaseCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class RustCommandStub extends BaseCommand
+{
+ /** @param array{name: string, description: string, aliases: list<string>, hidden: bool} $meta */
+ public function __construct(array $meta)
+ {
+ parent::__construct($meta['name']);
+ $this->setDescription($meta['description']);
+ $this->setAliases($meta['aliases']);
+ $this->setHidden($meta['hidden']);
+ // The real input definition lives on the Rust side and the raw tokens are forwarded
+ // untouched, so nothing may be validated (or consumed) here.
+ $this->ignoreValidationErrors();
+ }
+
+ public function run(InputInterface $input, OutputInterface $output): int
+ {
+ return (int) \ShirabeRpcRuntime::callRust(0, '__shirabe_run_rust_command', [$this->getName(), (string) $input]);
+ }
+}