{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "rulewalk/schema/pipeline.schema.json",
  "title": "RuleWalk Pipeline IR v2",
  "description": "Intermediate Representation produced by RuleWalk. Uses step_type as a discriminator so each step kind carries only the fields that are meaningful for it.",
  "type": "object",
  "additionalProperties": false,
  "required": ["schema_version", "meta", "initial_dataset", "steps", "final_result"],

  "properties": {

    "schema_version": { "const": 2 },

    "meta": {
      "type": "object",
      "additionalProperties": false,
      "required": ["title", "source_type", "data_origin", "entity_schema"],
      "properties": {
        "title":       { "type": "string", "minLength": 1 },
        "description": { "type": "string" },
        "source_type": { "enum": ["doc", "code"] },
        "data_origin": { "enum": ["provided", "synthetic"] },
        "entity_schema": {
          "description": "Describes the shape of the INITIAL entity only. Fields added by transform/lookup steps are not reflected here; use each step's 'changes' field to track evolution.",
          "type": "object",
          "minProperties": 1,
          "additionalProperties": {
            "enum": ["string","number","integer","boolean","date","datetime","array","object","unknown"]
          }
        },
        "generated_at": { "type": "string", "format": "date-time" },
        "rule_source":  { "type": "string" }
      }
    },

    "sample_validation": {
      "description": "Present only when data_origin is 'provided'.",
      "type": "object",
      "additionalProperties": false,
      "required": ["fields_checked", "schema_matched"],
      "properties": {
        "fields_checked": { "type": "array", "minItems": 1, "items": { "type": "string" } },
        "schema_matched": { "type": "boolean" },
        "warnings":       { "type": "array", "items": { "type": "string" } }
      }
    },

    "initial_dataset": {
      "type": "object",
      "additionalProperties": false,
      "required": ["count", "sample"],
      "properties": {
        "count":  { "type": "integer", "minimum": 1 },
        "sample": { "type": "array", "minItems": 1, "items": { "type": "object" } },
        "note":   { "type": "string" }
      }
    },

    "steps": {
      "type": "array",
      "minItems": 1,
      "items": {
        "oneOf": [
          { "$ref": "#/$defs/step_filter" },
          { "$ref": "#/$defs/step_transform" },
          { "$ref": "#/$defs/step_group" },
          { "$ref": "#/$defs/step_lookup" },
          { "$ref": "#/$defs/step_action" }
        ]
      }
    },

    "final_result": {
      "description": "The dataset that represents the pipeline's outcome. When the last step is an 'action', result_from is required to point to the last data-producing step.",
      "type": "object",
      "additionalProperties": false,
      "required": ["count", "sample"],
      "properties": {
        "result_from": {
          "type": "string",
          "description": "Step id whose output_count/output_sample populates this field. Required when the last step is an action. Omit for data-producing last steps."
        },
        "count":  { "type": "integer", "minimum": 0 },
        "sample": { "type": "array", "items": { "type": "object" } }
      }
    }
  },

  "$defs": {

    "id": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },

    "step_filter": {
      "type": "object",
      "additionalProperties": false,
      "required": ["step_type","id","name","rule_text","input_count","output_count","passed_sample","rejected_sample"],
      "properties": {
        "step_type":       { "const": "filter" },
        "id":              { "$ref": "#/$defs/id" },
        "name":            { "type": "string", "minLength": 1 },
        "rule_text":       { "type": "string", "minLength": 1 },
        "condition_expr":  { "type": "string" },
        "input_count":     { "type": "integer", "minimum": 0 },
        "output_count":    { "type": "integer", "minimum": 0 },
        "passed_sample":   { "type": "array", "items": { "type": "object" } },
        "rejected_sample": { "type": "array", "items": { "$ref": "#/$defs/rejected_record" } },
        "confidence": {
          "enum": ["confirmed", "assumed", "approximated"],
          "description": "How directly this step's rule was extracted from the source. Default when absent: 'confirmed'."
        },
        "confidence_note": {
          "type": "string",
          "description": "Required when confidence is not 'confirmed'. Explains what is uncertain and why."
        }
      }
    },

    "step_transform": {
      "type": "object",
      "additionalProperties": false,
      "required": ["step_type","id","name","rule_text","input_count","output_count","output_sample"],
      "properties": {
        "step_type":      { "const": "transform" },
        "id":             { "$ref": "#/$defs/id" },
        "name":           { "type": "string", "minLength": 1 },
        "rule_text":      { "type": "string", "minLength": 1 },
        "condition_expr": { "type": "string" },
        "input_count":    { "type": "integer", "minimum": 0 },
        "output_count":   { "type": "integer", "minimum": 0 },
        "output_sample":  { "type": "array", "items": { "type": "object" } },
        "changes": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Human-readable list of fields added or modified, e.g. [\"lead_score added\"]."
        },
        "confidence": {
          "enum": ["confirmed", "assumed", "approximated"],
          "description": "How directly this step's rule was extracted from the source. Default when absent: 'confirmed'."
        },
        "confidence_note": {
          "type": "string",
          "description": "Required when confidence is not 'confirmed'. Explains what is uncertain and why."
        }
      }
    },

    "step_group": {
      "type": "object",
      "additionalProperties": false,
      "required": ["step_type","id","name","rule_text","group_by","output_unit","input_count","output_count","output_sample"],
      "properties": {
        "step_type":    { "const": "group" },
        "id":           { "$ref": "#/$defs/id" },
        "name":         { "type": "string", "minLength": 1 },
        "rule_text":    { "type": "string", "minLength": 1 },
        "condition_expr": { "type": "string" },
        "group_by": {
          "type": "string",
          "minLength": 1,
          "description": "The field name used as the grouping key."
        },
        "output_unit": {
          "type": "string",
          "minLength": 1,
          "description": "Human-readable label for what output_count now counts, e.g. 'groups by region'. Signals a unit boundary: the validator will enforce numeric chain continuity but will NOT cross-reference individual records across this step."
        },
        "input_count":   { "type": "integer", "minimum": 0 },
        "output_count":  { "type": "integer", "minimum": 0 },
        "output_sample": { "type": "array", "items": { "type": "object" } },
        "confidence": {
          "enum": ["confirmed", "assumed", "approximated"],
          "description": "How directly this step's rule was extracted from the source. Default when absent: 'confirmed'."
        },
        "confidence_note": {
          "type": "string",
          "description": "Required when confidence is not 'confirmed'. Explains what is uncertain and why."
        }
      }
    },

    "step_lookup": {
      "type": "object",
      "additionalProperties": false,
      "required": ["step_type","id","name","rule_text","lookup_source","input_count","output_count","output_sample"],
      "properties": {
        "step_type":      { "const": "lookup" },
        "id":             { "$ref": "#/$defs/id" },
        "name":           { "type": "string", "minLength": 1 },
        "rule_text":      { "type": "string", "minLength": 1 },
        "condition_expr": { "type": "string" },
        "lookup_source": {
          "type": "string",
          "minLength": 1,
          "description": "Description of the external table or data source joined here, e.g. 'território_vendas — mapeamento região → vendedor'."
        },
        "lookup_key": {
          "type": "string",
          "description": "The field used as the join key."
        },
        "input_count":   { "type": "integer", "minimum": 0 },
        "output_count":  { "type": "integer", "minimum": 0 },
        "output_sample": { "type": "array", "items": { "type": "object" } },
        "changes": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Fields added from the lookup source, e.g. [\"vendedor added\", \"email_vendedor added\"]."
        },
        "confidence": {
          "enum": ["confirmed", "assumed", "approximated"],
          "description": "How directly this step's rule was extracted from the source. Default when absent: 'confirmed'."
        },
        "confidence_note": {
          "type": "string",
          "description": "Required when confidence is not 'confirmed'. Explains what is uncertain and why."
        }
      }
    },

    "step_action": {
      "type": "object",
      "additionalProperties": false,
      "required": ["step_type","id","name","rule_text","effects"],
      "properties": {
        "step_type":      { "const": "action" },
        "id":             { "$ref": "#/$defs/id" },
        "name":           { "type": "string", "minLength": 1 },
        "rule_text":      { "type": "string", "minLength": 1 },
        "condition_expr": { "type": "string" },
        "trigger_count": {
          "type": "integer",
          "minimum": 0,
          "description": "How many items triggered this action. Validated against the previous data step's output_count."
        },
        "effects": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/effect" }
        },
        "confidence": {
          "enum": ["confirmed", "assumed", "approximated"],
          "description": "How directly this step's rule was extracted from the source. Default when absent: 'confirmed'."
        },
        "confidence_note": {
          "type": "string",
          "description": "Required when confidence is not 'confirmed'. Explains what is uncertain and why."
        }
      }
    },

    "rejected_record": {
      "type": "object",
      "additionalProperties": false,
      "required": ["record", "reason"],
      "properties": {
        "record": { "type": "object" },
        "reason": { "type": "string", "minLength": 1 }
      }
    },

    "effect": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "description"],
      "properties": {
        "type":        { "type": "string", "minLength": 1,
                         "description": "Effect kind: 'email', 'webhook', 'notification', 'database-write', etc." },
        "description": { "type": "string", "minLength": 1 },
        "count":       { "type": "integer", "minimum": 0 }
      }
    }
  }
}
