{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://bewith.dev/schemas/policy.json",
  "title": "BeWith Policy",
  "description": "Schema for a single policy YAML file under /policies. The Policy Engine reads every file matching this schema and aggregates them at step 4 of the autonomous loop.",
  "type": "object",
  "required": ["id", "name", "description", "triggered_by", "risk"],
  "additionalProperties": false,
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$",
      "description": "kebab-case identifier — must match the filename without .yaml"
    },
    "name": {
      "type": "string",
      "minLength": 3,
      "description": "Human-readable label"
    },
    "description": {
      "type": "string",
      "minLength": 10,
      "description": "Multi-line explanation of when this policy fires and what it enforces"
    },
    "summary": {
      "type": "string",
      "minLength": 10,
      "description": "Single-line summary surfaced in the capability index (docs/capabilities.md). Pairs with the longer `description`."
    },
    "tags": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "string",
        "pattern": "^[a-z0-9][a-z0-9-]*$"
      },
      "description": "Tag vocabulary from scripts/build-capability-index.mjs (KNOWN_TAGS). Used to group the policy in the capability index."
    },
    "audience": {
      "type": "string",
      "enum": ["dev", "product", "both"],
      "description": "Which user role this policy is surfaced to in discovery (dev | product | both). See docs/methodology/artifact-types.md#frontmatter-conventions."
    },
    "triggered_by": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "oneOf": [
          {
            "required": ["file_change"],
            "additionalProperties": false,
            "properties": {
              "file_change": {
                "type": "string",
                "description": "Glob pattern matched against changed file paths"
              }
            }
          },
          {
            "required": ["event"],
            "additionalProperties": false,
            "properties": {
              "event": {
                "type": "string",
                "description": "Event name from events/vocabulary.md"
              }
            }
          },
          {
            "required": ["diff_size_gt"],
            "additionalProperties": false,
            "properties": {
              "diff_size_gt": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "files": {
                    "type": "integer",
                    "minimum": 1
                  }
                },
                "required": ["files"]
              }
            }
          }
        ]
      }
    },
    "risk": {
      "type": "object",
      "required": ["score", "blast_radius", "reason"],
      "additionalProperties": false,
      "properties": {
        "score": {
          "type": "integer",
          "minimum": 1,
          "maximum": 10
        },
        "blast_radius": {
          "type": "string",
          "enum": ["low", "medium", "high"]
        },
        "reason": {
          "type": "string",
          "minLength": 5
        }
      }
    },
    "required_agents": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[a-z0-9][a-z0-9-]*$",
        "description": "kebab-case name of an agent under .claude/agents/ (without .md)"
      }
    },
    "required_gates": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "description"],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9_]*$"
          },
          "description": {
            "type": "string",
            "minLength": 5
          }
        }
      }
    },
    "auto_workflows": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["on", "action"],
        "additionalProperties": false,
        "properties": {
          "on": {
            "type": "string",
            "description": "Condition expression evaluated by the Policy Engine"
          },
          "action": {
            "type": "string",
            "description": "Named action the Policy Engine knows how to execute"
          }
        }
      }
    },
    "human_approval_required": {
      "type": "array",
      "items": {
        "type": "object",
        "oneOf": [
          {
            "required": ["always"],
            "additionalProperties": false,
            "properties": {
              "always": { "const": true }
            }
          },
          {
            "required": ["hard_floor"],
            "additionalProperties": false,
            "properties": {
              "hard_floor": {
                "type": "string",
                "description": "Hard Floor item id from autonomy/defaults.yaml (cannot be disabled)"
              }
            }
          },
          {
            "required": ["condition"],
            "additionalProperties": false,
            "properties": {
              "condition": {
                "type": "string",
                "description": "Predicate evaluated against gate outputs (e.g. \"data_loss_detected\", \"risk.score >= 7\")"
              }
            }
          }
        ]
      }
    }
  }
}
