{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://usecalculator.app/specs/calculator.schema.json",
  "title": "UseCalculator UCALC/1 calculator definition",
  "description": "Structural contract. Runtime semantic validation additionally checks formula grammar, units, identifiers, bounds, arithmetic budgets, and expected-answer checks. This schema is not a certification of business or legal correctness.",
  "type": "object",
  "additionalProperties": false,
  "required": ["schemaVersion", "language", "id", "revision", "title", "description", "currency", "inputs", "output", "assumptions", "fixtures", "provenance", "review"],
  "properties": {
    "$schema": { "const": "https://usecalculator.app/specs/calculator.schema.json" },
    "schemaVersion": { "const": "1.0" },
    "language": { "const": "ucalc-1" },
    "id": { "type": "string", "pattern": "^[a-z][a-z0-9-]{0,63}$" },
    "revision": { "type": "integer", "minimum": 1 },
    "title": { "type": "string", "minLength": 1, "maxLength": 100 },
    "description": { "type": "string", "maxLength": 400 },
    "currency": { "type": "string", "pattern": "^[A-Z]{3}$", "description": "A single currency label for all monetary values. No exchange conversion is implied." },
    "inputs": { "type": "array", "minItems": 1, "maxItems": 12, "items": { "$ref": "#/$defs/input" } },
    "output": { "$ref": "#/$defs/output" },
    "assumptions": { "type": "array", "maxItems": 12, "items": { "type": "string", "minLength": 1, "maxLength": 500 } },
    "fixtures": { "type": "array", "maxItems": 20, "items": { "$ref": "#/$defs/fixture" } },
    "provenance": {
      "type": "object", "additionalProperties": false,
      "required": ["method", "createdAt"],
      "properties": {
        "method": { "enum": ["guided-template", "explicit-formula", "manual", "model-proposal"] },
        "templateId": { "type": "string", "maxLength": 80 },
        "prompt": { "type": "string", "maxLength": 3000 },
        "createdAt": { "type": "string", "format": "date-time", "maxLength": 40 }
      }
    },
    "review": {
      "oneOf": [
        { "type": "object", "additionalProperties": false, "required": ["status"], "properties": { "status": { "const": "draft" } } },
        {
          "type": "object", "additionalProperties": false,
          "required": ["status", "signature", "checkedAt", "checklist"],
          "properties": {
            "status": { "const": "personal-reviewed" },
            "signature": { "type": "string", "description": "Deterministic serialized-definition comparison fingerprint. NOT a cryptographic signature, access permission, or independent certification." },
            "checkedAt": { "type": "string", "format": "date-time" },
            "checklist": { "const": true }
          }
        }
      ]
    }
  },
  "$defs": {
    "decimal": { "type": ["string", "number"], "description": "Runtime requires a plain signed decimal with up to 30 integer and 18 fractional digits. Exponent notation, localized grouping, NaN and infinity are rejected." },
    "kind": { "enum": ["number", "percent", "count", "money", "money_per_item", "hours", "money_per_hour", "length", "area", "volume"] },
    "input": {
      "type": "object", "additionalProperties": false,
      "required": ["key", "label", "kind", "default", "min", "max"],
      "properties": {
        "key": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,31}$", "not": { "enum": ["constructor", "prototype", "__proto__", "min", "max", "abs", "infinity", "nan"] } },
        "label": { "type": "string", "minLength": 1, "maxLength": 100 },
        "kind": { "$ref": "#/$defs/kind" },
        "integer": { "type": "boolean", "description": "When true, this input accepts whole numbers only. The constraint is independent of its unit, including count. Omitted is equivalent to false; nonboolean values are rejected." },
        "default": { "$ref": "#/$defs/decimal" },
        "min": { "$ref": "#/$defs/decimal" },
        "max": { "$ref": "#/$defs/decimal" }
      }
    },
    "output": {
      "type": "object", "additionalProperties": false,
      "required": ["label", "expression", "kind", "decimals", "rounding"],
      "properties": {
        "label": { "type": "string", "minLength": 1, "maxLength": 100 },
        "expression": { "type": "string", "minLength": 1, "maxLength": 2000 },
        "kind": { "$ref": "#/$defs/kind" },
        "decimals": { "type": "integer", "minimum": 0, "maximum": 12 },
        "rounding": { "enum": ["half-even", "half-up"] }
      }
    },
    "fixture": {
      "type": "object", "additionalProperties": false,
      "required": ["name", "inputs", "expected"],
      "properties": {
        "name": { "type": "string", "minLength": 1, "maxLength": 100 },
        "inputs": { "type": "object", "minProperties": 1, "maxProperties": 12, "additionalProperties": { "$ref": "#/$defs/decimal" } },
        "expected": { "$ref": "#/$defs/decimal" }
      }
    }
  }
}
