#  Copyright (c) 2026 Cisco Systems, Inc. and its affiliates
#  SPDX-License-Identifier: Apache-2.0
$schema: "http://json-schema.org/draft-07/schema#"
$id: "mas-lab/lab-config/v1"
title: "mas-lab lab-config manifest (v1)"
description: >
  Schema for lab-config.yaml — interactive MAS demo configuration.
  Top-level key must be 'lab:'.  All relative paths are resolved from
  the directory containing this file.

  A lab-config.yaml is loaded by 'mas-lab demo'.  It configures the live
  demo UI (port, layout, node positions) and declares which scenarios the
  user can select interactively.  Unlike experiment.yaml it does NOT have
  execution batch parameters, flavours, or post-run plots.

type: object
required: [lab]
additionalProperties: false

properties:
  lab:
    type: object
    required: [name]
    additionalProperties: false
    description: "Interactive MAS demo configuration."

    properties:
      # ── Identity ──────────────────────────────────────────────────────────
      name:
        type: string
        minLength: 1
        description: "Use-case name shown in the demo UI header."

      version:
        type: string
        default: "v1"
        description: "Format version — omit or set 'v1' to silence future warnings."

      description:
        type: string
        description: "Free-text description shown in the demo UI."

      # ── MAS applications ──────────────────────────────────────────────────
      default_flavour:
        type: string
        description: "Legacy-compatible default runtime flavour for interactive runs."

      output_dir:
        type: string
        description: "Legacy-compatible output directory; relative paths are resolved from this file."

      applications:
        type: array
        minItems: 1
        description: "MAS use-case pointer(s) for the demo."
        items:
          oneOf:
            - type: string
              minLength: 1
              description: "Library + app identifier, e.g. example-library:my-app@v2."
              pattern: "^[a-z0-9][a-z0-9-]*:[^\\s]+$"
            - type: object
              additionalProperties: false
              properties:
                manifest:
                  type: string
                  description: >
                    Path or library:app identifier resolving to mas.yaml
                    (e.g. example-library:my-app@v2).
                app:
                  type: string
                  description: >
                    Application catalog id, optionally library-qualified
                    (example-library:my-app@v2 or my-app@v2).
                configs_dir:
                  type: string
                  description: "Path to the scenario overlay YAML directory."
                base_scenario:
                  type: string
                  default: "baseline"
                  description: "Scenario loaded on demo startup."
              anyOf:
                - required: [manifest]
                - required: [app]

      mas:
        deprecated: true
        description: >
          DEPRECATED. Alias of applications[0]. Loaders still accept
          lab.mas and emit a warning. Replace with lab.applications.
          See https://ioc-project.github.io/mas-lab/manifests/experiment/#applications
        oneOf:
          - type: object
            additionalProperties: true
          - type: array
            minItems: 1
          - type: string
            minLength: 1

      # ── Scenarios ─────────────────────────────────────────────────────────
      scenarios:
        type: array
        description: "Selectable scenarios in the demo UI dropdown."
        items:
          type: object
          required: [id]
          additionalProperties: false
          properties:
            id:
              type: string
              minLength: 1
              description: "Scenario identifier shown in the UI dropdown."
            overlays:
              type: object
              additionalProperties: false
              required: [logic, control, infra]
              properties:
                logic:
                  type: array
                  items:
                    type: string
                  default: []
                control:
                  type: array
                  items:
                    type: string
                  default: []
                infra:
                  type: array
                  items:
                    type: string
                  default: []
              description: "Layered overlay stacks applied logic → control → infra."
            description:
              type: string
              description: "Human-readable label shown in the UI dropdown."
            user_prompt:
              type: string
              description: "Legacy-compatible default prompt pre-filled when this scenario is selected."
            tags:
              type: array
              items:
                type: string

      libraries:
        type: array
        description: >
          Library paths (same role as workspace config.yaml
          ``manifest_libraries:``). A directory containing ``library.yaml``
          is a library; the name is the listed basename (``lib/`` →
          ``lib``) and is used in ``name:path`` refs. Immediate children
          of this lab that contain ``library.yaml`` are included too.
          A directory without ``library.yaml`` is added to Python's import
          path only. In-repo labs that list a local dir must ship
          ``library.yaml`` there. A listed name that is already a known
          library (for example ``samples``) resolves to that library.
          Lab-local libraries win over workspace and installed libraries
          of the same name. See docs/labs-and-libraries.md.
        items:
          type: string
          minLength: 1

      enable_plugins:
        type: array
        description: >
          Overlay plugin URNs this lab turns on (same catalog as workspace
          config.yaml ``plugins:``). Off unless listed: gdb and checkpoint
          stores.
        items:
          type: string
          minLength: 1

      dataset:
        type: object
        required: [path]
        additionalProperties: false
        description: "Optional prompts dataset for automated demo runs."
        properties:
          path:
            type: string
          filter:
            type: object
            additionalProperties: true
          source:
            type: object
            additionalProperties: false
            description: >
              Optional Dataset spec.source overlay (same shape as experiment.dataset.source).
            properties:
              kind:
                type: string
                enum: [huggingface, jsonl, csv, glob, pickle]
              id:
                type: string
              split:
                type: string
              path:
                type: string
              map:
                type: object
                additionalProperties: true
              config:
                type: string
              name:
                type: string
              limit:
                type: integer
                minimum: 1

      model:
        type: string
        description: >
          Shorthand for models.main. Same meaning as experiment.model.
          evaluation.model overrides the judge only.

      models:
        type: object
        additionalProperties:
          type: string
        description: >
          Slot map matching spec.models[].id plus judge. Same meaning as
          experiment.models.

      # ── Evaluation ────────────────────────────────────────────────────────
      evaluation:
        type: object
        required: [method]
        additionalProperties: false
        properties:
          method:
            type: string
            enum: [user_emulation, llm_judge, metrics]
          model:
            type: string
            description: >
              LLM-as-judge override for demo eval_mce. Omit to inherit
              lab.models.judge / lab.model / application spec.models
              (`any` uses local config).
          config:
            type: object
            additionalProperties: true

      trace_cache_dir:
        type: string
        description: >
          Override the global trace-cache root for this demo.
          Defaults to env var MAS_TRACE_CACHE, then $XDG_CACHE_HOME/mas/traces
          (see docs/user-config.md).

      # ── UI hints ──────────────────────────────────────────────────────────
      ui:
        type: object
        additionalProperties: false
        description: "Demo UI configuration — port, layout, per-agent canvas positions."
        properties:
          port:
            type: integer
            minimum: 1
            maximum: 65535
            description: "HTTP port for the demo server (CLI --port takes precedence)."
          mode:
            type: string
            enum: [interactive, automated]
            default: "interactive"
            description: "'interactive': user drives; 'automated': runs without input."
          layout:
            type: string
            enum: [dag, grid, default]
            default: "default"
            description: "Graph layout hint for the topology visualiser."
          node_positions:
            type: object
            additionalProperties:
              type: object
              additionalProperties: false
              required: [x, y]
              properties:
                x:
                  type: number
                y:
                  type: number
            description: "Per-agent canvas coordinates {agent_id: {x: float, y: float}}."
