version: 1
rules:
  - id: battery_before_movement
    description: Any NAVIGATE action must be preceded by CHECK_BATTERY.
    severity: CRITICAL
    condition: |
      for every step S where S.action == "NAVIGATE":
        exists step B where B.action == "CHECK_BATTERY" and path_exists(B, S)

  - id: human_proximity_before_speed
    description: High-speed navigation requires a human proximity scan.
    severity: CRITICAL
    condition: |
      for every step S where S.action == "NAVIGATE" and S.params.speed == "fast":
        exists step H where H.action == "SCAN_AREA" and H.params.target == "humans" and path_exists(H, S)

  - id: no_orphan_nodes
    description: All steps must be reachable from the entry steps.
    severity: CRITICAL
    condition: |
      for every step S in plan.steps:
        S is reachable from at least one entry step

  - id: no_cycles
    description: Plan must be a valid DAG (no cycles).
    severity: CRITICAL
    condition: |
      topological_sort(plan.steps, plan.dependencies) does not fail

  - id: abort_path_exists
    description: Conditional branches must have a defined failure path.
    severity: HIGH
    condition: |
      for every conditional branch from a step:
        a sibling branch exists with a different condition

  - id: max_plan_depth
    description: Plan depth cannot exceed 20 steps.
    severity: HIGH
    condition: |
      longest_path_length(plan) <= 20
