{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://polymorphism.com.br/morph-spec/schemas/ai-pin.schema.json",
  "title": "morph-spec AI package pin",
  "description": "Shape of framework/ai-pin.json — the single source of truth for the AI package versions the framework commits to. Written by a human after checking api.nuget.org; read by scripts/generate-ai-pin-props.js (Central Package Management + global.json) and by src/lib/standards/verified-against.js (age of ai-agents standards against pinnedAt). Every version is exact SemVer: a range here would restore floating versions in the generated .props, which is the defect this file exists to remove.",
  "type": "object",
  "required": ["pinnedAt", "source", "targetFramework", "sdk", "packages", "toolchain"],
  "additionalProperties": false,
  "properties": {
    "$schema": {
      "type": "string",
      "description": "Relative path to this schema, so an editor validates the pin while it is edited."
    },
    "pinnedAt": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      "description": "ISO date on which a human checked these versions against the registry. It is the anchor of the ai-agents freshness window — NOT derived from `published`: `published` is a registry fact, `pinnedAt` is the framework's commitment. A date in the future is a pin error, never a fresh standard."
    },
    "source": {
      "type": "string",
      "pattern": "^https://",
      "description": "The registry endpoint the versions were read from, so the check is reproducible."
    },
    "targetFramework": {
      "type": "string",
      "pattern": "^net\\d+\\.\\d+$",
      "description": "TFM the kit compiles against — the TFM the pinned Microsoft.Agents.AI declares."
    },
    "sdk": {
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+$",
      "description": "SDK band written into the kit's global.json and read by actions/setup-dotnet."
    },
    "packages": {
      "type": "object",
      "description": "The AI packages the framework commits to. The SET is closed HERE, by `required` plus `maxProperties` — issue #92 pinned five, and issue #97 added the three Evaluation packages that make `verify` able to run evals from a committed response cache. `patternProperties` still carries the per-entry SHAPE, because JSON Schema cannot name a closed set of keys and repeat their shape without writing it once per key; test/framework/ai-pin.test.js reads THIS `required` list rather than a literal of its own, so the pin and its ruler can never name different sets.",
      "required": [
        "Microsoft.Agents.AI",
        "Microsoft.Extensions.AI",
        "OpenAI",
        "Google.GenAI",
        "ModelContextProtocol",
        "Microsoft.Extensions.AI.Evaluation",
        "Microsoft.Extensions.AI.Evaluation.Quality",
        "Microsoft.Extensions.AI.Evaluation.Reporting"
      ],
      "minProperties": 8,
      "maxProperties": 8,
      "additionalProperties": false,
      "patternProperties": {
        "^[A-Za-z0-9_.-]+$": {
          "type": "object",
          "required": ["version", "published", "role"],
          "additionalProperties": false,
          "properties": {
            "version": {
              "type": "string",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "description": "Exact SemVer. No range, no wildcard, no floating version."
            },
            "published": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "description": "ISO publication date of that exact version in the registry."
            },
            "role": {
              "type": "string",
              "pattern": "^[a-z0-9-]+$",
              "description": "Human-readable label (maf-core, provider, mcp, ...). Documentation, not code semantics."
            }
          }
        }
      }
    },
    "toolchain": {
      "type": "object",
      "description": "Build/test packages. They live in the SAME file because the generator writes a single Directory.Packages.props; splitting them would produce two version files and the very second-truth problem the pin removes.",
      "minProperties": 3,
      "maxProperties": 3,
      "additionalProperties": false,
      "patternProperties": {
        "^[A-Za-z0-9_.-]+$": {
          "type": "object",
          "required": ["version"],
          "additionalProperties": false,
          "properties": {
            "version": {
              "type": "string",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "description": "Exact SemVer, same rule as `packages`."
            }
          }
        }
      }
    }
  }
}
