Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Référence de la syntaxe SOP

Les définitions de SOP sont chargées depuis les sous-répertoires de sops_dir, qui n’est pas défini par défaut ; l’exécution des SOP au runtime est donc désactivée tant qu’un opérateur ne l’a pas activée explicitement. Définissez sops_dir sur un répertoire pour l’activer : une valeur relative est résolue par rapport à la racine d’installation (le répertoire qui contient config.toml), de sorte que la valeur documentée shared/sops donne <install>/shared/sops, le même répertoire que celui dans lequel l’auteur de la SOP écrit. Une valeur absolue ou préfixée par ~- est utilisée telle quelle. Redéfinir sops_dir sur "" (ou ne pas le définir) désactive l’exécution des SOP au runtime ; les commandes CLI utilisent toujours <install>/shared/sops comme solution de repli pour l’inspection hors ligne.

1. Structure des répertoires

<shared>/sops/
  deploy-prod/
    SOP.toml
    SOP.md

Chaque SOP doit avoir SOP.toml. SOP.md est optionnel, mais échouera à la validation s’il n’exécute aucune étape analysée.

2. Limite de création

La représentation sauvegardée sur fichier contient toujours un fichier manifeste ainsi que SOP.md. Cette page ne répertorie intentionnellement pas les champs du manifeste et ne fournit pas d’exemples de manifeste rédigés manuellement.

Utilisez cette page pour la syntaxe qui reste visible lors de la révision, de la validation ou du débogage des SOP : les puces d’étapes de SOP.md, les résumés de champ déclencheur générés à partir du schéma d’exécution, et les expressions condition. Avant d’exécuter un SOP généré ou archivé, validez-le avec zeroclaw sop validate <name>.

SOP.toml porte l’identité de la SOP (name, description, version), ses triggers et ses paramètres d’exécution. Les champs d’admission de concurrence régissent ce qui se passe lorsqu’un déclencheur arrive alors que les créneaux d’exécution de cette SOP sont tous occupés :

ChampPar défautEffet
max_concurrent1Nombre maximal d’exécutions de cette SOP en cours simultanément. Une exécution en attente d’une approbation HITL ou d’un point de contrôle déterministe libère son emplacement, elle n’est donc pas comptabilisée ici.
admission_policyparallelComment est géré un déclencheur qui ne peut pas accepter pour le moment (voir ci-dessous).
max_pending_approvals0 (illimité)Borne supérieure sur le nombre d’exécutions de cette SOP en attente d’une approbation HITL simultanément. Au-delà de cette borne, les déclenchements supplémentaires sont différés (contre-pression), jamais abandonnés silencieusement (sauf en mode drop).

Valeurs de admission_policy (SopAdmissionPolicy, snake_case) :

  • parallel (par défaut) - admet jusqu’à max_concurrent ; un déclencheur qui ne peut pas être admis immédiatement est différé (signalé pour backpressure/redistribution sur le transport du déclencheur), jamais abandonné silencieusement. Idéal pour les tâches indépendantes (par exemple, les SOP d’approbation de PR).
  • hold - sérialiser : n’admettre que lorsqu’aucune exécution de ce SOP n’est active ou en pause ; les autres déclencheurs sont différés. Pour les pipelines dont les étapes de pré-approbation ne doivent pas se chevaucher.
  • coalesce - fusionne un déclencheur concurrent avec l’exécution déjà en cours (l’état le plus récent de l’exécution en cours le couvre déjà).
  • drop - « fire-and-forget » hérité : un déclencheur qui ne peut pas être admis est abandonné. Activation explicite uniquement ; jamais par défaut.

La reprise d’un déclencheur différé dépend du transport - il n’existe pas, dans cette version, de file d’attente durable des déclencheurs en attente au sein du moteur (cela fera l’objet d’un suivi distinct) :

  • AMQP (durable_ack = true, distribution réservée aux SOP) : la livraison est rejetée avec un nack (requeue = true) afin que le broker la réessaie dès qu’il y a de la place.
  • AMQP combiné sop_and_agent_loop : le côté agent a déjà consommé la livraison ; un débordement de SOP dû à la contre-pression est donc consigné de façon bien visible et acquitté (sans être remis), afin d’éviter de réexécuter deux fois le côté agent.
  • MQTT / cron / système de fichiers / channel-router (et toute autre source sans interface qui ne fait que journaliser ses résultats de distribution) : pas de nouvelle livraison par message ; un déclencheur différé est donc abandonné après un journal explicite (le prochain déclencheur planifié/publié/observé est la seule récupération).
