OperationGenerator
Generates an OPERATION: something an agent, the terminal and MCP work with (greenhouse decisions/0591). Nothing else `make` scaffolds enters the agent's catalogue as something to work with: a controller serves a route, an entity stores, and a `#[Tool]` shows up and is refused as unjudgeable, because no producer states its effect. A real resident decided on its own to write `#[Operation]` classes, and the house had no door for it: `implement` fills a class, it does not create one (greenhouse evidence/1127). WHAT IT LEAVES is the declared form of `milpa/command` (greenhouse decisions/0212), one class per operation: - its NAME, `domain:verb` — given (`--operation`), or derived from the plugin and the class and said back; - WHAT IT DOES AT WORST — `#[Mutates]` with the write profile of a domain operation (persistent, no third party, manual recovery, as the caller, over data), or `#[Reads]` when asked (`--reads`). Said nothing, it mutates: silence never lowers a control; - THE AUTHORITY IT SPENDS — `#[Needs(scopes: ['<domain>:write'])]`, or `:read`. The domain is what stands before the separator of its name, so nobody invents a word of authority. It is what a person grants to admit it; - ITS INPUT — the `--fields`, as the constructor; - WHERE ITS STATE LIVES — `run()` receives the repository of an entity of its plugin, the one `make entity` registered: the one `--entity` names, or the plugin's ONLY entity when none is named. Nothing is invented: it is the same store, reached by the same key. With several entities and none named, none is guessed — and the result says so, because a `run()` written against a repository nobody hands it lands and fails at its first call (greenhouse evidence/1154); - what else `run()` WORKS THROUGH — the `--needs`, resolved by whoever registers it. AND IT IS REGISTERED, never left as prose to paste: `operations()` of the plugin lists it through `DeclaredOperation::from()`, at the anchor when the plugin carries one, structurally through {@see PluginSurgeon} when it does not — the same ladder {@see ServiceGenerator} and {@see ControllerGenerator} follow. A plugin `make plugin` or `make entity` scaffolded becomes a `CommandProvider` this way. THE BODY IS NOT WRITTEN, AND IT SAYS SO: `run()` answers `ok: false` naming itself a scaffold. A scaffold that answered `ok: true` would be a write that did not happen (greenhouse decisions/0587). `milpa/command` is a dependency of the TARGET app, as every runtime stub's framework classes are.
OperationGenerator::__construct()
public function __construct(Milpa\DevTools\Make\StubRenderer $renderer = new StubRenderer(), Milpa\DevTools\Make\ConventionDetector $detector = new ConventionDetector(), Milpa\DevTools\Make\MarkerInserter $markers = new MarkerInserter(), Milpa\DevTools\Make\StubLocator $locator = new StubLocator(), Milpa\DevTools\Make\PluginSurgeon $surgeon = new PluginSurgeon()):Parameters
| Name | Type | Description |
|---|---|---|
| $renderer | Milpa\DevTools\Make\StubRenderer | |
| $detector | Milpa\DevTools\Make\ConventionDetector | |
| $markers | Milpa\DevTools\Make\MarkerInserter | |
| $locator | Milpa\DevTools\Make\StubLocator | |
| $surgeon | Milpa\DevTools\Make\PluginSurgeon |
OperationGenerator::name()
public function name(): stringThe `<what>` token this generator answers to: `'operation'`.
OperationGenerator::generate()
public function generate(Milpa\DevTools\Make\GenerationContext $context): Milpa\DevTools\Make\GenerationResultRenders the operation and its registration.
Parameters
| Name | Type | Description |
|---|---|---|
| $context | Milpa\DevTools\Make\GenerationContext |
Throws
\RuntimeException when the flavor is {@see Flavor::Legacy}: a declared operation is a runtime concept
\InvalidArgumentException when a name or a field is not one this scaffold can declare without guessing
OperationGenerator::operationName()
public static function operationName(Milpa\DevTools\Make\GenerationContext $context): stringThe name the operation declares: the one given, or `<plugin>:<class>` in kebab case.
Parameters
| Name | Type | Description |
|---|---|---|
| $context | Milpa\DevTools\Make\GenerationContext |
Throws
\InvalidArgumentException when the given name is not `domain:verb`
OperationGenerator::domainOf()
public static function domainOf(string $name): stringThe domain of an operation name: what stands before its first separator.
Parameters
| Name | Type | Description |
|---|---|---|
| $name | string |
OperationGenerator::toolName()
public static function toolName(string $name): stringThe name an agent's catalogue shows for an operation — the rule of `Milpa\Console\McpProjector::toolName()`.
Parameters
| Name | Type | Description |
|---|---|---|
| $name | string |
OperationGenerator::entry()
public static function entry(string $operationFqcn, ?string $entityFqcn = null): stringThe registration entry `operations()` lists, fully qualified so it splices into any plugin file. The closure is how `run()` finds what it works through: every collaborator by its class, from the plugin's container — and, for an operation over an entity, that entity's repository by the id `make entity` registered it under (`Entity::class . 'Repository'`). A repository has no class of its own to be found by.
Parameters
| Name | Type | Description |
|---|---|---|
| $operationFqcn | string | |
| $entityFqcn | ?string |
OperationGenerator::entitiesIn()
public static function entitiesIn(string $pluginDir): arrayThe entities under a plugin's source directory, by name and in order.
Parameters
| Name | Type | Description |
|---|---|---|
| $pluginDir | string |
OperationGenerator::unfilledIn()
public static function unfilledIn(string $pluginDir): arrayThe operations of a plugin whose body is still the scaffold's, by class name. Read from the sentence the scaffold itself answers with: the house wrote it, so the house can tell an unfilled operation from a filled one without calling either (greenhouse evidence/1156).
Parameters
| Name | Type | Description |
|---|---|---|
| $pluginDir | string |
OperationGenerator::entityHandedTo()
public static function entityHandedTo(string $pluginSource, string $class): ?stringThe entity whose repository a plugin hands the operation's `run()`, read back from the entry {@see entry()} wrote — or `null` when the entry finds everything by its class.
Parameters
| Name | Type | Description |
|---|---|---|
| $pluginSource | string | |
| $class | string |
OperationGenerator::lists()
public static function lists(string $pluginSource, string $class): boolWhether a plugin's source already lists the operation class, by its short or its qualified name.
Parameters
| Name | Type | Description |
|---|---|---|
| $pluginSource | string | |
| $class | string |