{
  "$defs": {
    "About": {
      "additionalProperties": false,
      "description": "The plain-language card of one catalog item.\n\nEvery field except the expert ones is required, so an About that validates is\nstructurally complete; :func:`about_issues` adds the editorial rules (one or two\nsentences, no jargon in the summary, known chooser tags, related ids that exist).",
      "examples": [
        {
          "assumptions": [
            "Numbers can be added up (spend, sales); averages are averaged"
          ],
          "avoid_when": [
            "Your data already has one row per week"
          ],
          "data_needs": [
            "A date column"
          ],
          "difficulty": "beginner",
          "example": "Daily TV spend of 100 each day becomes 700 for the week.",
          "fits": {
            "goal": [
              "check_data"
            ]
          },
          "outputs": [
            "The same columns, one row per week"
          ],
          "related": [
            "core.calendar"
          ],
          "summary_plain": "Adds up daily numbers into one number per week (or month), so that every row covers the same length of time.",
          "title": "Weekly totals",
          "typical_runtime": "instant",
          "use_when": [
            "Your data is daily but you want to plan or report by week"
          ]
        }
      ],
      "properties": {
        "assumptions": {
          "items": {
            "type": "string"
          },
          "maxItems": 10,
          "minItems": 1,
          "title": "Assumptions",
          "type": "array"
        },
        "avoid_when": {
          "items": {
            "type": "string"
          },
          "maxItems": 10,
          "minItems": 1,
          "title": "Avoid When",
          "type": "array"
        },
        "data_needs": {
          "items": {
            "type": "string"
          },
          "maxItems": 10,
          "minItems": 1,
          "title": "Data Needs",
          "type": "array"
        },
        "difficulty": {
          "$ref": "#/$defs/Difficulty"
        },
        "example": {
          "description": "A tiny example",
          "maxLength": 600,
          "minLength": 10,
          "title": "Example",
          "type": "string"
        },
        "expert_notes": {
          "anyOf": [
            {
              "maxLength": 4000,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Maths, estimator details, caveats for experts",
          "title": "Expert Notes"
        },
        "fits": {
          "additionalProperties": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "description": "Chooser tags: question id -> the answers this item suits",
          "maxProperties": 16,
          "title": "Fits",
          "type": "object"
        },
        "outputs": {
          "items": {
            "type": "string"
          },
          "maxItems": 10,
          "minItems": 1,
          "title": "Outputs",
          "type": "array"
        },
        "references": {
          "items": {
            "$ref": "#/$defs/AboutReference"
          },
          "maxItems": 10,
          "title": "References",
          "type": "array"
        },
        "related": {
          "description": "Ids of related catalog items (models, steps, nodes, checks, templates)",
          "items": {
            "type": "string"
          },
          "maxItems": 16,
          "title": "Related",
          "type": "array"
        },
        "summary_plain": {
          "description": "One or two sentences without jargon: what it does for you",
          "maxLength": 400,
          "minLength": 20,
          "title": "Summary Plain",
          "type": "string"
        },
        "title": {
          "description": "A human name",
          "maxLength": 80,
          "minLength": 3,
          "title": "Title",
          "type": "string"
        },
        "typical_runtime": {
          "$ref": "#/$defs/TypicalRuntime"
        },
        "use_when": {
          "items": {
            "type": "string"
          },
          "maxItems": 10,
          "minItems": 1,
          "title": "Use When",
          "type": "array"
        }
      },
      "required": [
        "title",
        "summary_plain",
        "use_when",
        "avoid_when",
        "data_needs",
        "assumptions",
        "outputs",
        "difficulty",
        "typical_runtime",
        "example"
      ],
      "title": "About",
      "type": "object"
    },
    "AboutReference": {
      "additionalProperties": false,
      "description": "A source for the expert detail (a paper, a book chapter, library documentation).",
      "properties": {
        "title": {
          "maxLength": 300,
          "minLength": 3,
          "title": "Title",
          "type": "string"
        },
        "url": {
          "anyOf": [
            {
              "maxLength": 500,
              "pattern": "^https://\\S+$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Url"
        }
      },
      "required": [
        "title"
      ],
      "title": "AboutReference",
      "type": "object"
    },
    "Capabilities": {
      "additionalProperties": false,
      "description": "What a model plugin can do (declared in its manifest).",
      "properties": {
        "calibration": {
          "default": [],
          "description": "Calibration data the model uses from a spec's calibration block (M3)",
          "items": {
            "enum": [
              "business_priors",
              "lift_tests"
            ],
            "type": "string"
          },
          "title": "Calibration",
          "type": "array",
          "uniqueItems": true
        },
        "checkpointable": {
          "default": false,
          "title": "Checkpointable",
          "type": "boolean"
        },
        "conditions_on_actuals": {
          "default": false,
          "description": "A forecast can be conditioned on actuals sent with the request (target values for periods after, or at the end of, the fitted history): the model updates its state with them without re-estimating its parameters and forecasts from the last actual (mapi_spec.actuals). Models without it refuse such requests with ACTUALS_NOT_SUPPORTED instead of ignoring the actuals",
          "title": "Conditions On Actuals",
          "type": "boolean"
        },
        "contribution_scale": {
          "default": "none",
          "enum": [
            "additive",
            "multiplicative",
            "none"
          ],
          "title": "Contribution Scale",
          "type": "string"
        },
        "decision": {
          "default": false,
          "title": "Decision",
          "type": "boolean"
        },
        "deterministic_given_seed": {
          "default": true,
          "title": "Deterministic Given Seed",
          "type": "boolean"
        },
        "evidence": {
          "default": false,
          "title": "Evidence",
          "type": "boolean"
        },
        "fast_score": {
          "default": false,
          "title": "Fast Score",
          "type": "boolean"
        },
        "identified_quantities": {
          "items": {
            "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
            "type": "string"
          },
          "title": "Identified Quantities",
          "type": "array"
        },
        "inference": {
          "enum": [
            "mcmc",
            "vi",
            "map",
            "smc",
            "kalman",
            "point",
            "bootstrap",
            "custom"
          ],
          "title": "Inference",
          "type": "string"
        },
        "input": {
          "default": "dataset",
          "description": "M4: 'tree' models also receive the whole tree dataset (the bound xr.DataTree) next to the flat pipeline output; 'dataset' models only the flat one. v0.15: 'collection' models implement fit_batches/score_batches and train on every image of an image collection through a lazy loader; they also read plain datasets",
          "enum": [
            "dataset",
            "tree",
            "collection"
          ],
          "title": "Input",
          "type": "string"
        },
        "loo_invalid_reason": {
          "anyOf": [
            {
              "maxLength": 500,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Loo Invalid Reason"
        },
        "loo_valid": {
          "default": true,
          "title": "Loo Valid",
          "type": "boolean"
        },
        "owns": {
          "default": [],
          "items": {
            "enum": [
              "scaling",
              "carryover",
              "inverse_units",
              "recursion"
            ],
            "type": "string"
          },
          "title": "Owns",
          "type": "array",
          "uniqueItems": true
        },
        "recommend": {
          "default": false,
          "title": "Recommend",
          "type": "boolean"
        },
        "representation": {
          "$ref": "#/$defs/Representation"
        },
        "score_modes": {
          "items": {
            "enum": [
              "predict",
              "forecast",
              "counterfactual",
              "simulate",
              "filter",
              "evaluate"
            ],
            "type": "string"
          },
          "minItems": 1,
          "title": "Score Modes",
          "type": "array",
          "uniqueItems": true
        }
      },
      "required": [
        "inference",
        "representation",
        "score_modes"
      ],
      "title": "Capabilities",
      "type": "object"
    },
    "DataSchemaTemplate": {
      "additionalProperties": false,
      "description": "A DataSchema-shaped JSON template plus the settings parameters it depends on.\n\nResolution is pure and static: ``resolve(settings)`` extracts each declared parameter\nfrom the settings (falling back to its default), checks its type/enum, renders the\n:mod:`~mapi_spec.template` placeholders, deep-merges every matching ``case`` and\nvalidates the result as a :class:`DataSchema`.",
      "properties": {
        "cases": {
          "items": {
            "$ref": "#/$defs/TemplateCase"
          },
          "maxItems": 64,
          "title": "Cases",
          "type": "array"
        },
        "params": {
          "additionalProperties": {
            "$ref": "#/$defs/TemplateParam"
          },
          "maxProperties": 64,
          "title": "Params",
          "type": "object"
        },
        "template": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "title": "Template",
          "type": "object"
        }
      },
      "required": [
        "template"
      ],
      "title": "DataSchemaTemplate",
      "type": "object"
    },
    "DerivedDecl": {
      "additionalProperties": false,
      "description": "A derived quantity (contributions, response curves, ...).",
      "properties": {
        "cache": {
          "default": "on_demand",
          "enum": [
            "fit",
            "on_demand"
          ],
          "title": "Cache",
          "type": "string"
        },
        "description": {
          "anyOf": [
            {
              "maxLength": 2000,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "dims": {
          "items": {
            "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
            "type": "string"
          },
          "title": "Dims",
          "type": "array"
        },
        "name": {
          "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
          "title": "Name",
          "type": "string"
        },
        "units": {
          "anyOf": [
            {
              "maxLength": 64,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Units"
        }
      },
      "required": [
        "name",
        "dims"
      ],
      "title": "DerivedDecl",
      "type": "object"
    },
    "Difficulty": {
      "description": "How much statistical background an item needs to use well.",
      "enum": [
        "beginner",
        "intermediate",
        "expert"
      ],
      "title": "Difficulty",
      "type": "string"
    },
    "GridDecl": {
      "additionalProperties": false,
      "description": "How to draw an output as a 2-D field (an image, a map, a vector field).\n\n``y`` and ``x`` are the dims of the raster rows and columns; ``y`` runs top to bottom\nunless ``origin`` is ``lower``. ``frame`` names a third dim with one raster per level\n(years, eras, times); ``component`` names a dim of length two that holds the ``(x, y)``\ncomponents of a vector field. Every other dim of the output is reduced over the\nposterior draws only, never over space.",
      "properties": {
        "colormap": {
          "default": "viridis",
          "enum": [
            "viridis",
            "magma",
            "cividis",
            "gray",
            "diverging"
          ],
          "title": "Colormap",
          "type": "string"
        },
        "component": {
          "anyOf": [
            {
              "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Component"
        },
        "frame": {
          "anyOf": [
            {
              "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Frame"
        },
        "log": {
          "default": false,
          "description": "Draw log10 of the value (for counts and intensities)",
          "title": "Log",
          "type": "boolean"
        },
        "origin": {
          "default": "upper",
          "enum": [
            "upper",
            "lower"
          ],
          "title": "Origin",
          "type": "string"
        },
        "x": {
          "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
          "title": "X",
          "type": "string"
        },
        "y": {
          "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
          "title": "Y",
          "type": "string"
        }
      },
      "required": [
        "y",
        "x"
      ],
      "title": "GridDecl",
      "type": "object"
    },
    "JsonValue": {},
    "ModelManifest": {
      "additionalProperties": false,
      "description": "Everything the control plane knows about a model plugin version (static JSON).",
      "properties": {
        "about": {
          "anyOf": [
            {
              "$ref": "#/$defs/About"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "M3.5: the plain-language About card (required by the catalog rule and the contract kit; optional here so older manifests still parse)"
        },
        "artifact_format": {
          "default": "zarr.zip/v1",
          "maxLength": 64,
          "title": "Artifact Format",
          "type": "string"
        },
        "capabilities": {
          "$ref": "#/$defs/Capabilities"
        },
        "derived": {
          "items": {
            "$ref": "#/$defs/DerivedDecl"
          },
          "title": "Derived",
          "type": "array"
        },
        "description": {
          "anyOf": [
            {
              "maxLength": 4000,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "family": {
          "anyOf": [
            {
              "pattern": "^[a-z][a-z0-9_]{0,31}$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "M3.5: the model family governance policies match (mmm, forecast, ts_multivariate, tabular, choice, regime); default: the id's namespace",
          "title": "Family"
        },
        "fit_schema": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "title": "Fit Schema",
          "type": "object"
        },
        "id": {
          "title": "Id",
          "type": "string"
        },
        "outputs": {
          "patternProperties": {
            "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$": {
              "$ref": "#/$defs/OutputDecl"
            }
          },
          "title": "Outputs",
          "type": "object"
        },
        "plots": {
          "items": {
            "type": "string"
          },
          "title": "Plots",
          "type": "array"
        },
        "resources": {
          "$ref": "#/$defs/ResourceHint"
        },
        "schema_template": {
          "$ref": "#/$defs/DataSchemaTemplate"
        },
        "settings_schema": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "title": "Settings Schema",
          "type": "object"
        },
        "side_table_params": {
          "description": "v0.15: settings keys whose value names a data.side_tables entry the model reads (pretrained weights, for example), like a step's side_table_params",
          "items": {
            "type": "string"
          },
          "maxItems": 8,
          "title": "Side Table Params",
          "type": "array"
        },
        "version": {
          "title": "Version",
          "type": "string"
        }
      },
      "required": [
        "id",
        "version",
        "capabilities",
        "schema_template"
      ],
      "title": "ModelManifest",
      "type": "object"
    },
    "OutputDecl": {
      "additionalProperties": false,
      "description": "An output variable the model writes (e.g. ``y_hat``).",
      "properties": {
        "circular": {
          "default": false,
          "description": "The output is an angle on a circle (a direction, a time of day). The model sets a 'period' attr (one turn, in the output's units) on the scored array; holdout metrics then use the circular mean and wrapped errors, and the score summaries of draws use the circular mean and intervals centred on it, wrapped into [0, period)",
          "title": "Circular",
          "type": "boolean"
        },
        "description": {
          "anyOf": [
            {
              "maxLength": 2000,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "dims": {
          "items": {
            "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
            "type": "string"
          },
          "title": "Dims",
          "type": "array"
        },
        "dims_of": {
          "anyOf": [
            {
              "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The output also carries every dim of this input variable (e.g. 'y' for models whose data dims come from settings, such as the sklearn row dims)",
          "title": "Dims Of"
        },
        "grid": {
          "anyOf": [
            {
              "$ref": "#/$defs/GridDecl"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Draw the output as a 2-D field (Model Explorer 'fields' section)"
        },
        "units": {
          "anyOf": [
            {
              "maxLength": 64,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Units"
        },
        "units_of": {
          "anyOf": [
            {
              "pattern": "^[A-Za-z_][A-Za-z0-9_.\\-]{0,127}$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Take units from this input variable",
          "title": "Units Of"
        }
      },
      "required": [
        "dims"
      ],
      "title": "OutputDecl",
      "type": "object"
    },
    "Representation": {
      "description": "How a model encodes uncertainty in its outputs.",
      "enum": [
        "draws",
        "quantiles",
        "interval",
        "point",
        "moments"
      ],
      "title": "Representation",
      "type": "string"
    },
    "ResourceClass": {
      "description": "Executor resource class. Ordered: ``S < M < L < XL < GPU``.\n\n``GPU`` is the last (highest-rank) member on purpose: a quota whose\n``max_resource_class`` is below it refuses it, and :meth:`next_up` never offers it.",
      "enum": [
        "S",
        "M",
        "L",
        "XL",
        "GPU"
      ],
      "title": "ResourceClass",
      "type": "string"
    },
    "ResourceHint": {
      "additionalProperties": false,
      "description": "Resource guidance for scheduling.",
      "properties": {
        "default_class": {
          "$ref": "#/$defs/ResourceClass",
          "default": "S"
        },
        "est_fit_seconds": {
          "anyOf": [
            {
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Est Fit Seconds"
        },
        "gpu": {
          "default": false,
          "title": "Gpu",
          "type": "boolean"
        },
        "min_class": {
          "$ref": "#/$defs/ResourceClass",
          "default": "S"
        }
      },
      "title": "ResourceHint",
      "type": "object"
    },
    "TemplateCase": {
      "additionalProperties": false,
      "description": "Conditional fragment merged into the template when all ``when`` params match.",
      "properties": {
        "merge": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "title": "Merge",
          "type": "object"
        },
        "when": {
          "additionalProperties": {
            "$ref": "#/$defs/JsonValue"
          },
          "minProperties": 1,
          "title": "When",
          "type": "object"
        }
      },
      "required": [
        "when",
        "merge"
      ],
      "title": "TemplateCase",
      "type": "object"
    },
    "TemplateParam": {
      "additionalProperties": false,
      "description": "A settings value that a :class:`DataSchemaTemplate` depends on.",
      "properties": {
        "default": {
          "$ref": "#/$defs/JsonValue",
          "default": null
        },
        "enum": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/JsonValue"
              },
              "maxItems": 256,
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Enum"
        },
        "path": {
          "anyOf": [
            {
              "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*$",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Dotted path into the settings (defaults to the parameter name)",
          "title": "Path"
        },
        "required": {
          "default": false,
          "title": "Required",
          "type": "boolean"
        },
        "type": {
          "enum": [
            "string",
            "integer",
            "number",
            "boolean",
            "string_list",
            "integer_list"
          ],
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "type"
      ],
      "title": "TemplateParam",
      "type": "object"
    },
    "TypicalRuntime": {
      "description": "Rough wall-clock time on typical data (``S`` resource class).",
      "enum": [
        "instant",
        "seconds",
        "minutes",
        "long"
      ],
      "title": "TypicalRuntime",
      "type": "string"
    }
  },
  "$id": "https://schemas.mapi.dev/v1/catalog-model.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false,
  "description": "A model plugin version: its manifest plus registry metadata.",
  "properties": {
    "base_image": {
      "anyOf": [
        {
          "maxLength": 256,
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "examples": [
        "base-bayes@2026.10"
      ],
      "title": "Base Image"
    },
    "manifest": {
      "$ref": "#/$defs/ModelManifest"
    },
    "overlay_hash": {
      "anyOf": [
        {
          "pattern": "^sha256:[0-9a-f]{64}$",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Overlay Hash"
    },
    "yanked": {
      "default": false,
      "title": "Yanked",
      "type": "boolean"
    }
  },
  "required": [
    "manifest"
  ],
  "title": "ModelCatalogEntry",
  "type": "object",
  "x-mapi-contract-version": "0.2"
}
