{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://mnstry.ai/contracts/atelier-kit-manifest.v1.schema.json",
  "title": "MNSTRY Atelier Kit Manifest v1",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema",
    "kit",
    "versions",
    "runtimeLock",
    "contracts",
    "extensionPacks",
    "fileClasses",
    "telemetry"
  ],
  "properties": {
    "schema": {
      "const": "mnstry-atelier-kit-manifest@v1"
    },
    "kit": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "boundary", "clientZero"],
      "properties": {
        "name": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9-]*$"
        },
        "boundary": {
          "const": "extractable-kit-readiness"
        },
        "clientZero": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9-]*$"
        }
      }
    },
    "versions": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "kernel",
        "sourceDialect",
        "exportContract",
        "readinessRules",
        "actionRules"
      ],
      "properties": {
        "kernel": {
          "type": "string",
          "pattern": "^v[0-9]+$"
        },
        "sourceDialect": {
          "type": "string",
          "pattern": "^v[0-9]+$"
        },
        "exportContract": {
          "const": "atelier-export@v1"
        },
        "readinessRules": {
          "type": "string",
          "pattern": "^atelier-readiness@v[0-9]+$"
        },
        "actionRules": {
          "type": "string",
          "pattern": "^atelier-action-intent@v[0-9]+$"
        }
      }
    },
    "runtimeLock": {
      "type": "object",
      "additionalProperties": false,
      "required": ["path", "schema", "digest"],
      "properties": {
        "path": {
          "const": "atelier-runtime.lock.json"
        },
        "schema": {
          "const": "atelier-runtime-lock@v1"
        },
        "digest": {
          "type": "string",
          "pattern": "^sha256:[0-9a-f]{64}$"
        }
      }
    },
    "contracts": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "additionalProperties": false,
        "required": ["path", "digest"],
        "properties": {
          "path": {
            "type": "string",
            "pattern": "^(?!.*(^|/)\\.\\.(/|$))[A-Za-z0-9._/-]+$"
          },
          "digest": {
            "type": "string",
            "pattern": "^sha256:[0-9a-f]{64}$"
          }
        }
      },
      "required": ["export", "readiness", "actions"]
    },
    "extensionPacks": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "version", "path", "enabled"],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*$"
          },
          "version": {
            "type": "string",
            "pattern": "^v[0-9]+$"
          },
          "path": {
            "type": "string",
            "pattern": "^(?!.*(^|/)\\.\\.(/|$))[A-Za-z0-9._/-]+\\.json$"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "uniqueItems": true
    },
    "fileClasses": {
      "description": "How automated handling must treat each file the kit ships or generates. Sync loops, merge policies, upgrade tooling, and CI guards consume this one declaration instead of each keeping its own list of filenames. Later entries win, as in .gitignore.",
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["pattern", "class"],
        "properties": {
          "pattern": {
            "type": "string",
            "minLength": 1
          },
          "class": {
            "description": "source: canonical, never discarded, conflicts need a human. generated-projection: rebuilt deterministically, discard freely. distributed-runtime-copy: canonical in one repo role, rederivable in consumers.",
            "enum": ["source", "generated-projection", "distributed-runtime-copy"]
          },
          "canonicalRepoRole": {
            "description": "The repo role in which a distributed-runtime-copy is canonical source. Without it, a sync loop cannot tell the repo that owns the file from the repos that merely receive it, and will discard canonical edits.",
            "type": "string",
            "minLength": 1
          },
          "note": {
            "type": "string"
          }
        },
        "allOf": [
          {
            "if": {
              "properties": { "class": { "const": "distributed-runtime-copy" } },
              "required": ["class"]
            },
            "then": { "required": ["canonicalRepoRole"] },
            "else": { "not": { "required": ["canonicalRepoRole"] } }
          }
        ]
      }
    },
    "telemetry": {
      "type": "object",
      "additionalProperties": false,
      "required": ["mode", "background", "sendPath"],
      "properties": {
        "mode": {
          "const": "none"
        },
        "background": {
          "const": false
        },
        "sendPath": {
          "const": false
        }
      }
    }
  }
}