[sop]
name = "deploy-prod"
description = "Production deploy with approval"
version = "1.0.0"
max_concurrent = 1
admission_policy = "hold"
max_pending_approvals = 8

[[triggers]]
type = "manual"

Les groupes et politiques du courtier d’approbation se trouvent dans la configuration principale de ZeroClaw, et non dans les fichiers SOP.toml propres à chaque SOP. Une étape peut référencer une politique configurée par son nom avec - policy: prod dans 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"

Les membres de [sop.approval.groups.*] sont des identités d’approbation, pas des noms de compte. Les membres peuvent être qualifiés par source (http:<subject>, ws:<subject>, agent:<alias>) pour accorder des droits d’approbation sur un seul transport, ou nus (ZeroClawOperator) pour accorder l’accès à toute source portant cette identité. Les surfaces d’approbation HTTP et WebSocket utilisent le sujet du jeton couplé ; le chemin d’approbation CLI actuel (zeroclaw sop approve) est anonyme et ne peut pas encore satisfaire l’appartenance cli:<user>.

Le sujet du jeton apparié est l’empreinte hexadécimale SHA-256 en minuscules du jeton porteur. Après l’appariement, copiez l’empreinte à partir de l’entrée canonique gateway.paired_tokens, ou calculez-la à partir du jeton porteur sans placer ce secret dans l’historique du shell. La rotation d’un jeton apparié crée un nouveau sujet ; mettez donc à jour, dans le cadre de la même rotation, chaque appartenance à un groupe d’approbation qui référence l’ancienne empreinte.

3. Format des étapes de SOP.md

Les étapes sont analysées à partir de la section ## 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

Les étapes d’acheminement et d’approbation peuvent être combinées dans les mêmes étapes 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

Comportement de l’analyseur :

  • La section ## Steps est analysée jusqu’au prochain titre de niveau deux.
  • Les éléments numérotés (1., 2., …) définissent l’ordre des étapes.
  • Le texte en gras au début (**Title**) devient le titre de l’étape ; le texte restant en constitue le corps.
  • - tools: correspond à suggested_tools et fournit les noms des outils à titre indicatif pour l’étape.
  • - allow-tools: (ou - allow_tools:) définit une liste explicite des outils autorisés pour chaque étape.
  • - deny-tools: (ou - deny_tools:) définit une liste explicite d’outils interdits pour chaque étape.
  • - requires_confirmation: true impose une approbation pour cette étape.
  • - kind: accepte execute (par défaut), checkpoint/approval ou capability ; un point de contrôle met en pause l’exécution déterministe, tandis que requires_confirmation: true exige une approbation quel que soit le mode d’exécution.
  • - capability: désigne la capacité déterministe utilisée par une étape kind: capability.
  • - with: fournit l’entrée structurée d’une étape de capacité.
  • - input: associe un contrat d’entrée semblable à un schéma JSON à la limite de l’étape.
  • - output: associe un contrat de sortie similaire à un schéma JSON à la limite de l’étape.
  • La clause - when: est évaluée par rapport aux sorties cumulées des étapes terminées après la fin de l’étape courante. Une garde fausse contourne switch et next explicite, en prenant le successeur linéaire ou en terminant lorsque l’étape est terminale ou n’a pas de successeur. Avec une garde vraie ou absente, un switch non vide est prioritaire sur next ; en l’absence de switch, un next explicite est utilisé avant le routage terminal ou linéaire.
  • - next: achemine vers un successeur explicite uniquement lorsque le when de niveau supérieur autorise le routage et qu’aucun port switch n’est déclaré ; les étapes routées non éligibles sont marquées skipped et laissent l’exécution à l’état pending au lieu d’être déclenchées.
  • - terminal: true termine l’exécution au lieu de passer à une autre étape ; l’étape finale se termine également lorsqu’elle n’a pas de successeur linéaire.
  • - depends_on: (ou - depends-on:) répertorie les étapes préalables d’une exécution non linéaire.
  • - switch: définit des ports name>condition>step ordonnés pour le routage à plusieurs branches. Avec un when de niveau supérieur vrai ou absent, le premier port correspondant l’emporte ; un switch sans correspondance termine l’exécution, et next ainsi que le successeur linéaire sont ignorés. Un when de niveau supérieur faux contourne l’évaluation du switch.
  • - on_failure: (ou - on-failure:) accepte fail, retry:<count> ou goto:<step> et s’applique aux échecs d’étape signalés ainsi qu’aux échecs du schéma de sortie.
  • - mode: remplace le mode d’exécution du SOP pour cette étape.
  • - agent: surcharge l’alias de l’agent parent pour cette étape.
  • - call: ajoute un appel d’outil planifié JSON à l’étape lorsque la valeur est analysée comme un appel planifié.
  • - prompt: définit le modèle de notification de la barrière d’approbation.
  • - policy: désigne une politique d’approval-broker dans [sop.approval].policies ; cette politique conditionne l’approbation selon l’appartenance aux groupes requis et le quorum. Une politique absente applique un refus par défaut plutôt que de lever le blocage après une seule approbation, tandis que son omission laisse le contrôle sans politique.
  • - edit: configure un point de contrôle pour modifier le champ nommé avant la reprise.
  • Les sous-puces non reconnues et les autres lignes de continuation non vides sont ajoutées au corps de l’étape.

