{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://davit.ie/schemas/mx/manifest/0.2.0.json",
  "title": "mx manifest 0.2.0",
  "description": "The manifest.json contract, edition 0.2: one package's identity, placement, capabilities and artifacts. Written by `manifest`; read by package-manager and the other readers listed in the Data Dictionary §8. Interim: written by hand from manifest's Data Dictionary 0.2.2 (2026-10-26); replaced at this URL by the davit_registry export (artifact-inspector TS 21).",
  "type": "object",
  "x-davit": {
    "family": "manifest",
    "edition": "0.2",
    "revision": "0.2.0",
    "status": "interim",
    "owner": "artifact-inspector",
    "writer": "manifest",
    "source": "manifest/docs/Data-Dictionary.md 0.2.2 (2026-10-26), §1, §2.1, §2.2, §2.4, §2.5, §3.1, §3.2, §4",
    "breaking": "For files and validators: a 0.1 file is not a valid 0.2 file (project_* keys renamed to package_*). Readers of .artifacts[] are unaffected.",
    "key_order": {
      "first": "version",
      "second": "$schema",
      "note": "JSON Schema cannot express key order; a checker enforces it. `version` is the first key; `$schema`, when present, is the second."
    },
    "invariants": [
      "first key is `version`; `$schema`, when present, is second",
      "`version` is the file's own version, owned by manifest, never above `package_version`; it is neither the schema's nor the tool's version",
      "a 0.2 file never carries both spellings of a renamed key (project_* and package_*)",
      "`entrypoint` resolves to exactly one artifact with role `entry`",
      "an artifact's id key is named after its `id_type` (script-id -> script_id) and survives a rename",
      "`binary` equals the stem of `name`",
      "`created_on` is written once; `last_update` and each artifact's `last_updated` follow every change"
    ],
    "open": [
      "package_status: the closed enum and its pipeline meaning are AISP's to publish (Data Dictionary Q4); this edition accepts the four values written today",
      "placement.category: free text until AISP publishes the category vocabulary (Q6)",
      "capabilities.provides[].capability, .contract and uses[]: names must be known contracts; no vocabulary is published yet (ex-TS 68)",
      "capabilities.provides[].contract uses a version syntax (`pkg>=1.0`) that is not defined yet"
    ],
    "supersedes_draft": "manifest/archives/manifest-0.6.0/schemas/mx/manifest/0.2.0.json (0.6.0 proposal; not published)"
  },
  "required": [
    "version",
    "package_name",
    "description",
    "domain",
    "created_on",
    "last_update",
    "package_version",
    "package_status",
    "author",
    "artifact_id",
    "package_id",
    "artifacts"
  ],
  "properties": {
    "version": {
      "$ref": "#/$defs/semver",
      "description": "The file's own version: first key; owned by manifest; never above package_version."
    },
    "$schema": {
      "type": "string",
      "pattern": "^https://davit\\.ie/schemas/mx/manifest/0\\.2\\.[0-9]+\\.json$",
      "description": "The schema this file follows; second key, after version."
    },
    "package_name": {
      "type": "string",
      "pattern": "^[a-z0-9-]{2,64}$",
      "description": "Kebab-case package name (was project_name)."
    },
    "description": {
      "type": "string",
      "minLength": 1,
      "maxLength": 120,
      "description": "Sentence case, at most 120 characters."
    },
    "domain": {
      "type": "string",
      "minLength": 1,
      "description": "Default `davit`."
    },
    "created_on": {
      "$ref": "#/$defs/datetime",
      "description": "Written once, by init."
    },
    "last_update": {
      "$ref": "#/$defs/datetime",
      "description": "Every write."
    },
    "package_version": {
      "$ref": "#/$defs/semver",
      "description": "The package version (was project_version); manifest never changes it."
    },
    "package_status": {
      "enum": [
        "development",
        "staging",
        "production",
        "archived"
      ],
      "description": "Package status (was project_status). The four values written today; the closed enum is open (Q4)."
    },
    "author": {
      "type": "string",
      "minLength": 1,
      "not": {
        "const": "USER"
      },
      "description": "A resolved identity; the literal USER is invalid."
    },
    "artifact_id": {
      "$ref": "#/$defs/uuid",
      "description": "Primary key of the package, issued by package-manager; never changes."
    },
    "package_id": {
      "type": "string",
      "pattern": "^[0-9]{4}$",
      "not": {
        "enum": [
          "0000",
          "9999"
        ]
      },
      "description": "Four digits from package-manager, 0001–9998; 0000 and 9999 are reserved."
    },
    "entrypoint": {
      "$ref": "#/$defs/uuid",
      "description": "The id of the main `entry` artifact; required when the package has an entry."
    },
    "placement": {
      "$ref": "#/$defs/placement"
    },
    "capabilities": {
      "$ref": "#/$defs/capabilities"
    },
    "tests": {
      "type": "boolean",
      "description": "Tests policy of upgrade.md (from 0.1)."
    },
    "test_result": {
      "enum": [
        "PASS",
        "FAIL",
        "NONE"
      ],
      "description": "Tests policy of upgrade.md (from 0.1)."
    },
    "artifacts": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/artifact"
      }
    },
    "project_name": false,
    "project_version": false,
    "project_status": false,
    "manifest_style": false,
    "authority": false,
    "total_artifacts": false,
    "remote_url": false
  },
  "additionalProperties": true,
  "allOf": [
    {
      "description": "A package with an `entry` artifact names it in `entrypoint`.",
      "if": {
        "required": [
          "artifacts"
        ],
        "properties": {
          "artifacts": {
            "contains": {
              "required": [
                "role"
              ],
              "properties": {
                "role": {
                  "const": "entry"
                }
              }
            }
          }
        }
      },
      "then": {
        "required": [
          "entrypoint"
        ]
      }
    },
    {
      "description": "Plane os: placement.order, capabilities.context, and provides or uses.",
      "if": {
        "required": [
          "placement"
        ],
        "properties": {
          "placement": {
            "required": [
              "plane"
            ],
            "properties": {
              "plane": {
                "const": "os"
              }
            }
          }
        }
      },
      "then": {
        "required": [
          "capabilities"
        ],
        "properties": {
          "placement": {
            "required": [
              "order"
            ]
          },
          "capabilities": {
            "required": [
              "context"
            ],
            "anyOf": [
              {
                "required": [
                  "provides"
                ]
              },
              {
                "required": [
                  "uses"
                ]
              }
            ]
          }
        }
      }
    },
    {
      "description": "Plane workbench: capabilities.uses.",
      "if": {
        "required": [
          "placement"
        ],
        "properties": {
          "placement": {
            "required": [
              "plane"
            ],
            "properties": {
              "plane": {
                "const": "workbench"
              }
            }
          }
        }
      },
      "then": {
        "required": [
          "capabilities"
        ],
        "properties": {
          "capabilities": {
            "required": [
              "uses"
            ]
          }
        }
      }
    }
  ],
  "$defs": {
    "semver": {
      "type": "string",
      "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$",
      "description": "Bare MAJOR.MINOR.PATCH, never v-prefixed."
    },
    "datetime": {
      "type": "string",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$",
      "description": "ISO 8601 UTC with a trailing Z."
    },
    "uuid": {
      "type": "string",
      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
    },
    "placement": {
      "type": "object",
      "required": [
        "plane"
      ],
      "properties": {
        "plane": {
          "enum": [
            "os",
            "workbench",
            "authoring",
            "lab",
            "archive"
          ]
        },
        "order": {
          "enum": [
            "1st",
            "2nd",
            "none"
          ],
          "description": "Omitted = none. 1st: uninstall breaks DAVIT-OS; 2nd: uninstall drops colour; none: lab."
        },
        "category": {
          "type": "string",
          "minLength": 1,
          "description": "Free text until AISP publishes the category vocabulary (Q6)."
        },
        "development_path": {
          "type": "string",
          "description": "Relative to DEV_DIR; never a second source of package_name."
        },
        "runtime_path": {
          "type": "string",
          "description": "Where install deploys it, under DOMAIN_ROOT."
        }
      },
      "additionalProperties": false
    },
    "capabilities": {
      "type": "object",
      "properties": {
        "context": {
          "enum": [
            "todo",
            "state",
            "session",
            "script-index",
            "pkg",
            "parse",
            "manifest",
            "log",
            "inspect-artifact",
            "versioning",
            "env",
            "dispatch",
            "changelog",
            "archive"
          ],
          "description": "One context per package (Q11)."
        },
        "provides": {
          "type": "array",
          "description": "Only what other packages may dispatch.",
          "items": {
            "type": "object",
            "required": [
              "capability"
            ],
            "properties": {
              "capability": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9-]*$"
              },
              "rank": {
                "type": "integer"
              },
              "contract": {
                "type": "string",
                "minLength": 1
              }
            },
            "additionalProperties": false
          }
        },
        "uses": {
          "type": "array",
          "description": "Contract names, never package names.",
          "items": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9-]*$"
          }
        },
        "fallback_ok": {
          "type": "boolean",
          "description": "True on 2nd-order providers, false on 1st-order contracts."
        }
      },
      "additionalProperties": false
    },
    "artifact": {
      "type": "object",
      "required": [
        "name",
        "path",
        "type",
        "id_type",
        "version",
        "desc_short",
        "last_updated",
        "status",
        "last_issue"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "description": "The file's base name, with extension."
        },
        "path": {
          "type": "string",
          "description": "The file's directory from the package root, e.g. src/bin."
        },
        "binary": {
          "type": "string",
          "minLength": 1,
          "description": "src/bin/ only; equals the stem of name."
        },
        "type": {
          "type": "string",
          "minLength": 1,
          "description": "The format (bash, markdown, json, troff, …), not the role."
        },
        "id_type": {
          "enum": [
            "script-id",
            "docid",
            "schema-id",
            "artifact-id"
          ]
        },
        "script_id": {
          "$ref": "#/$defs/uuid"
        },
        "docid": {
          "$ref": "#/$defs/uuid"
        },
        "schema_id": {
          "$ref": "#/$defs/uuid"
        },
        "artifact_id": {
          "$ref": "#/$defs/uuid"
        },
        "version": {
          "$ref": "#/$defs/semver",
          "description": "The file's own version, from its header."
        },
        "alias": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "description": "src/bin/ only; always an array."
        },
        "desc_short": {
          "type": "string",
          "minLength": 10
        },
        "last_updated": {
          "$ref": "#/$defs/datetime"
        },
        "status": {
          "enum": [
            "develop",
            "test",
            "fail",
            "deployed",
            "deprecated"
          ]
        },
        "last_issue": {
          "type": "string",
          "description": "Free text; may be empty."
        },
        "id_child": {
          "type": "string",
          "minLength": 1,
          "description": "Reserved for artifact-inspector; omitted when empty."
        },
        "role": {
          "enum": [
            "entry",
            "module",
            "config",
            "data",
            "doc"
          ],
          "description": "Optional in 0.2, required from 0.3; only an entry carries binary and alias."
        },
        "bin_name": false,
        "aliases": false,
        "id": false,
        "desc_long": false,
        "todos": false,
        "issues": false
      },
      "additionalProperties": true,
      "allOf": [
        {
          "if": {
            "properties": {
              "id_type": {
                "const": "script-id"
              }
            },
            "required": [
              "id_type"
            ]
          },
          "then": {
            "required": [
              "script_id"
            ]
          }
        },
        {
          "if": {
            "properties": {
              "id_type": {
                "const": "docid"
              }
            },
            "required": [
              "id_type"
            ]
          },
          "then": {
            "required": [
              "docid"
            ]
          }
        },
        {
          "if": {
            "properties": {
              "id_type": {
                "const": "schema-id"
              }
            },
            "required": [
              "id_type"
            ]
          },
          "then": {
            "required": [
              "schema_id"
            ]
          }
        },
        {
          "if": {
            "properties": {
              "id_type": {
                "const": "artifact-id"
              }
            },
            "required": [
              "id_type"
            ]
          },
          "then": {
            "required": [
              "artifact_id"
            ]
          }
        },
        {
          "description": "Only an entry carries binary and alias.",
          "if": {
            "required": [
              "role"
            ],
            "not": {
              "properties": {
                "role": {
                  "const": "entry"
                }
              }
            }
          },
          "then": {
            "properties": {
              "binary": false,
              "alias": false
            }
          }
        }
      ]
    }
  }
}
