{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://raw.githubusercontent.com/shruggietech/insonic/v0.0.0/schemas/v0.0.0/pipeline-config.schema.json",
  "title": "insonic pipeline configuration",
  "description": "Immutable revision of a user-selected capability pipeline. CLI and GUI use this same configuration; local and hosted routes, preparation/training capabilities and credential IDs are explicit.",
  "type": "object",
  "properties": {
    "schema_version": {
      "const": "0.0.0",
      "description": "Version of this public insonic contract."
    },
    "kind": {
      "const": "pipeline-config",
      "description": "Document discriminator selected by the master registry."
    },
    "pipeline_id": {
      "$ref": "common.schema.json#/$defs/uuid",
      "description": "Stable pipeline identity across configuration revisions."
    },
    "revision": {
      "$ref": "common.schema.json#/$defs/revision",
      "description": "Immutable pipeline revision selected by jobs."
    },
    "display_name": {
      "type": "string",
      "minLength": 1,
      "description": "Human-readable pipeline name."
    },
    "stages": {
      "type": "array",
      "minItems": 1,
      "description": "Stage declarations with stable IDs. Application validation constructs a dependency graph and verifies effective options.",
      "items": {
        "type": "object",
        "description": "One capability stage. Dependencies, adapter capability compatibility and binding existence are checked before a job starts.",
        "properties": {
          "stage_id": {
            "type": "string",
            "pattern": "^[A-Za-z][A-Za-z0-9_-]*$",
            "description": "Unique stage ID used by dependencies and input bindings.",
            "examples": [
              "transcribe"
            ]
          },
          "capability": {
            "type": "string",
            "enum": [
              "acquisition",
              "metadata-capture",
              "audio-prepare",
              "transcription",
              "diarization",
              "subtitle-normalization",
              "speaker-attribution",
              "chunking",
              "assertion-extraction",
              "embedding",
              "speaker-model-prepare",
              "speaker-model-train",
              "query-assistance"
            ],
            "description": "Processing capability requested from the chosen adapter."
          },
          "adapter_id": {
            "type": "string",
            "minLength": 1,
            "description": "User-selected local or hosted adapter identity.",
            "examples": [
              "faster-whisper"
            ]
          },
          "adapter_contract_version": {
            "type": "string",
            "minLength": 1,
            "description": "Exact adapter protocol version used for request/results.",
            "examples": [
              "1"
            ]
          },
          "execution": {
            "type": "object",
            "description": "Explicit local or hosted routing; failure never selects an unconfigured host.",
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "local",
                  "hosted"
                ],
                "description": "Where this stage executes."
              },
              "worker_id": {
                "type": "string",
                "minLength": 1,
                "description": "Managed or user-selected local executable worker identity."
              },
              "provider_profile": {
                "$ref": "common.schema.json#/$defs/backendProfileReference",
                "description": "Configured hosted provider profile, with credentials resolved separately."
              }
            },
            "required": [
              "mode"
            ],
            "additionalProperties": false,
            "allOf": [
              {
                "if": {
                  "properties": {
                    "mode": {
                      "const": "local",
                      "description": "Where this stage executes."
                    }
                  },
                  "required": [
                    "mode"
                  ],
                  "type": "object"
                },
                "then": {
                  "required": [
                    "worker_id"
                  ],
                  "not": {
                    "required": [
                      "provider_profile"
                    ],
                    "type": "object"
                  },
                  "type": "object"
                },
                "else": {
                  "required": [
                    "provider_profile"
                  ],
                  "not": {
                    "required": [
                      "worker_id"
                    ],
                    "type": "object"
                  },
                  "type": "object"
                }
              }
            ]
          },
          "credential_id": {
            "$ref": "common.schema.json#/$defs/credentialId",
            "description": "Optional opaque credential ID available only to this stage."
          },
          "depends_on": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "type": "string",
              "minLength": 1,
              "description": "ID of a prerequisite stage in this pipeline."
            },
            "description": "Prerequisite stage IDs. Application validation rejects cycles and unknown IDs."
          },
          "inputs": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "minLength": 1,
              "description": "Typed logical binding such as media.original or prepare.audio; never a shell expression."
            },
            "description": "Named adapter inputs resolved from admitted assets and earlier stage outputs."
          },
          "options": {
            "$ref": "common.schema.json#/$defs/nonsecretOptions",
            "description": "Effective adapter options; adapter validation rejects unsupported values and secret fields."
          },
          "retry": {
            "type": "object",
            "description": "Bounded idempotent retry policy, separate from changing provider routing.",
            "properties": {
              "max_attempts": {
                "type": "integer",
                "minimum": 1,
                "description": "Maximum attempts for eligible retryable errors."
              },
              "backoff_seconds": {
                "type": "number",
                "minimum": 0,
                "description": "Initial nonnegative retry delay."
              }
            },
            "required": [
              "max_attempts",
              "backoff_seconds"
            ],
            "additionalProperties": false
          },
          "extensions": {
            "$ref": "common.schema.json#/$defs/extensions",
            "description": "Optional stage metadata without hidden routing or secrets."
          }
        },
        "required": [
          "stage_id",
          "capability",
          "adapter_id",
          "adapter_contract_version",
          "execution",
          "options"
        ],
        "additionalProperties": false
      }
    },
    "extensions": {
      "$ref": "common.schema.json#/$defs/extensions",
      "description": "Optional namespaced nonsecret extension data."
    }
  },
  "required": [
    "schema_version",
    "kind",
    "pipeline_id",
    "revision",
    "display_name",
    "stages"
  ],
  "additionalProperties": false,
  "examples": [
    {
      "schema_version": "0.0.0",
      "kind": "pipeline-config",
      "pipeline_id": "66666666-6666-4666-8666-666666666666",
      "revision": 1,
      "display_name": "Local transcription",
      "stages": [
        {
          "stage_id": "transcribe",
          "capability": "transcription",
          "adapter_id": "faster-whisper",
          "adapter_contract_version": "1",
          "execution": {
            "mode": "local",
            "worker_id": "faster-whisper-cpu"
          },
          "inputs": {
            "audio": "media.transcription_audio"
          },
          "options": {
            "model": "small",
            "compute_type": "int8"
          },
          "retry": {
            "max_attempts": 2,
            "backoff_seconds": 1
          }
        }
      ]
    }
  ]
}