Exemple de routage conditionnel copiable

Ce SOP.md complet achemine les alertes critiques vers une étape de remédiation approuvée, tout en journalisant les autres alertes sans remédiation :

# 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

Lorsque l’étape 1 produit {"severity":"critical"}, sa condition de garde est satisfaite et next passe à l’étape 3. Toute autre gravité passe à l’étape 2, dont le next explicite ignore la remédiation et rejoint le chemin critique à l’étape 4.

Le chargeur ne détecte qu’un répertoire contenant également un fichier SOP.toml ; associez donc les étapes ci-dessus à ce manifeste dans <sops_dir>/alert-triage/ :

[sop]
name = "alert-triage"
description = "Classer une alerte entrante, remédier aux alertes critiques et notifier l’opérateur."

[[triggers]]
type = "manual"

Exécutez ensuite zeroclaw sop validate alert-triage, qui indique que la SOP est valide.

Politiques [sop.approval] et acheminement de la livraison

Une politique peut également acheminer sa demande d’approbation hors bande vers un canal, afin qu’un approbateur puisse agir sans surveiller la surface à l’origine de l’exécution :

[sop.approval.policies.prod]
required_group = "release"
quorum = 2
# Envoyé lorsqu'une exécution SE MET EN ATTENTE à une porte gérée par cette politique.
request_route = "discord.ops:123456789012345678"
# Envoyé uniquement si cette porte EXPIRE ensuite (une seconde route distincte).
escalation_route = "discord.oncall:987654321098765432"

Les deux routes suivent le format channel:recipient : channel est la clé de la map d’un canal configuré (<channel>.<alias>, ou simplement <channel> pour un singleton) et recipient est le destinataire de ce canal (un identifiant de canal Discord, un identifiant de conversation, …). La livraison est de type best-effort et ne bloque jamais ni n’efface le gate — l’approbation elle-même revient toujours via une surface d’approbation/refus authentifiée dont le principal peut satisfaire les exigences de groupe et de quorum de la politique. Les routes ne se déclenchent que dans le daemon (là où les canaux sont configurés) ; laissez-les non définies (ou vides) pour notifier uniquement la surface d’origine, ce qui est le comportement par défaut.

La livraison des notifications ne dispose pas de file d’attente de nouvelle tentative durable. Si un démon se termine avant que l’envoi asynchrone ne soit terminé, ou en cas d’échec d’envoi sur le canal, la notification peut être perdue sans que la porte en attente ne soit modifiée. Les opérateurs peuvent inspecter les exécutions en attente avec zeroclaw sop pending et contacter un approbateur éligible via une surface d’approbation authentifiée.

Les groupes d’approbation qui accordent des approbateurs natifs au canal doivent utiliser la forme de membre qualifiée par canal channel:<channel-key>:<sender>, par exemple channel:discord.ops:123456789012345678. Les membres non délimités tels que channel:123 ou 123 seul ne correspondent pas aux approbations de canal, car les identifiants d’expéditeur peuvent se chevaucher entre les plateformes et les alias de canal.

Points de contrôle déterministes : approbation et reprise

