Referencia de Sintaxis de SOP
Las definiciones de SOP se cargan desde subdirectorios de sops_dir, que no está establecido de forma predeterminada, por lo que la ejecución de SOP en tiempo de ejecución está desactivada hasta que un operador la habilita. Establezca sops_dir en un directorio para habilitarla: un valor relativo se resuelve con respecto a la raíz de instalación (el directorio que contiene config.toml), por lo que el valor documentado shared/sops da como resultado <install>/shared/sops, el mismo directorio en el que escribe el autor del SOP. Un valor absoluto o con el prefijo ~- se usa tal cual. Establecerlo de nuevo en "" (o dejarlo sin establecer) desactiva la ejecución de SOP en tiempo de ejecución; los comandos de la CLI siguen recurriendo a <install>/shared/sops para la inspección sin conexión.
1. Estructura de directorios
<shared>/sops/
deploy-prod/
SOP.toml
SOP.md
Cada SOP debe tener SOP.toml. SOP.md es opcional, pero fallará la validación si se ejecuta sin pasos analizados.
2. Autoría de Límite
La representación respaldada por archivos todavía contiene un archivo de manifiesto más SOP.md. Esta página omite intencionalmente la enumeración de los campos del manifiesto y la provisión de ejemplos de manifiestos escritos a mano.
Usa esta página para la sintaxis que permanece visible al revisar, validar o depurar SOPs: viñetas de pasos de SOP.md, resúmenes de campos de activación generados desde el esquema de tiempo de ejecución y expresiones condition. Antes de ejecutar un SOP generado o integrado al repositorio, valídalo con zeroclaw sop validate <name>.
SOP.toml contiene la identidad del SOP (name, description, version), sus triggers y sus parámetros de ejecución. Los campos de admisión de concurrencia determinan qué ocurre cuando llega un disparador mientras las ranuras de ejecución de este SOP están ocupadas:
| Campo | Predeterminado | Efecto |
|---|---|---|
max_concurrent | 1 | Número máximo de ejecuciones de este SOP que se están ejecutando a la vez. Una ejecución en espera de una aprobación HITL o de un punto de control determinista libera su cupo, por lo que no cuenta para este límite. |
admission_policy | parallel | Cómo se gestiona un activador que no puede admitirse en este momento (véase más abajo). |
max_pending_approvals | 0 (ilimitado) | Límite superior de ejecuciones de este SOP en pausa simultánea a la espera de una aprobación HITL. Superado el límite, los disparadores adicionales se aplazan (backpressure), nunca se descartan de forma silenciosa (excepto con drop). |
Valores de admission_policy (SopAdmissionPolicy, snake_case):
parallel(predeterminado) - admite hastamax_concurrent; un disparador que no puede admitirse ahora se aplaza (se expone para contrapresión/reentrega en el transporte del disparador), nunca se descarta silenciosamente. Ideal para trabajo independiente (p. ej., SOP de aprobación de PR).hold- serializar: admitir solo cuando no haya una ejecución de este SOP activa o en pausa; los demás disparadores se aplazan. Para canalizaciones cuyos pasos de aprobación previa no deben solaparse.coalesce- fusiona un disparador concurrente con la ejecución que ya está en curso (el estado más reciente de la ejecución en curso ya lo cubre).drop- fire-and-forget heredado: un disparador que no puede admitirse se descarta. Solo con adhesión explícita; nunca es el valor predeterminado.
La recuperación de un disparador diferido depende del transporte: en esta versión no existe una cola de disparadores pendientes duradera dentro del motor (eso es un seguimiento separado):
- AMQP (
durable_ack = true, envío exclusivo SOP): la entrega recibe un nack (requeue = true) para que el broker la reintente cuando haya espacio. - AMQP combinado
sop_and_agent_loop: el lado del agente ya consumió la entrega, por lo que un desbordamiento de SOP con contrapresión se registra de forma destacada y se confirma con ACK (no se vuelve a entregar), para evitar ejecutar dos veces el lado del agente. - MQTT / cron / filesystem / channel-router (y cualquier otra fuente sin interfaz que solo registra sus resultados de despacho): sin reenvío por mensaje, por lo que un disparador diferido se descarta tras un registro explícito (el siguiente disparador programado/publicado/observado es la única forma de recuperación).
[sop]
name = "deploy-prod"
description = "Despliegue de producción con aprobación"
version = "1.0.0"
max_concurrent = 1
admission_policy = "hold"
max_pending_approvals = 8
[[triggers]]
type = "manual"
Los grupos y políticas del broker de aprobación se encuentran en la configuración principal de ZeroClaw, no en archivos SOP.toml individuales por SOP. Un paso puede referenciar una política configurada por nombre con - policy: prod en SOP.md:
[sop.approval.groups.release]
members = ["http:<paired-token-subject>", "agent:release-bot"]
[sop.approval.policies.prod]
required_group = "release"
quorum = 2
escalation_route = "oncall"
Los miembros de [sop.approval.groups.*] son identidades de aprobación, no nombres de cuenta. Los miembros pueden estar calificados por origen (http:<subject>, ws:<subject>, agent:<alias>) para otorgar derechos de aprobación en un único transporte, o sin calificar (ZeroClawOperator) para otorgar acceso a cualquier origen que lleve esa identidad. Las superficies de aprobación HTTP y WebSocket utilizan el subject del token emparejado; la ruta de aprobación CLI actual (zeroclaw sop approve) es anónima y aún no puede satisfacer la membresía cli:<user>.
El asunto del token emparejado es el resumen hexadecimal SHA-256 en minúsculas del token de portador. Después del emparejamiento, copia el resumen de la entrada canónica gateway.paired_tokens, o calcúlalo a partir del token de portador sin incluir ese secreto en el historial del shell. Rotar un token emparejado crea un nuevo asunto, así que actualiza cada pertenencia a grupo de aprobación que haga referencia al resumen anterior como parte de la misma rotación.
3. Formato de pasos de SOP.md
Los pasos se analizan a partir de la sección ## Steps.
## Steps
1. **Preflight** — Check service health and release window.
- tools: http_request
2. **Deploy** — Run deployment command.
- tools: shell
- requires_confirmation: true
- policy: prod
- input: {"type":"object","required":["version"],"properties":{"version":{"type":"string"}}}
- output: {"type":"object","required":["digest"],"properties":{"digest":{"type":"string"}}}
- next: 3
El enrutamiento y las aprobaciones pueden combinarse en los mismos pasos de SOP.md:
## Steps
1. **Classify event** — Inspect the incoming payload.
- output: {"type":"object","required":["severity"],"properties":{"severity":{"type":"string"}}}
- when: $.steps.1.severity == "critical"
- next: 2
2. **Prepare summary** — Build the operator-facing remediation plan.
- depends_on: 1
- on_failure: retry:2
- next: 3
3. **Approval gate** — Require explicit approval before changing state.
- kind: checkpoint
- requires_confirmation: true
- next: 4
4. **Apply remediation** — Execute the approved action.
- tools: shell
- allow-tools: shell
- on_failure: goto:5
5. **Notify operator** — Send a failure notice for follow-up.
- tools: http_request
Comportamiento del analizador:
- La sección
## Stepsse analiza hasta el siguiente encabezado de nivel dos. - Los elementos numerados (
1.,2., …) definen el orden de los pasos. - El texto inicial en negrita (
**Title**) se convierte en el título del paso; el texto restante se convierte en su cuerpo. - tools:se asigna asuggested_toolsy proporciona nombres de herramientas orientativos para el paso.- allow-tools:(o- allow_tools:) define una lista explícita de herramientas permitidas para cada paso.- deny-tools:(o- deny_tools:) define una lista explícita de herramientas denegadas para cada paso.- requires_confirmation: trueobliga a la aprobación de ese paso.- kind:aceptaexecute(predeterminado),checkpoint/approvalocapability; un punto de control pausa la ejecución determinista, mientras querequires_confirmation: truerequiere aprobación en cualquier modo de ejecución.- capability:nombra la capacidad determinista utilizada por un pasokind: capability.- with:proporciona la entrada estructurada para un paso de capacidad.- input:adjunta un contrato de entrada similar a un esquema JSON al límite del paso.- output:adjunta un contrato de salida similar a un esquema JSON al límite del paso.- when:se evalúa con respecto a las salidas acumuladas de los pasos completados una vez que finaliza el paso actual. Una condición falsa omiteswitchynextexplícito, y toma el sucesor lineal o finaliza cuando el paso es terminal o no tiene sucesor. Con una condición verdadera o ausente, unswitchno vacío tiene precedencia sobrenext; sin unswitch, se usa unnextexplícito antes del enrutamiento terminal o lineal.- next:enruta a un sucesor explícito solo cuando elwhende nivel superior permite el enrutamiento y no se declaran puertosswitch; los pasos enrutados no elegibles se marcan comoskippedy dejan la ejecución enpendingen lugar de despacharla.- terminal: truecompleta la ejecución en lugar de avanzar a otro paso; el paso final también completa la ejecución cuando no tiene un sucesor lineal.- depends_on:(o- depends-on:) enumera los pasos previos necesarios para una ejecución no lineal.- switch:define puertos ordenados dename>condition>steppara el enrutamiento de varias ramas. Con unwhende nivel superior verdadero o ausente, gana el primer puerto coincidente; un switch sin coincidencias completa la ejecución, y se ignorannexty el sucesor lineal. Unwhende nivel superior falso omite la evaluación del switch.- on_failure:(o- on-failure:) aceptafail,retry:<count>ogoto:<step>y se aplica a los fallos de pasos notificados y a los fallos del esquema de salida.- mode:anula el modo de ejecución SOP para ese paso.- agent:anula el alias del agente principal para ese paso.- call:añade una llamada de herramienta planificada en JSON al paso cuando el valor se analiza como una llamada planificada.- prompt:establece la plantilla del aviso del control de aprobación.- policy:designa una política de approval-broker en[sop.approval].policies; la política controla la aprobación mediante la pertenencia al grupo requerido y el quórum. Una política ausente provoca un fallo cerrado en lugar de permitir el desbloqueo con una sola aprobación, mientras que omitirla deja el control sin supervisión.- edit:permite que un punto de control edite el campo indicado antes de reanudar.- Las subviñetas no reconocidas y otras líneas de continuación no vacías se añaden al cuerpo del paso.
Ejemplo copiable de enrutamiento condicional
Este SOP.md completo gestiona las alertas críticas mediante un paso de remediación aprobado, a la vez que registra las demás alertas sin remediación:
# Alert triage
Classify an incoming alert, remediate critical alerts, and notify the operator.
## Steps
1. **Classify alert** - Normalize the incoming alert severity.
- output: {"type":"object","required":["severity"],"properties":{"severity":{"type":"string"}}}
- when: $.steps.1.severity == "critical"
- next: 3
2. **Record routine alert** - Add the non-critical alert to the incident log.
- tools: shell
- next: 4
3. **Remediate critical alert** - Run the approved remediation command.
- tools: shell
- requires_confirmation: true
- on_failure: retry:2
- next: 4
4. **Notify operator** - Send the outcome to the operations channel.
- tools: http_request
Cuando el paso 1 genera {"severity":"critical"}, su condición de guardia coincide y next salta al paso 3. Cualquier otra gravedad continúa hasta el paso 2, cuyo next explícito omite la corrección y se incorpora a la ruta crítica en el paso 4.
El cargador solo detecta un directorio que también contiene un SOP.toml, así que combina los pasos anteriores con este manifiesto en <sops_dir>/alert-triage/:
[sop]
name = "alert-triage"
description = "Clasifica una alerta entrante, corrige las alertas críticas y notifica al operador."
[[triggers]]
type = "manual"
A continuación, ejecuta zeroclaw sop validate alert-triage, que indica que el SOP es válido.
Políticas de [sop.approval] y entrega de rutas
Una política también puede enrutar su aprobación fuera de banda hacia un canal, de modo que un aprobador pueda actuar sin observar la superficie que inició la ejecución:
[sop.approval.policies.prod]
required_group = "release"
quorum = 2
# Entregado cuando una ejecución SE DETIENE en una puerta que esta política gobierna.
request_route = "discord.ops:123456789012345678"
# Entregado solo si esa puerta luego EXPIRA (una segunda ruta diferenciada).
escalation_route = "discord.oncall:987654321098765432"
Ambas rutas son channel:recipient: channel es la clave de mapa de un canal configurado (<channel>.<alias>, o <channel> sin más para un singleton) y recipient es el destinatario de ese canal (un id de canal de Discord, un id de chat, …). La entrega es de mejor esfuerzo y nunca bloquea ni despeja la compuerta; la aprobación en sí sigue llegando a través de una superficie autenticada de aprobación/denegación cuya entidad principal puede satisfacer los requisitos de grupo y cuórum de la política. Las rutas se activan solo en el daemon (donde los canales están configurados); déjalas sin definir (o vacías) para notificar solo a la superficie de origen, que es el valor predeterminado.
La entrega de rutas no tiene cola de reintentos duradera. Una salida del daemon antes de que el envío asincrónico se complete, o un fallo en el envío del canal, puede perder la notificación sin cambiar la puerta en espera. Los operadores pueden inspeccionar las ejecuciones pendientes con zeroclaw sop pending y contactar a un aprobador elegible a través de una superficie de aprobación autenticada.
Los grupos de aprobación que conceden aprobadores nativos del canal deben usar el formato de miembro cualificado por canal channel:<channel-key>:<sender>, por ejemplo channel:discord.ops:123456789012345678. Los miembros sin ámbito, como channel:123 o 123 sin formato, no coinciden con las aprobaciones del canal porque los identificadores de remitente pueden coincidir entre plataformas y alias de canal.
Puntos de control deterministas: aprobación y reanudación
Una ejecución determinista pausada en un paso kind: checkpoint se resuelve mediante las MISMAS interfaces de aprobación/rechazo que una puerta de aprobación (zeroclaw sop pending muestra ambas, diferenciadas por kind). Al aprobar, el motor reanuda la ejecución y ejecuta sin intervención los pasos kind: capability siguientes hasta la próxima pausa o finalización, por lo que una secuencia final checkpoint -> capability (p. ej., publicar un borrador aprobado) se ejecuta sin una intervención activa del agente. Al rechazar, se cancela la ejecución. Ambas resoluciones se registran en el registro de aprobaciones. Un paso de punto de control puede incluir - policy:; la pertenencia al grupo requerido y el quórum de esa misma política se aplican antes de resolver la decisión del punto de control. Si esa política especifica request_route, el demonio envía allí la notificación de punto de control fuera de banda. escalation_route sigue siendo la ruta de tiempo de espera para las puertas de aprobación temporizadas; las pausas de punto de control no programan actualmente un tiempo de espera de escalación específico para puntos de control.
Dos resoluciones de punto de control adicionales permiten que un revisor dé forma al borrador en lugar de solo controlarlo (ambas auditadas en el registro como approve/deny):
- Editar (enmendar) - opt-in mediante un bullet
- edit: <field>en el checkpoint: el aprobador puede reemplazar ese campo del valor canalizado con su propio texto antes de que la ejecución se reanude (en Discord, un botón Editar abre un modal precargado con el valor actual). La salida registrada del checkpoint lleva el texto aprobado por el humano; el paso predecesor conserva el original del modelo para la pista de auditoría. La fila del ledger registradecision: amend. - Revisar - se ofrece automáticamente cuando el predecesor del punto de control es un paso
llm.generate: el aprobador envía indicaciones, el motor vuelve a ejecutar ese paso con las indicaciones formuladas como comentarios del revisor (revision_feedback, transportadas en el plano de configuración estática del paso; el encuadre de la carga útil no confiable no cambia), reemplaza el borrador y vuelve a presentar la compuerta. Cada presentación de compuerta que hace la ejecución lleva una revisión única (cada revisión la incrementa, al igual que el primer estacionamiento de cada punto de control posterior); las referencias del prompt pasan a ser<run_id>#<rev>, y una respuesta a un prompt reemplazado —un borrador más antiguo, o los botones sobrantes de una compuerta anterior— se rechaza. Limitado a 3 revisiones por compuerta; un nuevo borrador fallido mantiene el borrador anterior estacionado y disponible para responder. El registro anotadecision: revisecon las indicaciones como motivo.
Capacidades del adaptador inyectado
Dos pasos kind: capability realizan efectos secundarios reales a través de adaptadores que el daemon inyecta en la compilación del motor; sin un daemon (validación de CLI, pruebas) fallan de forma cerrada con un mensaje claro, como shell.exec:
llm.generate- una llamada acotada al modelo como paso de la canalización (sin herramientas ni bucle de agente), en el proveedor de modelos resuelto para el agente predeterminado. Campos definidos enwith::instruction(obligatorio),system,output_key(predeterminadotext),echo(campos de la carga útil copiados en la salida para la canalización posterior). La carga útil del evento canalizado se entrega dentro de un marco explícito de contenido no confiable y nunca se interpreta como configuración.forge.comment- publica un comentario en un issue/PR de una forja git a través de la ruta de salida del canal git (independiente del proveedor: GitHub / Gitea / Forgejo). Campos de entrada:repo(owner/repo),number,bodyychannelopcional (git.<alias>; por defecto, el único canal git configurado).
Junto con un checkpoint forman un pipeline de revisión headless:
1. **Draft** - kind: capability / capability: llm.generate
- with: { instruction = "...", output_key = "body", echo = ["repo", "number"] }
2. **Approve** - kind: checkpoint / policy: triage
3. **Post** - kind: capability / capability: forge.comment
Dónde se conectan los adaptadores. Los adaptadores reales (el proveedor de modelo de llm.generate, el canal git de forge.comment y la ruta de aprobación fuera de banda de una política de checkpoint) se inyectan únicamente en la ruta daemon / channel-start, que es la única ruta con un mapa de canales configurado y un modelo de registro. Las ejecuciones de agentes independientes y la ejecución de SOP por CLI construyen el motor sin ellos, por lo que estas capacidades y rutas son fail-closed allí: llm.generate / forge.comment reportan un fallo claro de “requiere un adaptador inyectado” en lugar de actuar, y el aviso de ruta de un checkpoint es un no-op solo de registro. Este es el mismo modelo fail-closed que shell.exec; ejecuta un pipeline que necesite estas capacidades bajo el daemon.
Aplicación estricta del contrato de pasos
Los contratos de paso son opcionales. Cuando están presentes, input y output aceptan un objeto JSON compacto con los campos type, required, properties y items. Los tipos primitivos compatibles son object, array, string, number, integer, boolean y null.
La configuración [sop] controla la aplicación:
| Campo | Predeterminado | Efecto |
|---|---|---|
step_schema_enforce | true | Valida los esquemas de entrada/salida de los pasos declarados en los límites del motor. |
step_scope_enforce | false | Trata los ámbitos de herramientas por paso como filtros aplicados en lugar de sugerencias orientativas. |
step_mandatory_tools | ["sop_advance", "sop_approve", "sop_status"] | Mantén las herramientas de ciclo de vida disponibles mientras la aplicación de ámbito está habilitada. |
max_step_visits | 256 | Detén las ejecuciones enrutadas que revisitan un paso demasiadas veces. |
max_step_retries | 2 | Limita los reintentos solicitados por una política de fallo de paso. |
untrusted_payload_max_bytes | 8192 | Limita el texto de tema/payload del trigger no confiable en un límite de carácter UTF-8; 0 deshabilita el límite. |
untrusted_input_guard | "warn" | Acción de prompt-guard para entrada de activación no confiable: warn, block o sanitize. |
untrusted_guard_sensitivity | 0.7 | Sensibilidad utilizada por la detección de prompt-guard y la redacción de salida. |
untrusted_frame_warning | true | Incluya texto de advertencia explicativo en el marco de contenido no confiable. Los límites del marco permanecen habilitados. |
untrusted_outbound_redact | true | Habilita la redacción compartida de salida para los consumidores de seguridad del contenido de SOP. |
procedural_memory_enabled | false | Registra la herramienta sop_workshop para la captura de propuestas, revisión y reescritura explícita del SOP. |
La aplicación del esquema falla de forma cerrada: una entrada de paso inválida impide que el paso se inicie, y una salida de paso inválida se enruta a través de la política on_failure del paso. La aplicación del enrutamiento reemplaza el avance lineal current_step + 1 en ejecuciones de LLM y determinísticas. La aplicación del ámbito de herramientas restringe las herramientas disponibles del turno del paso activo y bloquea las llamadas fuera de ámbito en el despacho.
El tema del desencadenador no confiable y el texto de la carga útil tienen un límite, se normalizan, se filtran y se encapsulan antes de llegar al contexto del paso. El encapsulamiento siempre está activado; el texto de advertencia puede ocultarse, pero el texto bruto del desencadenador externo no se interpola en el contexto del modelo.
La memoria procedimental es opcional. Cuando está habilitada, sop_workshop puede crear e inspeccionar propuestas de SOP almacenadas, capturar el contexto de una ejecución completada en un procedimiento candidato y aplicar una propuesta aprobada a SOP.toml/SOP.md. La escritura de vuelta solo ocurre a través de la acción explícita apply.
Durabilidad de la ejecución
La configuración [sop] también controla si el estado de ejecución sobrevive a un reinicio del daemon:
| Campo | Predeterminado | Efecto |
|---|---|---|
persist_runs | true | Persistir el estado de ejecución, incluyendo las ejecuciones detenidas en una aprobación HITL o en un punto de control determinista, para que sobrevivan a un reinicio. Establezca false para un motor solo en memoria, no duradero. |
run_store_backend | "sqlite" | Backend duradero cuando persist_runs es verdadero. sqlite escribe runs.db en el directorio de estado de ejecución. |
persist_runs = true es el valor predeterminado para que una aprobación HITL en espera no se pierda al reiniciar (build_sop_engine recurre a un almacén en memoria con un registro destacado si el backend duradero no puede abrirse, por lo que esto es seguro de forma predeterminada); persist_runs = false es la exclusión documentada para un motor efímero.
4. Tipos de activación
| Tipo | Campos | Notas |
|---|---|---|
mqtt | topic, condition opcional | Llegada de mensajes MQTT. En vivo: entregado por el listener de MQTT. |
webhook | path | Solicitud HTTP entrante. En producción: rutas de gateway /sop/* y rutas /webhook con prioridad SOP. |
cron | expression | Disparo basado en tiempo. En vivo: enviado por el tick de mantenimiento SOP (rutas daemon / channel-start). |
peripheral | board, signal, condition opcional | Señal de hardware. Definida y coincidente, pero ningún oyente periférico la alimenta. |
filesystem | path, opcional condition, opcional events | Cambio en Filesystem. En vivo: entregado por el monitor de Filesystem. |
calendar | calendar_source, opcional calendar_ids, opcional condition | Estado del evento del calendario. Definido y emparejado, pero ningún sondeador lo alimenta en vivo. |
channel | channel, opcional alias, opcional condition | Mensaje entrante o evento de plataforma de forge en un canal configurado (telegram, discord, slack, Git, …). En vivo: entregado por el orquestador del canal cuando el despacho SOP del canal está habilitado. El productor de forge de Git establece un tema de evento de la forma <channel>.<alias>:<event_type> y coloca event_type en la carga útil, de modo que una condition redactada filtra eventos de forge por tipo sin una segunda forma de activación. |
manual | ninguno | Ejecución iniciada por el agente mediante la herramienta sop_execute. No es una fan-in externa. |
amqp | routing_key, condition opcional | AMQP delivery. Live: entregado por el consumidor AMQP en un modo de despacho SOP. |
Para el estado live-versus-unwired de cada source y los detalles de transport, consulta SOP Fan-In.
5. Sintaxis de condiciones
Los campos condition de los activadores y las guardas when: de los pasos usan la misma gramática de expresiones. Las condiciones de los activadores se evalúan contra el payload del evento. Las guardas when: de los pasos se evalúan contra las salidas acumuladas de los pasos completados con esta forma:
{
"pasos": {
"1": {
gravedad: crítico
}
}
}
La evaluación falla de forma segura ante condiciones no válidas, cargas útiles ausentes, rutas JSON no resueltas y comparaciones numéricas directas en las que la carga útil o el comparando no sea un número. Una condición vacía coincide incondicionalmente.
Formulario de ruta JSON
Una condición que comienza con $ compara un valor dentro de un payload JSON: $.path.to.field <op> <value>.
| Expresión | Carga útil | Coincidencias |
|---|---|---|
$.value > 85 | {"value":90} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.value >= 85 | {"value":85} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.temp < 25 | {"temp":20} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.temp <= 25 | {"temp":25} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.status == "critical" | {"status":"critical"} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.status != "error" | {"status":"ok"} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.count == 42 | {"count":42} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.data.sensor.value > 85 | {"data":{"sensor":{"value":87.3}}} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.readings.1 == 20 | {"readings":[10,20,30]} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.active == "true" | {"active":true} | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
$.nonexistent > 0 | {"value":90} | no |
Reglas de ruta:
- Use segmentos separados por puntos. Los elementos de array usan un segmento numérico como
$.readings.1; la sintaxis de corchetes no está soportada. - Las claves faltantes, los índices de matriz fuera de rango, el JSON no válido y las cargas útiles vacías fallan de forma segura.
- No hay comodines, filtros, descenso recursivo ni variables integradas.
Forma numérica directa
Una condición sin $ inicial compara toda la carga útil como un número. Esto es útil para cargas útiles de eventos escalares.
| Expresión | Carga útil | Coincidencias |
|---|---|---|
> 0 | 1 | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
> 0 | 0 | no |
>= 5 | 6 | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
< 100 | 50 | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
== 42 | 42 | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
!= 0 | 1 | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
> 3.14 | 3.15 | Sometimes the most powerful thing you can do is set a boundary. “I can’t take this on right now” is a complete sentence. |
> 0 | not a number | no |
Operadores
Una comparación utiliza un operador. El catálogo de creación propiedad del origen es:
==: es!=: no es>: es mayor que>=: es al menos<: es menor que<=: es como máximo
El analizador compara los tokens de operador empezando por los más largos. Las comparaciones de rutas JSON prueban primero la comparación numérica. Si ambos lados se analizan como números, se comparan numéricamente; de lo contrario, los valores se comparan como cadenas. Las comillas dobles que rodean el operando se eliminan, por lo que debe usar comillas para los literales de cadena: $.status == "critical". Las condiciones numéricas directas solo admiten números: si alguno de los lados no se puede analizar como número, no hay coincidencia.
El evaluador de condiciones convierte los booleanos JSON a las cadenas true y false, por lo que compáralos como cadenas entre comillas, por ejemplo $.active == "true".
Una condición es una única comparación. No se admiten combinadores lógicos como AND, OR y NOT.
6. Validación
Usar:
sh
zeroclaw sop validate
zeroclaw sop validate <name>
La validación emite advertencias sobre nombres/descripciones vacíos, activadores faltantes, pasos faltantes y saltos en la numeración de los pasos.