SecondOpinionGate
Un segundo juicio entre la llamada propuesta y su ejecución. ── QUÉ PROBLEMA ATACA, CON NÚMERO ────────────────────────────────────────────────────────────── Cuatro tandas y ~200 corridas midieron con qué frecuencia el agente ejecuta la operación destructiva que nadie le pidió: **6, 5, 5, 6, 6 de 16**, y no se movió con ninguna forma de contexto. Peor: Q-P17-J midió que agregar contexto **empeora** la corrección de la respuesta. Esto es lo primero que no le agrega nada al actor. No le explica más ni le pide más: interpone otro lector. Está pre-registrado en Q-P19-D y **puede refutarse** — cinco falsificadores escritos antes de esta clase, incluido «el verificador aprueba todo y no hace nada». ── EL PISO SE QUEDA DEBAJO, Y NO ES UN DETALLE ───────────────────────────────────────────────── La compuerta que ya existe es **sintáctica**: ¿muta?, ¿exige firma?, ¿la sesión concedió permiso? No se le puede convencer de nada. Ésta es un modelo, y **a un modelo se le puede persuadir** — una compuerta que se puede convencer dejó de ser compuerta. Por eso el orden no se negocia: primero pregunta el piso, y **si el piso niega, aquí no se pregunta nada**. Un verificador que pudiera revertir un `no` sintáctico sería una vía de escape con forma de mejora. ── SI EL SEGUNDO JUICIO NO PUEDE OPINAR, DEJA PASAR — Y LO DICE ──────────────────────────────── Cuando el modelo no contesta —sin red, sin llave, un timeout— esto **deja pasar**, porque el piso ya decidió y una capa de mejora que rompe al agente cuando se cae es peor que no tenerla. Pero no calla: un verificador caído se vería exactamente igual que uno que aprueba todo, y ésa es justo la confusión que arruinaría la medición (falsificador 1).
SecondOpinionGate::__construct()
public function __construct(Milpa\AiGateway\ToolCallGate $piso, Milpa\ToolRuntime\Contracts\LlmServiceInterface $modelo, string $tarea, array $jamas = [], array $alternativas = [], Psr\Log\LoggerInterface $logger = new NullLogger(), ?Milpa\AiGateway\OptionTable $mesa = null):Parameters
| Name | Type | Description |
|---|---|---|
| $piso | ToolCallGate | la compuerta sintáctica; decide PRIMERO y su `no` es definitivo |
| $modelo | Milpa\ToolRuntime\Contracts\LlmServiceInterface | |
| $tarea | string | lo que el humano pidió, tal cual. Es contra esto que se juzga la llamada: sin la petición, «apagar un plugin» no es ni correcto ni incorrecto |
| $jamas | list<string> | herramientas que este verificador mira con lupa. No es una lista de prohibidas —eso sería el piso otra vez— sino de las que ameritan preguntar si la tarea las pedía |
| $alternativas | array | |
| $logger | Psr\Log\LoggerInterface | |
| $mesa | (OptionTable | null) | a quien se le avisa cuando ESTE juicio niega, para que la opción deje de estar enfrente. Sin mesa, la negativa es sólo un motivo — que es exactamente lo que Q-P19-D/E midieron insuficiente |
SecondOpinionGate::refuse()
public function refuse(string $tool, array $arguments): ?stringEl motivo por el que esta llamada no procede, o `null` si procede. Dos lectores en orden: primero el piso sintáctico —cuyo `no` es definitivo— y sólo si deja pasar, el segundo juicio. El motivo que vuelve es el de quien negó, para que quien recibe la negativa sepa contra qué está.
Parameters
| Name | Type | Description |
|---|---|---|
| $tool | string | |
| $arguments | array<string, mixed> |