Une exécution déterministe suspendue à une étape kind: checkpoint est résolue par les MÊMES interfaces d’approbation/refus qu’une barrière d’approbation (zeroclaw sop pending liste les deux, distingués par kind). En cas d’approbation, le moteur reprend l’exécution et pilote sans intervention les étapes kind: capability suivantes jusqu’à la prochaine pause ou l’achèvement — ainsi une queue checkpoint -> capability (par exemple la publication d’un brouillon approuvé) s’exécute sans tour d’agent en direct. En cas de refus, l’exécution est annulée. Les deux résolutions sont enregistrées dans le registre d’approbations. Une étape de checkpoint peut porter - policy: ; l’appartenance au groupe requis et le quorum de cette même politique s’appliquent avant que la décision de checkpoint ne soit résolue. Si cette politique nomme request_route, le démon y envoie l’avis de checkpoint hors bande. escalation_route reste la route de délai d’expiration pour les barrières d’approbation temporisées ; les pauses de checkpoint ne planifient pas actuellement de délai d’escalade spécifique au checkpoint.

Deux résolutions de point de contrôle supplémentaires permettent à un relecteur de façonner le brouillon au lieu de simplement le contrôler (toutes deux auditées dans le registre comme approve/deny) :

  • Modifier (amend) - activation facultative via une puce - edit: <field> sur le point de contrôle : l’approbateur peut remplacer ce champ de la valeur transmise par son propre texte avant la reprise de l’exécution (sur Discord, un bouton Modifier ouvre une fenêtre modale préremplie avec la valeur actuelle). La sortie enregistrée du point de contrôle contient le texte approuvé par l’humain ; l’étape précédente conserve l’original du modèle pour la piste d’audit. La ligne du registre enregistre decision: amend.
  • Réviser — proposé automatiquement lorsque le prédécesseur du point de contrôle est une étape llm.generate : l’approbateur envoie des directives, le moteur réexécute cette étape en présentant les directives comme des commentaires du réviseur (revision_feedback, transmis dans la couche de configuration statique de l’étape — l’encadrement de la charge utile non fiable reste inchangé), remplace le brouillon et réaffiche le point de validation. Chaque présentation du point de validation effectuée par l’exécution porte une révision unique (chaque révision l’incrémente, tout comme la première mise en attente de chaque point de contrôle ultérieur) ; les références d’invite deviennent <run_id>#<rev>, et toute réponse à une invite obsolète — un brouillon plus ancien ou les boutons restants d’un point de validation précédent — est refusée. Limité à 3 révisions par point de validation ; un nouvel essai de rédaction échoué maintient le brouillon précédent en attente et permet d’y répondre. Le registre consigne decision: revise, les directives servant de motif.

Capacités des adaptateurs injectés

Deux étapes kind: capability réalisent de véritables effets de bord via des adaptateurs que le daemon injecte lors de la construction du moteur ; sans daemon (validation CLI, tests), elles échouent de manière sécurisée avec un message clair, comme shell.exec :

  • llm.generate - un appel de modèle borné en tant qu’étape de pipeline (sans outils, sans boucle d’agent), sur le fournisseur de modèle résolu de l’agent par défaut. Champs définis dans with: - instruction (requis), system, output_key (par défaut text), echo (champs de charge utile copiés dans la sortie pour le chaînage en aval). La charge utile de l’événement chaînée est transmise à l’intérieur d’un cadre de contenu non fiable explicite et n’est jamais interprétée comme configuration.
  • forge.comment - publie un commentaire sur une issue/PR de forge git via le chemin sortant du canal git (indépendant du fournisseur : GitHub / Gitea / Forgejo). Champs d’entrée : repo (owner/repo), number, body, et channel facultatif (git.<alias> ; utilise par défaut l’unique canal git configuré).

Avec un point de contrôle, ils forment un pipeline de révision sans interface :

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

Où les adaptateurs sont raccordés. Les adaptateurs réels (le fournisseur de modèle de llm.generate, le canal git de forge.comment et la route d’approbation hors bande d’une politique de point de contrôle) ne sont injectés que sur le chemin daemon / channel-start, qui est le seul chemin disposant d’une carte de canaux configurée et d’un modèle de référence. Les exécutions d’agent autonomes et l’exécution de SOP via la CLI construisent le moteur sans eux ; ces capacités et routes y échouent donc en mode fermé : llm.generate / forge.comment signalent un échec clair “requires an injected adapter” au lieu d’agir, et l’avis de route d’un point de contrôle est une opération sans effet limitée au journal. Il s’agit du même modèle d’échec en mode fermé que shell.exec ; exécutez sous le daemon un pipeline qui a besoin de ces capacités.

Application des contrats d’étape

Les contrats d’étape sont optionnels. Lorsqu’ils sont présents, input et output acceptent un objet JSON compact avec les champs type, required, properties et items. Les types primitifs pris en charge sont object, array, string, number, integer, boolean et null.

