{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Config",
  "description": "`.devset/config.toml`: the sources, the layers, and the target's word on every setting they\ncarry.",
  "type": "object",
  "properties": {
    "sources": {
      "description": "Where profiles come from, each named once.",
      "type": "object",
      "additionalProperties": { "$ref": "#/$defs/SourceSpec" },
      "default": {}
    },
    "layers": { "description": "Profiles to apply, in order.", "type": "array", "items": { "$ref": "#/$defs/LayerSpec" }, "default": [] },
    "merge": { "description": "Merge settings; these override every layer's.", "$ref": "#/$defs/MergeSpec", "default": {} },
    "files": { "description": "Overrides of the layers' `[files]` entries.", "type": "object", "additionalProperties": { "$ref": "#/$defs/Override" } }
  },
  "additionalProperties": false,
  "$defs": {
    "SourceSpec": {
      "description": "A source as written in `config.toml`: Cargo's git-dependency fields.",
      "type": "object",
      "properties": {
        "git": { "description": "Repository URL.", "type": ["string", "null"] },
        "tag": { "description": "Tag to use; only with `git`.", "type": ["string", "null"] },
        "branch": { "description": "Branch to use; only with `git`.", "type": ["string", "null"] },
        "rev": { "description": "Full commit id to use; only with `git`.", "type": ["string", "null"] },
        "path": { "description": "The profile's directory: relative to the target, or within the repository with `git`.", "type": ["string", "null"] }
      },
      "additionalProperties": false
    },
    "LayerSpec": {
      "description": "A `[[layers]]` entry: a profile, and the features the target turns on.",
      "type": "object",
      "properties": {
        "profile": { "description": "The profile, `source/name`.", "$ref": "#/$defs/ProfileRef" },
        "features": {
          "description": "Its features to turn on, beside its default ones.",
          "type": "array",
          "items": { "description": "A feature of a profile; never `default`, which names the list of features on by default.", "type": "string" }
        },
        "default-features": { "description": "Whether its default features are on; unless a profile that requires it turns them on.", "type": "boolean" }
      },
      "additionalProperties": false,
      "required": ["profile"]
    },
    "ProfileRef": {
      "description": "A profile in a named source: `source/profile`.",
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]*/[A-Za-z0-9][A-Za-z0-9_-]*$"
    },
    "MergeSpec": {
      "description": "A `[merge]` table: defaults in `profile.toml`, decisions in `.devset/config.toml`.",
      "type": "object",
      "properties": {
        "on-conflict": { "description": "What a run does when a file conflicts.", "anyOf": [{ "$ref": "#/$defs/OnConflict" }, { "type": "null" }] },
        "driver": {
          "description": "A merge program, with `%O %A %B %P` substituted.\n\nFrom a profile it is only a suggestion: devset never runs a program a profile names.",
          "type": ["string", "null"]
        }
      },
      "additionalProperties": false
    },
    "OnConflict": {
      "description": "What a run does when a file conflicts.",
      "oneOf": [
        { "description": "Write every other file and advance the lock; conflicts wait in `.devset/conflicts/`.", "type": "string", "const": "apply-others" },
        { "description": "Write nothing but the conflicts until every one is resolved.", "type": "string", "const": "apply-none" }
      ]
    },
    "Override": {
      "description": "A `[files.\"path\"]` entry in `config.toml`, overriding the providing layer's.",
      "type": "object",
      "properties": {
        "from": { "description": "The layer that provides the file, when several do.", "type": ["string", "null"], "default": null },
        "policy": { "description": "How devset manages the file.", "anyOf": [{ "$ref": "#/$defs/Policy" }, { "type": "null" }], "default": null },
        "validate": { "description": "How a merged result is checked.", "anyOf": [{ "$ref": "#/$defs/Format" }, { "type": "null" }], "default": null }
      },
      "additionalProperties": false
    },
    "Policy": {
      "description": "How devset manages a file.",
      "oneOf": [
        { "description": "The profile is authoritative; local edits are drift.", "type": "string", "const": "owned" },
        { "description": "Local edits are kept, and merged with the profile's.", "type": "string", "const": "merge" },
        { "description": "Written once if absent; the target's from then on.", "type": "string", "const": "once" }
      ]
    },
    "Format": {
      "description": "How a file is checked after a merge: it must parse, with no duplicate keys.",
      "oneOf": [
        { "description": "TOML.", "type": "string", "const": "toml" },
        { "description": "JSON with comments and trailing commas (JSONC), a superset of JSON.", "type": "string", "const": "json" },
        { "description": "YAML.", "type": "string", "const": "yaml" },
        { "description": "Not checked.", "type": "string", "const": "none" }
      ]
    }
  }
}
