VerificationTool
Exposes {@see HumanVerifier} as two tools instead of one (D8 / T089, split in tool-runtime 0.3): `request_verification` opens a verification and returns its `request_id`; `resolve_verification` resolves a pending one with a `grant`/`reject` decision. Replaces the single combined verification tool tool-runtime 0.2 shipped, which mixed both phases into one schema with conditional fields ("omit `decision` to request") and a name that read as though the caller could grant its own request. The split gives each phase a clean, non-overlapping schema — `request_verification` has no `decision`/`principal` fields at all; `resolve_verification` requires them — and, as a direct consequence of being separate tools, lets a host's policy allow `request_*` broadly while restricting `resolve_*` to specific principals (the "policy dividend" — see the package README's Verification section for a worked example using {@see self::$resolveScopes} / {@see \Milpa\ValueObjects\Tooling\ToolOptions::$scopes}). Both tools register with `requiresConfirmation: false` — same reasoning as 0.2's single-tool bypass, now applying to each half independently: `handleRequest()` / `handleResolve()` together already ARE the two-phase confirmation protocol, so stacking the registry's generic step-4 confirm-token gate on top would recreate the exact double-gate choreography 0.2 killed. See {@see \Milpa\ToolRuntime\PolicyGate::requiresConfirmation()} for the one channel-level exception (`require_confirmation_for_mutating`, e.g. the built-in `telegram` policy) that still gates any `mutating: true` tool regardless of this flag.
VerificationTool::__construct()
public function __construct(Milpa\ToolRuntime\Verification\HumanVerifier $verifier, array $resolveScopes = []):Parameters
| Name | Type | Description |
|---|---|---|
| $verifier | Milpa\ToolRuntime\Verification\HumanVerifier | |
| $resolveScopes | list<string> | Scopes required to call `resolve_verification` (empty = open to anyone who can reach the registry, matching the pre-split default). `request_verification` never takes a scopes parameter — it is always open; that asymmetry IS the policy dividend the split buys. |
VerificationTool::register()
public function register(Milpa\Interfaces\Tooling\ToolRegistryInterface $registry): voidRegister `request_verification` and `resolve_verification` on the given registry.
Parameters
| Name | Type | Description |
|---|---|---|
| $registry | Milpa\Interfaces\Tooling\ToolRegistryInterface |
VerificationTool::handleRequest()
public function handleRequest(array $args): Milpa\ToolRuntime\ToolResultHandle a `request_verification` call: open a verification request for `subject`. Always opens a new request and returns {@see ToolResult::confirmation()} carrying its `request_id` — this tool never resolves a verdict itself, only {@see handleResolve()} does.
Parameters
| Name | Type | Description |
|---|---|---|
| $args | array<string, mixed> |
VerificationTool::handleResolve()
public function handleResolve(array $args): Milpa\ToolRuntime\ToolResultHandle a `resolve_verification` call: resolve a pending verification by `request_id`. `subject` is optional here. When the caller echoes it back, the reconstructed {@see VerificationRequest} carries the true subject. When omitted, this builds the request via {@see VerificationRequest::forResolution()} — `subject = null`, identified purely by `id` — instead of fabricating a value from `request_id` (tool-runtime 0.3's behavior, dropped in favor of core 0.4's resolution seam: a listener on `verification.granted`/`verification.rejected` no longer sees a fake, opaque `subject` that silently diverges from the one carried on `verification.requested` for the same correlation id). The success MESSAGE below still falls back to `request_id` for readability — that is tool-runtime-owned formatting, not the VO's `subject`.
Parameters
| Name | Type | Description |
|---|---|---|
| $args | array<string, mixed> |