La config [sop] contrôle l’application :

ChampPar défautEffet
step_schema_enforcetrueValider les schémas d’entrée/sortie déclarés des étapes aux frontières du moteur.
step_scope_enforcefalseTraiter les portées d’outils par étape comme des filtres imposés plutôt que comme des indications consultatives.
step_mandatory_tools["sop_advance", "sop_approve", "sop_status"]Conservez les outils de cycle de vie disponibles tant que l’application du périmètre est activée.
max_step_visits256Arrêter les exécutions routées qui revisitent une étape trop de fois.
max_step_retries2Limiter le nombre de tentatives de nouvelle exécution demandées par une politique de gestion des échecs d’étape.
untrusted_payload_max_bytes8192Limiter le texte des topics/payloads des triggers non fiables à une limite de caractère UTF-8 ; 0 désactive la limitation.
untrusted_input_guard"warn"Action Prompt-guard pour une entrée de déclencheur non fiable : warn, block ou sanitize.
untrusted_guard_sensitivity0.7Sensibilité utilisée par le filtrage prompt-guard et la rédaction sortante.
untrusted_frame_warningtrueInclure un texte d’avertissement explicatif dans le cadre de contenu non fiable. Les limites du cadre restent activées.
untrusted_outbound_redacttrueActiver le masquage sortant partagé pour les consommateurs de sécurité du contenu de SOP.
procedural_memory_enabledfalseEnregistrer l’outil sop_workshop pour la capture de propositions, la revue et l’écriture explicite de SOP.

L’application du schéma échoue de manière fermée : une entrée d’étape invalide empêche le démarrage de l’étape, et une sortie d’étape invalide est acheminée via la politique on_failure de l’étape. L’application du routage remplace l’avancement linéaire current_step + 1 dans les exécutions LLM et déterministes. L’application du périmètre des outils restreint les outils disponibles du tour d’étape en cours et bloque les appels hors périmètre lors du dispatch.

Le topic de déclenchement non fiable et le texte de payload sont plafonnés, normalisés, filtrés et encadrés avant d’atteindre le contexte de l’étape. L’encadrement est toujours activé ; le texte d’avertissement peut être masqué, mais le texte de déclenchement externe brut n’est pas interpolé dans le contexte du modèle.

La mémoire procédurale est en opt-in. Lorsqu’elle est activée, sop_workshop peut créer et inspecter des propositions SOP stockées, capturer le contexte d’une exécution terminée dans une procédure candidate, et appliquer une proposition approuvée à SOP.toml/SOP.md. L’écriture en retour n’a lieu que via l’action explicite apply.

Durabilité d’exécution

La configuration [sop] détermine également si l’état d’exécution est conservé après un redémarrage du démon :

ChampPar défautEffet
persist_runstruePersister l’état d’exécution - y compris les exécutions en attente d’une approbation HITL ou d’un point de contrôle déterministe - afin qu’elles survivent à un redémarrage. Définir false pour un moteur en mémoire uniquement, non durable.
run_store_backend"sqlite"Backend durable lorsque persist_runs vaut true. sqlite écrit runs.db dans le répertoire d’état des exécutions.

persist_runs = true est la valeur par défaut afin qu’une approbation HITL en attente ne soit pas perdue au redémarrage (build_sop_engine bascule sur un stockage en mémoire avec un journal explicite si le backend durable ne peut pas s’ouvrir, ce qui est donc sûr par défaut) ; persist_runs = false est l’option de désactivation documentée pour un moteur éphémère.

4. Types de déclencheurs

