{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://statewright.ai/workflow-schema.json",
  "title": "Statewright Workflow Definition",
  "description": "State machine workflow definition for AI agent guardrails. Compatible with XState patterns.",
  "type": "object",
  "required": ["id", "initial", "states"],
  "properties": {
    "id": { "type": "string", "description": "Unique workflow identifier" },
    "initial": { "type": "string", "description": "Name of the initial state" },
    "context": { "type": "object", "description": "Initial context values for guard evaluation", "additionalProperties": true },
    "states": {
      "type": "object",
      "description": "State definitions keyed by state name",
      "additionalProperties": { "$ref": "#/$defs/StateDef" }
    },
    "guards": {
      "type": "object",
      "description": "Named guard predicates for conditional transitions",
      "additionalProperties": { "$ref": "#/$defs/GuardDef" }
    }
  },
  "$defs": {
    "StateDef": {
      "type": "object",
      "properties": {
        "type": { "type": "string", "enum": ["final"], "description": "Set to 'final' for terminal states" },
        "allowed_tools": { "type": "array", "items": { "type": "string" }, "description": "Tools the agent can use in this state (e.g. Read, Edit, Bash)" },
        "instructions": { "type": "string", "description": "Natural language instructions for the agent in this state" },
        "max_iterations": { "type": "integer", "minimum": 1, "description": "Maximum tool calls before forcing a transition" },
        "safe_next": { "type": "string", "description": "Fallback state for unrecognized transition events" },
        "max_edit_lines": { "type": "integer", "minimum": 1, "description": "Maximum lines per edit operation" },
        "max_files_per_state": { "type": "integer", "minimum": 1, "description": "Maximum files that can be edited in this state" },
        "allowed_commands": { "type": "array", "items": { "type": "string" }, "description": "Allowed shell command prefixes (e.g. pytest, npm test)" },
        "blocked_env": { "type": "array", "items": { "type": "string" }, "description": "Environment variables denied in Bash commands. Alias: deny_env" },
        "env_overrides": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Environment variable overrides injected as context. Alias: env" },
        "context_budget_bytes": { "type": "integer", "description": "Maximum accumulated tool result bytes in this state" },
        "on": {
          "type": "object",
          "description": "Transition events keyed by event name",
          "additionalProperties": { "$ref": "#/$defs/TransitionDef" }
        }
      }
    },
    "TransitionDef": {
      "oneOf": [
        { "type": "string", "description": "Simple transition: target state name" },
        {
          "type": "object",
          "description": "Guarded transition with optional approval gate",
          "required": ["target"],
          "properties": {
            "target": { "type": "string" },
            "guard": { "type": "string", "description": "Single guard name to evaluate" },
            "guards": { "type": "array", "items": { "type": "string" }, "description": "Multiple guard names (all must pass)" },
            "requires_approval": { "type": "boolean", "description": "Pause for human approval before transitioning" },
            "approval_message": { "type": "string" }
          }
        },
        {
          "type": "array",
          "description": "Conditional branches (XState pattern): array of guarded transitions, first matching guard wins",
          "items": {
            "type": "object",
            "required": ["target"],
            "properties": {
              "target": { "type": "string" },
              "guard": { "type": "string", "description": "Guard name to evaluate against context" },
              "guards": { "type": "array", "items": { "type": "string" } }
            }
          }
        },
        {
          "type": "object",
          "description": "Invoke a sub-machine",
          "required": ["invoke", "on_complete"],
          "properties": {
            "invoke": { "type": "string", "description": "Sub-machine definition to invoke" },
            "on_complete": { "type": "string", "description": "State to transition to on success" },
            "on_fail": { "type": "string", "description": "State to transition to on failure" },
            "input": { "type": "object", "description": "Input data for the sub-machine" }
          }
        }
      ]
    },
    "GuardDef": {
      "type": "object",
      "required": ["field", "op"],
      "description": "Declarative predicate evaluated against workflow context",
      "properties": {
        "field": { "type": "string", "description": "Context field to check" },
        "op": { "type": "string", "enum": ["eq", "neq", "gt", "gte", "lt", "lte", "in", "contains", "exists", "not_exists"], "description": "Comparison operator" },
        "value": { "description": "Value to compare against (type depends on operator)" }
      }
    }
  }
}