TypeChampsNotes
mqtttopic, condition optionnelArrivée du message MQTT. En direct : transmis par l’écouteur MQTT.
webhookpathRequête HTTP entrante. En production : routes de passerelle /sop/* et routes /webhook donnant la priorité au SOP.
cronexpressionDéclenchement basé sur le temps. En direct : distribué par le tick de maintenance SOP (chemins daemon / démarrage de canal).
peripheralboard, signal, condition optionnelleSignal matériel. Défini et apparié, mais aucun écouteur périphérique ne l’alimente.
filesystempath, optionnel condition, optionnel eventsFilesystem modification. Live : fourni par le surveillant de système de fichiers.
calendarcalendar_source, optionnel calendar_ids, optionnel conditionÉtat de l’événement de calendrier. Défini et correspondant, mais aucun poller ne l’alimente en temps réel.
channelchannel, optionnel alias, optionnel conditionMessage entrant ou événement forge/platform sur un canal configuré (telegram, discord, slack, git, …). Live : diffusé par l’orchestrateur de canal lorsque le dispatch SOP du canal est activé. Le producteur forge Git définit un sujet d’événement sous la forme <channel>.<alias>:<event_type> et place event_type dans la charge utile, afin qu’une condition définie filtre les événements forge par type sans nécessiter de seconde forme de déclencheur.
manualaucunExécution initiée par l’agent via l’outil sop_execute. Pas un fan-in externe.
amqprouting_key, optionnel conditionLivraison AMQP. En direct : livrée par le consommateur AMQP dans un mode de dispatch SOP.

Pour le statut live ou sans fil de chaque source et les détails du transport, reportez-vous à SOP Fan-In.

5. Syntaxe des conditions

Les champs condition des déclencheurs et les gardes when: des étapes utilisent la même grammaire d’expression. Les conditions de déclenchement sont évaluées par rapport à la charge utile de l’événement. Les gardes when: des étapes sont évaluées par rapport aux sorties accumulées des étapes terminées, selon cette forme :

{
  étapes: {
    "1": {
      "gravité": critique
    }
  }
}

L’évaluation échoue de manière sécurisée (fail-closed) pour les conditions non valides, les charges utiles manquantes, les chemins JSON non résolus et les comparaisons numériques directes dont la charge utile ou le comparateur n’est pas un nombre. Une condition vide correspond de manière inconditionnelle.

Formulaire de chemin JSON

Une condition commençant par $ compare une valeur à l’intérieur d’une charge utile JSON : $.path.to.field <op> <value>.

ExpressionCharge utileCorrespondances
$.value > 85{"value":90}oui
$.value >= 85{"value":85}oui
$.temp < 25{"temp":20}oui
$.temp <= 25{"temp":25}oui
$.status == "critical"{"status":"critical"}oui
$.status != "error"{"status":"ok"}oui
$.count == 42{"count":42}oui
$.data.sensor.value > 85{"data":{"sensor":{"value":87.3}}}oui
$.readings.1 == 20{"readings":[10,20,30]}oui
$.active == "true"{"active":true}oui
$.nonexistent > 0{"value":90}non

Je suis prêt à traduire. Veuillez me fournir la chaîne de documentation technique à traduire.

  • Utilisez des segments séparés par des points. Les éléments de tableau utilisent un segment numérique tel que $.readings.1 ; la syntaxe entre crochets n’est pas prise en charge.
  • Les clés manquantes, les index de tableau hors limites, le JSON non valide et les charges utiles vides échouent en mode fermé.
  • Il n’y a pas de caractères génériques, de filtres, de descente récursive ou de variables intégrées.

Forme numérique directe

Une condition sans $ initial compare la totalité du payload en tant que nombre. Cela est utile pour les payloads d’événements scalaires.

ExpressionCharge utileCorrespondances
> 01oui
> 00non
>= 56oui
< 10050oui
== 4242oui
!= 01oui
> 3.143.15oui
> 0not a numbernon

Opérateurs

Une comparaison utilise un opérateur. Le catalogue de création appartenant à la source est :

  • == : est
  • != : n’est pas
  • >: est supérieur à
  • >= : est supérieur ou égal à
  • < : est inférieur à
  • <= : est inférieur ou égal à

Le parseur reconnaît les jetons d’opérateur en commençant par les plus longs. Les comparaisons de chemins JSON tentent d’abord une comparaison numérique. Si les deux côtés peuvent être analysés comme des nombres, ils sont comparés numériquement ; sinon, les valeurs sont comparées sous forme de chaînes. Les guillemets doubles entourant la valeur comparée sont supprimés ; utilisez donc des littéraux de chaîne entre guillemets : $.status == "critical". Les conditions numériques directes sont exclusivement numériques : si l’un ou l’autre côté ne peut pas être analysé comme un nombre, aucune correspondance n’est trouvée.

L’évaluateur de conditions convertit les booléens JSON en chaînes true et false, donc comparez-les en tant que chaînes entre guillemets, par exemple $.active == "true".

Une condition est une comparaison unique. Les combinateurs logiques tels que AND, OR et NOT ne sont pas pris en charge.

6. Validation

Utiliser :

sh

zeroclaw sop validate
zeroclaw sop validate <name>

La validation émet des avertissements en cas de noms/descriptions vides, de déclencheurs manquants, d’étapes manquantes et de lacunes dans la numérotation des étapes.