{
  "$defs": {
    "CommandStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "command": {
          "description": "Command to run in the environment.",
          "title": "Command",
          "type": "string"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "command",
          "default": "command",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "command"
      ],
      "title": "CommandStage",
      "type": "object"
    },
    "CondaEnvironment": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "kind": {
          "const": "conda",
          "default": "conda",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "description": "Path to the Conda environment YAML file.",
          "title": "Path",
          "type": "string"
        },
        "prefix": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path at which to create the environment.",
          "title": "Prefix"
        }
      },
      "required": [
        "path"
      ],
      "title": "CondaEnvironment",
      "type": "object"
    },
    "CopyFileToDir": {
      "description": "Copy a single file into a directory, keeping its name.",
      "properties": {
        "dest": {
          "description": "Path to the directory into which the file is copied.",
          "title": "Dest",
          "type": "string"
        },
        "kind": {
          "const": "file-to-dir",
          "default": "file-to-dir",
          "description": "Copy one file into a destination directory.",
          "title": "Kind",
          "type": "string"
        },
        "src": {
          "description": "Path to the file to copy.",
          "title": "Src",
          "type": "string"
        }
      },
      "required": [
        "src",
        "dest"
      ],
      "title": "CopyFileToDir",
      "type": "object"
    },
    "CopyFileToFile": {
      "description": "Copy a single file to a single destination path.",
      "properties": {
        "dest": {
          "description": "Path to which the file is copied.",
          "title": "Dest",
          "type": "string"
        },
        "kind": {
          "const": "file-to-file",
          "default": "file-to-file",
          "description": "Copy one file to one destination path.",
          "title": "Kind",
          "type": "string"
        },
        "src": {
          "description": "Path to the file to copy.",
          "title": "Src",
          "type": "string"
        }
      },
      "required": [
        "src",
        "dest"
      ],
      "title": "CopyFileToFile",
      "type": "object"
    },
    "Dataset": {
      "description": "A dataset, whether computed, collected here, or obtained elsewhere.\n\nData someone collected or measured for this project is a primary\nartifact, and ``created_by`` names them, since there is nothing\nupstream to point at. Data from elsewhere records ``imported_from``.",
      "not": {
        "properties": {
          "created_by": {
            "type": [
              "object",
              "array"
            ]
          },
          "imported_from": {
            "type": "object"
          }
        },
        "required": [
          "imported_from",
          "created_by"
        ]
      },
      "properties": {
        "created_by": {
          "anyOf": [
            {
              "$ref": "#/$defs/_Person"
            },
            {
              "items": {
                "$ref": "#/$defs/_Person"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Who created this primary artifact here, e.g., collected or measured the data, drew the figure, or took the photo, rather than it being produced by the pipeline or obtained from elsewhere. A primary artifact has no upstream source to point at, so naming who produced it is the only way to tell it apart from one whose provenance was never recorded. Each person discloses the generative AI tools they used via ``with_ai``.",
          "title": "Created By"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A longer description.",
          "title": "Description"
        },
        "imported_from": {
          "anyOf": [
            {
              "$ref": "#/$defs/_ImportedFromProject"
            },
            {
              "$ref": "#/$defs/_ImportedFromUrl"
            },
            {
              "$ref": "#/$defs/_ImportedFromDoi"
            },
            {
              "$ref": "#/$defs/_ImportedFromGit"
            },
            {
              "$ref": "#/$defs/_ImportedFromDescription"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where this came from, if imported.",
          "title": "Imported From"
        },
        "path": {
          "description": "Path to the file, relative to the project root.",
          "title": "Path",
          "type": "string"
        },
        "stage": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the pipeline stage that produces this.",
          "title": "Stage"
        },
        "title": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A human-readable title.",
          "title": "Title"
        }
      },
      "required": [
        "path"
      ],
      "title": "Dataset",
      "type": "object"
    },
    "DerivedFromProject": {
      "properties": {
        "git_repo_url": {
          "title": "Git Repo Url",
          "type": "string"
        },
        "git_rev": {
          "title": "Git Rev",
          "type": "string"
        },
        "project": {
          "title": "Project",
          "type": "string"
        }
      },
      "required": [
        "project",
        "git_repo_url",
        "git_rev"
      ],
      "title": "DerivedFromProject",
      "type": "object"
    },
    "DirToDirMerge": {
      "description": "Copy a directory's contents into another, keeping what's there.",
      "properties": {
        "dest": {
          "description": "Path to the directory to copy into.",
          "title": "Dest",
          "type": "string"
        },
        "kind": {
          "const": "dir-to-dir-merge",
          "default": "dir-to-dir-merge",
          "description": "Merge one directory's contents into another.",
          "title": "Kind",
          "type": "string"
        },
        "src": {
          "description": "Path to the directory to copy from.",
          "title": "Src",
          "type": "string"
        }
      },
      "required": [
        "src",
        "dest"
      ],
      "title": "DirToDirMerge",
      "type": "object"
    },
    "DirToDirReplace": {
      "description": "Replace a directory with the contents of another.",
      "properties": {
        "dest": {
          "description": "Path to the directory to replace, which is deleted first.",
          "title": "Dest",
          "type": "string"
        },
        "kind": {
          "const": "dir-to-dir-replace",
          "default": "dir-to-dir-replace",
          "description": "Replace the destination directory entirely.",
          "title": "Kind",
          "type": "string"
        },
        "src": {
          "description": "Path to the directory to copy from.",
          "title": "Src",
          "type": "string"
        }
      },
      "required": [
        "src",
        "dest"
      ],
      "title": "DirToDirReplace",
      "type": "object"
    },
    "DockerCommandStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "command": {
          "description": "Full command to run, including the 'docker run' call.",
          "title": "Command",
          "type": "string"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "docker-command",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "kind",
        "environment",
        "command"
      ],
      "title": "DockerCommandStage",
      "type": "object"
    },
    "DockerEnvironment": {
      "anyOf": [
        {
          "properties": {
            "image": {
              "type": "string"
            }
          },
          "required": [
            "image"
          ]
        },
        {
          "properties": {
            "path": {
              "type": "string"
            }
          },
          "required": [
            "path"
          ]
        }
      ],
      "properties": {
        "args": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Extra arguments passed to 'docker run'.",
          "title": "Args"
        },
        "build_platforms": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Platforms to build the image for, e.g., ['linux/amd64', 'linux/arm64'], as opposed to 'platform', which is the one it's pulled and run as. Building for more than one requires a registry, since a multi-platform image can only be kept in one.",
          "title": "Build Platforms"
        },
        "command_mode": {
          "default": "shell",
          "description": "Whether commands run through a shell or the image's entrypoint.",
          "enum": [
            "shell",
            "entrypoint"
          ],
          "title": "Command Mode",
          "type": "string"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "env_vars": {
          "anyOf": [
            {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Environmental variables to set in the container.",
          "title": "Env Vars"
        },
        "gpus": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "GPUs to make available, passed to 'docker run --gpus'.",
          "title": "Gpus"
        },
        "image": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the Docker image. Optional for an environment with a Dockerfile, which is named after the project and environment it belongs to, e.g., 'someone/some-project.my-env'. Required for one defined purely by an image.",
          "title": "Image"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Files added to the container as dependencies. Their checksums are recorded in the environment's lock file, so editing one rebuilds the image and reruns the stages that use it.",
          "title": "Inputs"
        },
        "jupyter_kernel": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the Jupyter kernel inside the image, used when executing notebooks with 'calkit nb execute'. Defaults to 'python3', or 'ir' for R images.",
          "title": "Jupyter Kernel"
        },
        "kind": {
          "const": "docker",
          "default": "docker",
          "title": "Kind",
          "type": "string"
        },
        "layers": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Predefined layers to add to the generated Dockerfile.",
          "title": "Layers"
        },
        "path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path to the Dockerfile. Optional, since Docker environments can be defined purely by an image.",
          "title": "Path"
        },
        "platform": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Platform to run as, e.g., 'linux/amd64'.",
          "title": "Platform"
        },
        "ports": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Ports to expose, e.g., '8080:80'.",
          "title": "Ports"
        },
        "registry": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Registry prefix images built from this environment's Dockerfile are pushed to and pulled from, e.g., 'ghcr.io/someone/some-project', or 'ghcr.io' for the project's own namespace in the GitHub Container Registry. Images are kept local if this is unset or null.",
          "title": "Registry"
        },
        "shell": {
          "default": "sh",
          "description": "Shell used to run commands in the image.",
          "enum": [
            "bash",
            "sh"
          ],
          "title": "Shell",
          "type": "string"
        },
        "user": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "User to run the container as. Defaults to the host user.",
          "title": "User"
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory inside the container. Defaults to '/work'.",
          "title": "Wdir"
        }
      },
      "title": "DockerEnvironment",
      "type": "object"
    },
    "Figure": {
      "description": "A figure, usually produced by a pipeline stage.\n\nCarries attribution for the ones that aren't: a schematic drawn by hand\nor laid out with a generative AI tool has no stage to point at, and is\nexactly the kind of thing a reader wants told. One obtained from\nelsewhere records ``imported_from`` instead, like a dataset does.",
      "not": {
        "properties": {
          "created_by": {
            "type": [
              "object",
              "array"
            ]
          },
          "imported_from": {
            "type": "object"
          }
        },
        "required": [
          "imported_from",
          "created_by"
        ]
      },
      "properties": {
        "created_by": {
          "anyOf": [
            {
              "$ref": "#/$defs/_Person"
            },
            {
              "items": {
                "$ref": "#/$defs/_Person"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Who created this primary artifact here, e.g., collected or measured the data, drew the figure, or took the photo, rather than it being produced by the pipeline or obtained from elsewhere. A primary artifact has no upstream source to point at, so naming who produced it is the only way to tell it apart from one whose provenance was never recorded. Each person discloses the generative AI tools they used via ``with_ai``.",
          "title": "Created By"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A longer description.",
          "title": "Description"
        },
        "imported_from": {
          "anyOf": [
            {
              "$ref": "#/$defs/_ImportedFromProject"
            },
            {
              "$ref": "#/$defs/_ImportedFromUrl"
            },
            {
              "$ref": "#/$defs/_ImportedFromDoi"
            },
            {
              "$ref": "#/$defs/_ImportedFromGit"
            },
            {
              "$ref": "#/$defs/_ImportedFromDescription"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where this came from, if imported.",
          "title": "Imported From"
        },
        "path": {
          "description": "Path to the file, relative to the project root.",
          "title": "Path",
          "type": "string"
        },
        "stage": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the pipeline stage that produces this.",
          "title": "Stage"
        },
        "title": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A human-readable title.",
          "title": "Title"
        }
      },
      "required": [
        "path"
      ],
      "title": "Figure",
      "type": "object"
    },
    "FigureEvidence": {
      "description": "Evidence to back up the answer to a question.",
      "properties": {
        "explanation": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Explanation"
        },
        "git_ref": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Git reference (branch, tag, or commit hash) pointing to the version of the repository where the figure can be found.",
          "title": "Git Ref"
        },
        "kind": {
          "const": "figure",
          "default": "figure",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "title": "FigureEvidence",
      "type": "object"
    },
    "Formula": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Input"
              },
              "type": "array"
            },
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            }
          ],
          "title": "Inputs"
        },
        "kind": {
          "const": "formula",
          "default": "formula",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "output": {
          "anyOf": [
            {
              "$ref": "#/$defs/Output"
            },
            {
              "type": "string"
            }
          ],
          "title": "Output"
        },
        "params": {
          "$ref": "#/$defs/FormulaParams"
        }
      },
      "required": [
        "params",
        "inputs",
        "output"
      ],
      "title": "Formula",
      "type": "object"
    },
    "FormulaParams": {
      "properties": {
        "formula": {
          "title": "Formula",
          "type": "string"
        }
      },
      "required": [
        "formula"
      ],
      "title": "FormulaParams",
      "type": "object"
    },
    "Input": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "dtype": {
          "default": "float",
          "enum": [
            "int",
            "float",
            "str"
          ],
          "title": "Dtype",
          "type": "string"
        },
        "max": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Max"
        },
        "min": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Min"
        },
        "name": {
          "title": "Name",
          "type": "string"
        }
      },
      "required": [
        "name"
      ],
      "title": "Input",
      "type": "object"
    },
    "InputsFromStageOutputs": {
      "properties": {
        "from_stage_outputs": {
          "description": "Name of a stage whose outputs are inputs to this one.",
          "title": "From Stage Outputs",
          "type": "string"
        }
      },
      "required": [
        "from_stage_outputs"
      ],
      "title": "InputsFromStageOutputs",
      "type": "object"
    },
    "JsonToLatexStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "command_name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the LaTeX command to define for each value.",
          "title": "Command Name"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "default": "_system",
          "title": "Environment",
          "type": "string"
        },
        "format": {
          "anyOf": [
            {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Format strings for values, keyed by their JSON key.",
          "title": "Format"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "keys": {
          "default": [],
          "description": "Keys to expose to the document, dotted to reach into nested output, e.g., 'cases.a.cp'. Without any, every top-level key is exposed, which is fine for a results file written for the paper and unwieldy for one exported wholesale from an analysis.",
          "items": {
            "type": "string"
          },
          "title": "Keys",
          "type": "array"
        },
        "kind": {
          "const": "json-to-latex",
          "default": "json-to-latex",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "title": "JsonToLatexStage",
      "type": "object"
    },
    "JuliaCommandStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "command": {
          "description": "Julia command to run.",
          "title": "Command",
          "type": "string"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "julia-command",
          "default": "julia-command",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "command"
      ],
      "title": "JuliaCommandStage",
      "type": "object"
    },
    "JuliaEnvironment": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "julia": {
          "description": "Julia version to use.",
          "title": "Julia",
          "type": "string"
        },
        "kind": {
          "const": "julia",
          "default": "julia",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "description": "Path to the Julia project's Project.toml.",
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path",
        "julia"
      ],
      "title": "JuliaEnvironment",
      "type": "object"
    },
    "JuliaScriptStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "args": {
          "default": [],
          "description": "Arguments passed to the script.",
          "items": {
            "type": "string"
          },
          "title": "Args",
          "type": "array"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "julia-script",
          "default": "julia-script",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "script_path": {
          "description": "Path to the Julia script to run.",
          "title": "Script Path",
          "type": "string"
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "script_path"
      ],
      "title": "JuliaScriptStage",
      "type": "object"
    },
    "JupyterNotebookStage": {
      "additionalProperties": false,
      "description": "A stage that runs a Jupyter notebook.\n\nNotebooks need to be cleaned of outputs so they can be used as DVC\ndependencies. The ``status`` and ``run`` commands handle this\nautomatically.",
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "cleaned_ipynb_storage": {
          "anyOf": [
            {
              "enum": [
                "git",
                "dvc"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where to store the output-stripped notebook.",
          "title": "Cleaned Ipynb Storage"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "executed_ipynb_storage": {
          "anyOf": [
            {
              "enum": [
                "git",
                "dvc"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "dvc",
          "description": "Where to store the executed notebook.",
          "title": "Executed Ipynb Storage"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "html_storage": {
          "anyOf": [
            {
              "enum": [
                "git",
                "dvc"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "dvc",
          "description": "Where to store the executed notebook as HTML.",
          "title": "Html Storage"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "jupyter-notebook",
          "default": "jupyter-notebook",
          "title": "Kind",
          "type": "string"
        },
        "language": {
          "anyOf": [
            {
              "enum": [
                "python",
                "matlab",
                "julia"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The notebook's language. Detected automatically if unset.",
          "title": "Language"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "notebook_path": {
          "description": "Path to the notebook to execute.",
          "title": "Notebook Path",
          "type": "string"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "parameters": {
          "additionalProperties": true,
          "default": {},
          "description": "Parameters injected into the notebook. A value like '{name}' is filled in from the project-level parameters.",
          "title": "Parameters",
          "type": "object"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "notebook_path"
      ],
      "title": "JupyterNotebookStage",
      "type": "object"
    },
    "LatexStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "aux_dir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Directory for latexmk auxiliary files.",
          "title": "Aux Dir"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "diff_pdf_storage": {
          "anyOf": [
            {
              "enum": [
                "git",
                "dvc"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "dvc",
          "description": "Where to store the resulting diff PDFs.",
          "title": "Diff Pdf Storage"
        },
        "diffs": {
          "default": [],
          "description": "Comparisons to keep for this document, each a pair of revisions. A bare string is shorthand for comparing that revision against the working tree.",
          "items": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              }
            ]
          },
          "title": "Diffs",
          "type": "array"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "force": {
          "default": false,
          "description": "Keep compiling despite errors (latexmk -f).",
          "title": "Force",
          "type": "boolean"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "latex",
          "default": "latex",
          "title": "Kind",
          "type": "string"
        },
        "latexdiff_args": {
          "default": [],
          "description": "Extra arguments passed straight through to latexdiff when building diffs, e.g., '--type=CFONT'. Changed figures are shown old and new unless '--graphics-markup' is set here.",
          "items": {
            "type": "string"
          },
          "title": "Latexdiff Args",
          "type": "array"
        },
        "latexmk_args": {
          "default": [],
          "description": "Extra arguments passed straight through to latexmk, for control Calkit does not model.",
          "items": {
            "type": "string"
          },
          "title": "Latexmk Args",
          "type": "array"
        },
        "latexmkrc_path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path to a latexmkrc file to use.",
          "title": "Latexmkrc Path"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "output_dir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Directory for latexmk output. Defaults to compiling in place, alongside the target.",
          "title": "Output Dir"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "pdf_storage": {
          "anyOf": [
            {
              "enum": [
                "git",
                "dvc"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "dvc",
          "description": "Where to store the resulting PDF.",
          "title": "Pdf Storage"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "synctex": {
          "default": true,
          "description": "Generate SyncTeX data for editor/PDF navigation.",
          "title": "Synctex",
          "type": "boolean"
        },
        "target_path": {
          "description": "Path to the .tex file to compile.",
          "title": "Target Path",
          "type": "string"
        },
        "verbose": {
          "default": false,
          "description": "Show full latexmk output.",
          "title": "Verbose",
          "type": "boolean"
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "target_path"
      ],
      "title": "LatexStage",
      "type": "object"
    },
    "Linear": {
      "description": "Calculation for a simple linear relationship.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Input"
              },
              "type": "array"
            },
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            }
          ],
          "title": "Inputs"
        },
        "kind": {
          "const": "linear",
          "default": "linear",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "output": {
          "anyOf": [
            {
              "$ref": "#/$defs/Output"
            },
            {
              "type": "string"
            }
          ],
          "title": "Output"
        },
        "params": {
          "$ref": "#/$defs/LinearParams"
        }
      },
      "required": [
        "params",
        "inputs",
        "output"
      ],
      "title": "Linear",
      "type": "object"
    },
    "LinearParams": {
      "properties": {
        "coeffs": {
          "additionalProperties": {
            "type": "number"
          },
          "title": "Coeffs",
          "type": "object"
        },
        "offset": {
          "default": 0.0,
          "title": "Offset",
          "type": "number"
        }
      },
      "required": [
        "coeffs"
      ],
      "title": "LinearParams",
      "type": "object"
    },
    "LookupTable": {
      "description": "A 1-D lookup table.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Input"
              },
              "type": "array"
            },
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            }
          ],
          "title": "Inputs"
        },
        "kind": {
          "const": "lookup-table",
          "default": "lookup-table",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "output": {
          "anyOf": [
            {
              "$ref": "#/$defs/Output"
            },
            {
              "type": "string"
            }
          ],
          "title": "Output"
        },
        "params": {
          "$ref": "#/$defs/LookupTableParams"
        }
      },
      "required": [
        "params",
        "inputs",
        "output"
      ],
      "title": "LookupTable",
      "type": "object"
    },
    "LookupTableParams": {
      "properties": {
        "method": {
          "default": "interpolate",
          "enum": [
            "floor",
            "ceil",
            "round",
            "interpolate"
          ],
          "title": "Method",
          "type": "string"
        },
        "x_values": {
          "items": {
            "type": "number"
          },
          "title": "X Values",
          "type": "array"
        },
        "y_values": {
          "items": {
            "type": "number"
          },
          "title": "Y Values",
          "type": "array"
        }
      },
      "required": [
        "x_values",
        "y_values"
      ],
      "title": "LookupTableParams",
      "type": "object"
    },
    "MapPathsStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "default": "_system",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "map-paths",
          "default": "map-paths",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "paths": {
          "description": "Copy operations to perform.",
          "items": {
            "discriminator": {
              "mapping": {
                "dir-to-dir-merge": "#/$defs/DirToDirMerge",
                "dir-to-dir-replace": "#/$defs/DirToDirReplace",
                "file-to-dir": "#/$defs/CopyFileToDir",
                "file-to-file": "#/$defs/CopyFileToFile"
              },
              "propertyName": "kind"
            },
            "oneOf": [
              {
                "$ref": "#/$defs/CopyFileToFile"
              },
              {
                "$ref": "#/$defs/CopyFileToDir"
              },
              {
                "$ref": "#/$defs/DirToDirMerge"
              },
              {
                "$ref": "#/$defs/DirToDirReplace"
              }
            ]
          },
          "title": "Paths",
          "type": "array"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "paths"
      ],
      "title": "MapPathsStage",
      "type": "object"
    },
    "MarimoHtmlWasmStage": {
      "additionalProperties": false,
      "description": "A stage that exports a marimo notebook to a WebAssembly app.\n\nThe app runs entirely in the browser via Pyodide, so it can be served\nas static files with no backend.\n\nmarimo's export commands differ enough from each other that each gets\nits own stage kind and CLI command, rather than one kind with a format\noption whose other fields only apply to some of its values.\n\nmarimo's own export is not self-contained: it requires the data an app\nreads to already sit in a ``public`` directory next to the notebook, and\ncopies only that directory into the output. Assembling that is this\nstage's main job, and it happens in a build directory rather than\nin place, so nothing is generated in the project tree. Paths in ``include_paths`` are\ncopied beneath ``public`` at their project-relative paths, so notebook\ncode that reads ``mo.notebook_location() / \"public\" / \"data.csv\"`` works\nthe same locally as it does in the browser.\n\n``include_paths`` is deliberately separate from ``inputs`` because these\nfiles are published to the web, which should be opt-in per path rather\nthan inferred from the dependency graph. They are dependencies too.",
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "include_paths": {
          "default": [],
          "description": "Paths published with the app, readable from the notebook at 'public/<path>'. These are dependencies as well.",
          "items": {
            "type": "string"
          },
          "title": "Include Paths",
          "type": "array"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "marimo-html-wasm",
          "default": "marimo-html-wasm",
          "title": "Kind",
          "type": "string"
        },
        "layout_path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path to the notebook's layout file, if it has one.",
          "title": "Layout Path"
        },
        "mode": {
          "default": "run",
          "description": "Whether the app runs its cells or opens as an editable notebook.",
          "enum": [
            "run",
            "edit"
          ],
          "title": "Mode",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "notebook_path": {
          "description": "Path to the marimo notebook to export.",
          "title": "Notebook Path",
          "type": "string"
        },
        "output_dir": {
          "description": "Directory into which the app is exported.",
          "title": "Output Dir",
          "type": "string"
        },
        "output_storage": {
          "anyOf": [
            {
              "enum": [
                "git",
                "dvc"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "dvc",
          "description": "Where to store the exported app.",
          "title": "Output Storage"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "show_code": {
          "default": false,
          "description": "Show the notebook's code in the app.",
          "title": "Show Code",
          "type": "boolean"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "validate_notebook": {
          "default": true,
          "description": "Run the notebook before exporting, to catch one that would fail in the browser.",
          "title": "Validate Notebook",
          "type": "boolean"
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "notebook_path",
        "output_dir"
      ],
      "title": "MarimoHtmlWasmStage",
      "type": "object"
    },
    "MarkdownStage": {
      "additionalProperties": false,
      "description": "A stage sourced from a Markdown file's annotated code blocks.\n\nThis stands in for however many stages the file declares. It is\nreplaced by them at compile time (see\n``calkit.markdown.expand_ck_info``), so nothing downstream needs to\nknow Markdown was involved.\n\n``inputs``, ``always_run``, ``frozen``, and ``scheduler`` apply to\nevery stage the file declares. A file can't iterate or declare\noutputs as a whole, since those belong to the individual stages in\nit, and its stages always run in the project root, where the scripts\nextracted from it are written.",
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "default": "_system",
          "description": "Environment used by blocks that don't name one.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths every stage declared in the file depends on, in addition to any a block declares for itself.",
          "title": "Inputs"
        },
        "iterate_over": {
          "default": null,
          "description": "Not supported; markdown stages can't iterate.",
          "title": "Iterate Over",
          "type": "null"
        },
        "kind": {
          "const": "markdown",
          "default": "markdown",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "default": null,
          "description": "Not supported; declare outputs on the file's blocks.",
          "title": "Outputs",
          "type": "null"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "target_path": {
          "description": "Path to the Markdown file.",
          "title": "Target Path",
          "type": "string"
        },
        "wdir": {
          "default": null,
          "description": "Not supported; a Markdown file's stages run in the project root.",
          "title": "Wdir",
          "type": "null"
        }
      },
      "required": [
        "target_path"
      ],
      "title": "MarkdownStage",
      "type": "object"
    },
    "MatlabCommandStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "command": {
          "description": "MATLAB command to run.",
          "title": "Command",
          "type": "string"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "matlab-command",
          "default": "matlab-command",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "command"
      ],
      "title": "MatlabCommandStage",
      "type": "object"
    },
    "MatlabEnvironment": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "kind": {
          "const": "matlab",
          "default": "matlab",
          "title": "Kind",
          "type": "string"
        },
        "products": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "MATLAB products (toolboxes) required.",
          "title": "Products"
        },
        "version": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "MATLAB version to use.",
          "title": "Version"
        }
      },
      "title": "MatlabEnvironment",
      "type": "object"
    },
    "MatlabScriptStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "matlab-script",
          "title": "Kind",
          "type": "string"
        },
        "matlab_path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Directory added to the MATLAB path, recursively.",
          "title": "Matlab Path"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "script_path": {
          "description": "Path to the MATLAB script to run.",
          "title": "Script Path",
          "type": "string"
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "kind",
        "environment",
        "script_path"
      ],
      "title": "MatlabScriptStage",
      "type": "object"
    },
    "MiscArtifact": {
      "description": "A path worth attributing that isn't one of the typed artifacts.\n\nMost files in a project are neither a dataset nor a figure nor a paper:\na photograph, a slide someone drew, a config a colleague sent over. They\nstill have an origin, and without somewhere to record it the honest\nanswer is missing rather than merely absent.",
      "not": {
        "properties": {
          "created_by": {
            "type": [
              "object",
              "array"
            ]
          },
          "imported_from": {
            "type": "object"
          }
        },
        "required": [
          "imported_from",
          "created_by"
        ]
      },
      "properties": {
        "created_by": {
          "anyOf": [
            {
              "$ref": "#/$defs/_Person"
            },
            {
              "items": {
                "$ref": "#/$defs/_Person"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Who created this primary artifact here, e.g., collected or measured the data, drew the figure, or took the photo, rather than it being produced by the pipeline or obtained from elsewhere. A primary artifact has no upstream source to point at, so naming who produced it is the only way to tell it apart from one whose provenance was never recorded. Each person discloses the generative AI tools they used via ``with_ai``.",
          "title": "Created By"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A longer description.",
          "title": "Description"
        },
        "imported_from": {
          "anyOf": [
            {
              "$ref": "#/$defs/_ImportedFromProject"
            },
            {
              "$ref": "#/$defs/_ImportedFromUrl"
            },
            {
              "$ref": "#/$defs/_ImportedFromDoi"
            },
            {
              "$ref": "#/$defs/_ImportedFromGit"
            },
            {
              "$ref": "#/$defs/_ImportedFromDescription"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where this came from, if imported.",
          "title": "Imported From"
        },
        "path": {
          "description": "Path to the file, relative to the project root.",
          "title": "Path",
          "type": "string"
        },
        "stage": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the pipeline stage that produces this.",
          "title": "Stage"
        },
        "title": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A human-readable title.",
          "title": "Title"
        }
      },
      "required": [
        "path"
      ],
      "title": "MiscArtifact",
      "type": "object"
    },
    "NixEnvironment": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "kind": {
          "const": "nix",
          "default": "nix",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "description": "Path to the project's flake.nix. The flake.lock alongside it is the reproducibility-anchoring lock file tracked as a DVC dependency.",
          "title": "Path",
          "type": "string"
        },
        "shell": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the dev shell to enter, passed as #<shell> to 'nix develop'. Defaults to the flake's default dev shell.",
          "title": "Shell"
        }
      },
      "required": [
        "path"
      ],
      "title": "NixEnvironment",
      "type": "object"
    },
    "Notebook": {
      "description": "A Jupyter notebook.\n\nUnlike the other objects, a notebook entry can be created just to record\nwhich environment it runs in (by ``calkit update notebook-env``), so\n``title`` is optional here.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "environment": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the environment in which to run this notebook, if it is not part of the pipeline.",
          "title": "Environment"
        },
        "imported_from": {
          "anyOf": [
            {
              "$ref": "#/$defs/_ImportedFromProject"
            },
            {
              "$ref": "#/$defs/_ImportedFromUrl"
            },
            {
              "$ref": "#/$defs/_ImportedFromDoi"
            },
            {
              "$ref": "#/$defs/_ImportedFromGit"
            },
            {
              "$ref": "#/$defs/_ImportedFromDescription"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where this came from, if it was taken from somewhere else. Notebooks are usually written by a project's own authors, so there is no 'calkit import notebook'; this is here so an entry that does say where it came from is kept rather than dropped, and so 'calkit sync import' can refresh it.",
          "title": "Imported From"
        },
        "path": {
          "title": "Path",
          "type": "string"
        },
        "stage": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Stage"
        },
        "title": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Title"
        }
      },
      "required": [
        "path"
      ],
      "title": "Notebook",
      "type": "object"
    },
    "Output": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "dtype": {
          "default": "float",
          "enum": [
            "int",
            "float",
            "str"
          ],
          "title": "Dtype",
          "type": "string"
        },
        "name": {
          "title": "Name",
          "type": "string"
        },
        "template": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Template"
        }
      },
      "required": [
        "name"
      ],
      "title": "Output",
      "type": "object"
    },
    "OverleafSync": {
      "description": "Configuration for syncing a directory with an Overleaf project.",
      "properties": {
        "push_paths": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Paths only pushed to Overleaf, never pulled back.",
          "title": "Push Paths"
        },
        "sync_paths": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Paths synced in both directions with Overleaf.",
          "title": "Sync Paths"
        },
        "url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "URL of the Overleaf project.",
          "title": "Url"
        }
      },
      "title": "OverleafSync",
      "type": "object"
    },
    "PBSEnvironment": {
      "properties": {
        "default_options": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options passed to qsub by default.",
          "title": "Default Options"
        },
        "default_setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run at the start of every job script.",
          "title": "Default Setup"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "host": {
          "default": "localhost",
          "description": "Host on which to submit jobs, over SSH if not localhost.",
          "title": "Host",
          "type": "string"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Files in the project that 'default_setup' reads, e.g., a setup script it sources. Added as an input to every stage using this environment, so editing one reruns them. Must be inside the project: a stage can't depend on something the repo doesn't carry.",
          "title": "Inputs"
        },
        "kind": {
          "const": "pbs",
          "default": "pbs",
          "title": "Kind",
          "type": "string"
        },
        "max_concurrent_jobs": {
          "anyOf": [
            {
              "minimum": 1,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "How many of this project's jobs may sit in the queue (running or pending) at once. Null means no limit.",
          "title": "Max Concurrent Jobs"
        }
      },
      "title": "PBSEnvironment",
      "type": "object"
    },
    "ParameterIteration": {
      "properties": {
        "parameter": {
          "description": "Name of a project parameter whose list of values to iterate over.",
          "title": "Parameter",
          "type": "string"
        }
      },
      "required": [
        "parameter"
      ],
      "title": "ParameterIteration",
      "type": "object"
    },
    "PathInput": {
      "additionalProperties": true,
      "description": "An input written as an object carrying a path.\n\nPrefer a plain path string. This exists so a stage keeps working when an\noutput is copied verbatim into another stage's ``inputs``, which is how\nentries like ``{path: ..., storage: ...}`` show up in the wild. Only\n``path`` is used: an input is a dependency wherever it happens to be\nstored, so the other keys are carried along and ignored.\n\nExtra keys are allowed deliberately, both to tolerate whatever came along\nwith a copied output and to leave room for object inputs that aren't\npaths at all, e.g., a database table. They are kept rather than dropped,\nsince a stage rewritten back to calkit.yaml (see\n``Pipeline.convert_sbatch_stages``) would otherwise silently lose them.",
      "properties": {
        "path": {
          "description": "Path to the input file or directory.",
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "title": "PathInput",
      "type": "object"
    },
    "PathOutput": {
      "additionalProperties": false,
      "properties": {
        "delete_before_run": {
          "default": true,
          "description": "Delete this output before the stage runs.",
          "title": "Delete Before Run",
          "type": "boolean"
        },
        "path": {
          "description": "Path to the output file or directory.",
          "title": "Path",
          "type": "string"
        },
        "storage": {
          "anyOf": [
            {
              "enum": [
                "git",
                "dvc",
                "dvc-zip"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "dvc",
          "description": "Where to store this output. Use null to leave it untracked.",
          "title": "Storage"
        }
      },
      "required": [
        "path"
      ],
      "title": "PathOutput",
      "type": "object"
    },
    "Pipeline": {
      "additionalProperties": false,
      "description": "The project's reproducible pipeline.",
      "properties": {
        "stages": {
          "additionalProperties": {
            "discriminator": {
              "mapping": {
                "command": "#/$defs/CommandStage",
                "docker-command": "#/$defs/DockerCommandStage",
                "json-to-latex": "#/$defs/JsonToLatexStage",
                "julia-command": "#/$defs/JuliaCommandStage",
                "julia-script": "#/$defs/JuliaScriptStage",
                "jupyter-notebook": "#/$defs/JupyterNotebookStage",
                "latex": "#/$defs/LatexStage",
                "map-paths": "#/$defs/MapPathsStage",
                "marimo-html-wasm": "#/$defs/MarimoHtmlWasmStage",
                "markdown": "#/$defs/MarkdownStage",
                "matlab-command": "#/$defs/MatlabCommandStage",
                "matlab-script": "#/$defs/MatlabScriptStage",
                "procedure": "#/$defs/ProcedureStage",
                "python-script": "#/$defs/PythonScriptStage",
                "quarto": "#/$defs/QuartoStage",
                "r-script": "#/$defs/RScriptStage",
                "sbatch": "#/$defs/SBatchStage",
                "shell-command": "#/$defs/ShellCommandStage",
                "shell-script": "#/$defs/ShellScriptStage",
                "word-to-pdf": "#/$defs/WordToPdfStage"
              },
              "propertyName": "kind"
            },
            "oneOf": [
              {
                "$ref": "#/$defs/PythonScriptStage"
              },
              {
                "$ref": "#/$defs/LatexStage"
              },
              {
                "$ref": "#/$defs/QuartoStage"
              },
              {
                "$ref": "#/$defs/JsonToLatexStage"
              },
              {
                "$ref": "#/$defs/MatlabScriptStage"
              },
              {
                "$ref": "#/$defs/MatlabCommandStage"
              },
              {
                "$ref": "#/$defs/ShellCommandStage"
              },
              {
                "$ref": "#/$defs/ShellScriptStage"
              },
              {
                "$ref": "#/$defs/DockerCommandStage"
              },
              {
                "$ref": "#/$defs/CommandStage"
              },
              {
                "$ref": "#/$defs/RScriptStage"
              },
              {
                "$ref": "#/$defs/WordToPdfStage"
              },
              {
                "$ref": "#/$defs/JupyterNotebookStage"
              },
              {
                "$ref": "#/$defs/JuliaScriptStage"
              },
              {
                "$ref": "#/$defs/JuliaCommandStage"
              },
              {
                "$ref": "#/$defs/SBatchStage"
              },
              {
                "$ref": "#/$defs/MapPathsStage"
              },
              {
                "$ref": "#/$defs/MarimoHtmlWasmStage"
              },
              {
                "$ref": "#/$defs/MarkdownStage"
              },
              {
                "$ref": "#/$defs/ProcedureStage"
              }
            ]
          },
          "title": "Stages",
          "type": "object"
        }
      },
      "required": [
        "stages"
      ],
      "title": "Pipeline",
      "type": "object"
    },
    "PixiEnvironment": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "kind": {
          "const": "pixi",
          "default": "pixi",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the environment within the Pixi manifest.",
          "title": "Name"
        },
        "path": {
          "description": "Path to the Pixi manifest file.",
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "title": "PixiEnvironment",
      "type": "object"
    },
    "Presentation": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A longer description.",
          "title": "Description"
        },
        "kind": {
          "anyOf": [
            {
              "enum": [
                "slides",
                "poster"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "What kind of presentation this is.",
          "title": "Kind"
        },
        "path": {
          "description": "Path to the file, relative to the project root.",
          "title": "Path",
          "type": "string"
        },
        "stage": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the pipeline stage that produces this.",
          "title": "Stage"
        },
        "title": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A human-readable title.",
          "title": "Title"
        }
      },
      "required": [
        "path"
      ],
      "title": "Presentation",
      "type": "object"
    },
    "Procedure": {
      "description": "A procedure, typically executed by a human, written out in full.",
      "not": {
        "required": [
          "path"
        ]
      },
      "properties": {
        "description": {
          "title": "Description",
          "type": "string"
        },
        "imported_from": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Imported From"
        },
        "steps": {
          "items": {
            "$ref": "#/$defs/ProcedureStep"
          },
          "title": "Steps",
          "type": "array"
        },
        "title": {
          "title": "Title",
          "type": "string"
        }
      },
      "required": [
        "title",
        "description",
        "steps"
      ],
      "title": "Procedure",
      "type": "object"
    },
    "ProcedureFile": {
      "additionalProperties": false,
      "description": "A procedure kept in its own YAML or JSON file.\n\nThe file holds what an inline ``Procedure`` would: ``title``,\n``description``, and ``steps``. Nothing else can be given alongside\n``path``, so a procedure is defined in one place, not split between\ncalkit.yaml and the file it points at. ``calkit.procedures.load``\nresolves one of these to the ``Procedure`` it names.",
      "properties": {
        "path": {
          "description": "Path to a YAML or JSON file holding the procedure, relative to the project root.",
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "title": "ProcedureFile",
      "type": "object"
    },
    "ProcedureInput": {
      "description": "An input that might be entered while running a procedure.\n\nAttributes\n----------\nname : str\n    The name of the input. This will be displayed to the user at the\n    prompt like 'Enter {name}:'. Note the column name for the log is the\n    key used to identify this input, and they can be different.\ndtype : 'int', 'bool', 'str', or 'float'\n    The datatype of the input.\nunits : str\n    Units of the input value.\ndescription : str\n    Optional longer description of the input.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "dtype": {
          "anyOf": [
            {
              "enum": [
                "int",
                "bool",
                "str",
                "float"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Dtype"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "units": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Units"
        }
      },
      "title": "ProcedureInput",
      "type": "object"
    },
    "ProcedureStage": {
      "additionalProperties": false,
      "description": "A procedure carried out by a person, as a pipeline stage.\n\nNot everything can be automated. A sample prepared by hand, a rig\nswitched on and read off, a survey administered: the work is real and\neverything downstream rests on it, but nothing in the pipeline knows\nwhether it has happened. Declaring it as a stage puts a manual step\nwhere automated ones are: running the pipeline walks the person\nthrough the procedure's steps, prompting for whatever it asks them to\nrecord, and the run log becomes an output the next stage reads like\nany other.\n\nThe log is a directory of one CSV per run, kept in Git rather than\nDVC, and never cleared before a run: earlier runs are data, not stale\noutput. Declaring further ``outputs`` is allowed for a procedure that\nwrites something else too, e.g., a file the instrument saves.",
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "default": "_system",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "procedure",
          "default": "procedure",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "no_commit": {
          "default": false,
          "description": "Do not commit the run log after each step. The log is still written; only the commit per step is skipped.",
          "title": "No Commit",
          "type": "boolean"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "procedure_name": {
          "description": "Name of the procedure to carry out, as it is keyed under 'procedures' in calkit.yaml.",
          "title": "Procedure Name",
          "type": "string"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "procedure_name"
      ],
      "title": "ProcedureStage",
      "type": "object"
    },
    "ProcedureStep": {
      "properties": {
        "cmd": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Cmd"
        },
        "details": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Details"
        },
        "inputs": {
          "anyOf": [
            {
              "additionalProperties": {
                "$ref": "#/$defs/ProcedureInput"
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Inputs"
        },
        "summary": {
          "title": "Summary",
          "type": "string"
        },
        "wait_after_s": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Wait After S"
        },
        "wait_before_s": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Wait Before S"
        }
      },
      "required": [
        "summary"
      ],
      "title": "ProcedureStep",
      "type": "object"
    },
    "Publication": {
      "description": "A publication the project produced, or one it builds upon.\n\nWhether it has been published is not written down but derived: a\npublication of record has a DOI, so ``is_published`` is true exactly\nwhen ``doi`` is set, and reads the same on the hub and in the CLI.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A longer description.",
          "title": "Description"
        },
        "doi": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "This publication's own DOI, once it has one. Setting it is what marks the publication as published.",
          "title": "Doi"
        },
        "imported_from": {
          "anyOf": [
            {
              "$ref": "#/$defs/_ImportedFromProject"
            },
            {
              "$ref": "#/$defs/_ImportedFromUrl"
            },
            {
              "$ref": "#/$defs/_ImportedFromDoi"
            },
            {
              "$ref": "#/$defs/_ImportedFromGit"
            },
            {
              "$ref": "#/$defs/_ImportedFromDescription"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where this came from, if imported.",
          "title": "Imported From"
        },
        "kind": {
          "anyOf": [
            {
              "enum": [
                "journal-article",
                "conference-paper",
                "proposal",
                "report",
                "blog",
                "book",
                "thesis",
                "phd-thesis"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Kind"
        },
        "path": {
          "description": "Path to the file, relative to the project root.",
          "title": "Path",
          "type": "string"
        },
        "stage": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the pipeline stage that produces this.",
          "title": "Stage"
        },
        "title": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A human-readable title.",
          "title": "Title"
        }
      },
      "required": [
        "path"
      ],
      "title": "Publication",
      "type": "object"
    },
    "PublicationEvidence": {
      "description": "Evidence in the form of a publication.\n\nThe pointer to *where* in the publication the evidence lives is split in\ntwo, in the spirit of a W3C selector: ``section`` is for the reader, and\n``label`` is an anchor in the source (e.g., a LaTeX ``\\label``) that\n``calkit check questions`` can verify still exists, so the reference\ncannot rot when the document is reorganized.",
      "properties": {
        "explanation": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Explanation"
        },
        "git_ref": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Git reference (branch, tag, or commit hash) pointing to the version of the repository where the publication can be found.",
          "title": "Git Ref"
        },
        "kind": {
          "const": "publication",
          "default": "publication",
          "title": "Kind",
          "type": "string"
        },
        "label": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Anchor for the section in the publication's source, e.g., a LaTeX label such as 'sec:results'. Checked against the source of the LaTeX stage that builds the publication.",
          "title": "Label"
        },
        "path": {
          "title": "Path",
          "type": "string"
        },
        "section": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Section or subsection of the publication where the evidence is presented, as a reader would find it, e.g., '4.2' or 'Results'.",
          "title": "Section"
        }
      },
      "required": [
        "path"
      ],
      "title": "PublicationEvidence",
      "type": "object"
    },
    "PythonScriptStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "args": {
          "default": [],
          "description": "Arguments passed to the script.",
          "items": {
            "type": "string"
          },
          "title": "Args",
          "type": "array"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "python-script",
          "default": "python-script",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "script_path": {
          "description": "Path to the Python script to run.",
          "title": "Script Path",
          "type": "string"
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "script_path"
      ],
      "title": "PythonScriptStage",
      "type": "object"
    },
    "QuartoStage": {
      "additionalProperties": false,
      "description": "A stage that renders a Quarto document.\n\nCalkit controls only what belongs on the CLI: which environment to\nrender in, the target document, and (optionally) the output format and\nextra ``quarto render`` arguments. The output format(s) and any other\nrendering behavior are left to the document/``_quarto.yml`` metadata, so\nthere is no redundancy between the pipeline definition and the doc.\n\nOutputs are declared explicitly via ``outputs`` rather than parsed out\nof the Quarto document, since a document can emit multiple formats to\narbitrary paths. As with other stages, plain string outputs are\nDVC-cached by default; use a ``PathOutput`` to store an output with Git\ninstead.",
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "args": {
          "default": [],
          "description": "Extra arguments passed to 'quarto render'.",
          "items": {
            "type": "string"
          },
          "title": "Args",
          "type": "array"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "quarto",
          "default": "quarto",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "target_path": {
          "description": "Path to the Quarto document to render.",
          "title": "Target Path",
          "type": "string"
        },
        "to": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Output format, passed to 'quarto render --to'. Defaults to what the document's metadata specifies.",
          "title": "To"
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "target_path"
      ],
      "title": "QuartoStage",
      "type": "object"
    },
    "Question": {
      "description": "A question the project hopes to answer.\n\nEach piece of evidence defines what it points at inline, discriminated by\n``kind``, so citing something doesn't require declaring it at the top\nlevel first. The top-level collections are for the things worth naming or\nannotating, not a registry that evidence has to be registered in.\n\nKeep the answer to the claim itself and let the evidence carry the\nnumbers: a ``value`` evidence entry can be templated into the text by\nname, as in ``\"about {improvement:.1f}x\"``, so it is read from the\nresults file rather than retyped. Longer reasoning belongs in the\npublication, pointed at with a publication evidence entry and its\n``section``.\n\nAn answer is a claim about the evidence as it was when the answer was\nlast edited, and Git records when that was. ``calkit check questions``\nreports a question as stale when any of its evidence has changed since\nthat commit, so editing the question after re-reading it against the\nnew evidence is how to say it still holds.",
      "properties": {
        "answer": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Answer"
        },
        "evidence": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/FigureEvidence"
                  },
                  {
                    "$ref": "#/$defs/ResultsEvidence"
                  },
                  {
                    "$ref": "#/$defs/ValueEvidence"
                  },
                  {
                    "$ref": "#/$defs/TableEvidence"
                  },
                  {
                    "$ref": "#/$defs/PublicationEvidence"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Evidence"
        },
        "hypothesis": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Hypothesis"
        },
        "notes": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Free-form notes, e.g., why a question is still open and what would answer it. Unlike an answer, notes make no claim, so a question with notes and no answer is reported as unanswered rather than as an answer lacking evidence.",
          "title": "Notes"
        },
        "question": {
          "title": "Question",
          "type": "string"
        }
      },
      "required": [
        "question"
      ],
      "title": "Question",
      "type": "object"
    },
    "REnvironment": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "kind": {
          "const": "renv",
          "default": "renv",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "description": "Path to the project's DESCRIPTION file. The renv lock file is created next to it.",
          "title": "Path",
          "type": "string"
        },
        "prefix": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path at which to create the environment.",
          "title": "Prefix"
        }
      },
      "required": [
        "path"
      ],
      "title": "REnvironment",
      "type": "object"
    },
    "RScriptStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "args": {
          "default": [],
          "description": "Arguments passed to the script.",
          "items": {
            "type": "string"
          },
          "title": "Args",
          "type": "array"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "r-script",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "script_path": {
          "description": "Path to the R script to run.",
          "title": "Script Path",
          "type": "string"
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "kind",
        "environment",
        "script_path"
      ],
      "title": "RScriptStage",
      "type": "object"
    },
    "RangeIteration": {
      "properties": {
        "range": {
          "$ref": "#/$defs/RangeIterationParams",
          "description": "Bounds of the range over which to iterate."
        }
      },
      "required": [
        "range"
      ],
      "title": "RangeIteration",
      "type": "object"
    },
    "RangeIterationParams": {
      "properties": {
        "start": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "number"
            }
          ],
          "description": "First value in the range, which is included.",
          "title": "Start"
        },
        "step": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "number"
            }
          ],
          "default": 1,
          "description": "Amount by which to increment each value.",
          "title": "Step"
        },
        "stop": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "number"
            }
          ],
          "description": "Value at which to stop, which is not included.",
          "title": "Stop"
        }
      },
      "required": [
        "start",
        "stop"
      ],
      "title": "RangeIterationParams",
      "type": "object"
    },
    "ReferenceCollection": {
      "properties": {
        "files": {
          "default": [],
          "items": {
            "$ref": "#/$defs/ReferenceFile"
          },
          "title": "Files",
          "type": "array"
        },
        "path": {
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "title": "ReferenceCollection",
      "type": "object"
    },
    "ReferenceFile": {
      "properties": {
        "key": {
          "title": "Key",
          "type": "string"
        },
        "path": {
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path",
        "key"
      ],
      "title": "ReferenceFile",
      "type": "object"
    },
    "Release": {
      "properties": {
        "calkit_version": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Calkit Version"
        },
        "date": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Date"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "doi": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Doi"
        },
        "git_rev": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated; recorded in .calkit/imports.json instead, with the other things a fetch resolves to.",
          "title": "Git Rev"
        },
        "includes_pipeline": {
          "default": false,
          "title": "Includes Pipeline",
          "type": "boolean"
        },
        "internal": {
          "default": false,
          "title": "Internal",
          "type": "boolean"
        },
        "kind": {
          "enum": [
            "project",
            "publication",
            "dataset",
            "figure",
            "presentation",
            "software",
            "model"
          ],
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Path"
        },
        "publisher": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Publisher"
        },
        "record_id": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Record Id"
        },
        "stored_path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Stored Path"
        },
        "url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Url"
        }
      },
      "required": [
        "kind"
      ],
      "title": "Release",
      "type": "object"
    },
    "Requirement": {
      "description": "Something that must be true of a machine before the project runs.\n\nFour kinds are supported:\n\n- ``app``: an executable that must be on ``PATH``, optionally\n  satisfying a ``version_spec``.\n- ``env-var``: an environmental variable that must be defined.\n- ``setup``: a per-machine precondition that isn't a file -- e.g.,\n  the user must have authenticated a CLI like ``gh auth login``.\n  A ``setup`` requirement declares ``check_command`` (a shell command\n  whose exit code determines whether it is satisfied) and\n  ``setup_command`` (run on a TTY when the user agrees, or printed\n  as a fix-it command otherwise). To run either inside a project\n  environment, prefix it with ``calkit xenv -n <env> --`` explicitly\n  rather than relying on an implicit wrap. ``cache_ttl`` skips\n  re-probing slow checks.\n- ``calkit-config``: a value that must be set in the user's Calkit\n  configuration.\n\nThese name a thing that must be present, so each has a ``name``. The\nproperties of a machine that can't be installed -- how many CPUs it\nhas, what OS it runs -- are constrained by\n``SystemNumberRequirement`` and ``SystemValueRequirement``\ninstead, which name a property rather than a thing.",
      "properties": {
        "cache_ttl": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Cache Ttl"
        },
        "check_command": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Check Command"
        },
        "default": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Default"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "kind": {
          "default": "app",
          "enum": [
            "app",
            "env-var",
            "setup",
            "calkit-config"
          ],
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "title": "Name",
          "type": "string"
        },
        "notes": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Notes"
        },
        "setup_command": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Setup Command"
        },
        "version_spec": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Version specifier an 'app' must satisfy, e.g. '>=2.40'. A string requirement like 'git>=2.40' is shorthand for this.",
          "title": "Version Spec"
        }
      },
      "required": [
        "name"
      ],
      "title": "Requirement",
      "type": "object"
    },
    "RequirementAttrs": {
      "description": "A requirement's properties, as written under ``{name: {...}}``.\n\n``Requirement`` is this plus the name; the mapping form supplies the\nname as its key instead.",
      "properties": {
        "cache_ttl": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Cache Ttl"
        },
        "check_command": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Check Command"
        },
        "default": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Default"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "kind": {
          "default": "app",
          "enum": [
            "app",
            "env-var",
            "setup",
            "calkit-config"
          ],
          "title": "Kind",
          "type": "string"
        },
        "notes": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Notes"
        },
        "setup_command": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Setup Command"
        },
        "version_spec": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Version Spec"
        }
      },
      "title": "RequirementAttrs",
      "type": "object"
    },
    "Result": {
      "description": "A finding the project produced: a value, a table, a map, or a file.\n\nLike the other artifacts, a result is identified by its path, but unlike\nthem several results can share one file, e.g., a mean and a standard\ndeviation both read out of one summary file. ``key`` is what tells those\napart, so the identity is really the ``(path, key)`` pair. Which part of\na file a result refers to is left open on purpose: other forms of\naddressing can be added without reshaping what a result is.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A longer description.",
          "title": "Description"
        },
        "key": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Which value within the file this result refers to, e.g., 'metrics.mean'. Omit it when the result is the whole file.",
          "title": "Key"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A short handle for referring to this result, which stays stable if the file is renamed. Optional, since the path and key already identify it.",
          "title": "Name"
        },
        "path": {
          "description": "Path to the file, relative to the project root.",
          "title": "Path",
          "type": "string"
        },
        "stage": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the pipeline stage that produces this.",
          "title": "Stage"
        },
        "title": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A human-readable title.",
          "title": "Title"
        }
      },
      "required": [
        "path"
      ],
      "title": "Result",
      "type": "object"
    },
    "ResultsEvidence": {
      "description": "Evidence in the form of a results file: a set of values, a table, a\nmap, whatever the pipeline wrote. For one value inside such a file, use\n``value`` evidence, which can be templated into the answer.",
      "properties": {
        "explanation": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Explanation"
        },
        "git_ref": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Git reference (branch, tag, or commit hash) pointing to the version of the repository where the result can be found.",
          "title": "Git Ref"
        },
        "key": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Deprecated: use 'value' evidence for a single value within a results file.",
          "title": "Key"
        },
        "kind": {
          "const": "result",
          "default": "result",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "title": "ResultsEvidence",
      "type": "object"
    },
    "SBatchStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "args": {
          "default": [],
          "description": "Arguments passed to the script.",
          "items": {
            "type": "string"
          },
          "title": "Args",
          "type": "array"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "sbatch",
          "default": "sbatch",
          "title": "Kind",
          "type": "string"
        },
        "log_path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path at which to write the job log.",
          "title": "Log Path"
        },
        "log_storage": {
          "anyOf": [
            {
              "enum": [
                "git",
                "dvc"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "git",
          "description": "Where to store the job log.",
          "title": "Log Storage"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "sbatch_options": {
          "default": [],
          "description": "Options passed to sbatch.",
          "items": {
            "type": "string"
          },
          "title": "Sbatch Options",
          "type": "array"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "script_path": {
          "description": "Path to the script to submit.",
          "title": "Script Path",
          "type": "string"
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "environment",
        "script_path"
      ],
      "title": "SBatchStage",
      "type": "object"
    },
    "SetupRequirement": {
      "description": "A ``setup`` requirement, whose ``name`` may be omitted.\n\nA single anonymous setup step is common enough that requiring a name\nadds friction, so Calkit synthesizes a stable ``setup-<hash>`` one from\n``check_command``. This is a separate model rather than a loosening of\n``Requirement.name`` so the published schema still rejects an ``app``\nor ``env-var`` requirement with no name, where the name is the\nidentity.",
      "properties": {
        "cache_ttl": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Cache Ttl"
        },
        "check_command": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Check Command"
        },
        "default": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Default"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "kind": {
          "const": "setup",
          "default": "setup",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "notes": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Notes"
        },
        "setup_command": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Setup Command"
        },
        "version_spec": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Version specifier an 'app' must satisfy, e.g. '>=2.40'. A string requirement like 'git>=2.40' is shorthand for this.",
          "title": "Version Spec"
        }
      },
      "title": "SetupRequirement",
      "type": "object"
    },
    "ShellCommandStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "command": {
          "description": "Shell command to run.",
          "title": "Command",
          "type": "string"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "shell-command",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "shell": {
          "default": "bash",
          "description": "Shell in which to run the command.",
          "enum": [
            "sh",
            "bash",
            "zsh"
          ],
          "title": "Shell",
          "type": "string"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "kind",
        "environment",
        "command"
      ],
      "title": "ShellCommandStage",
      "type": "object"
    },
    "ShellScriptStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "args": {
          "default": [],
          "description": "Arguments passed to the script.",
          "items": {
            "type": "string"
          },
          "title": "Args",
          "type": "array"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "description": "Name of the environment in which to run this stage.",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "shell-script",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "script_path": {
          "description": "Path to the shell script to run.",
          "title": "Script Path",
          "type": "string"
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "shell": {
          "default": "bash",
          "description": "Shell in which to run the script.",
          "enum": [
            "sh",
            "bash",
            "zsh"
          ],
          "title": "Shell",
          "type": "string"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        }
      },
      "required": [
        "kind",
        "environment",
        "script_path"
      ],
      "title": "ShellScriptStage",
      "type": "object"
    },
    "ShowcaseApp": {
      "description": "Show an app in the project's showcase, by its key in ``apps``.",
      "properties": {
        "app": {
          "title": "App",
          "type": "string"
        }
      },
      "required": [
        "app"
      ],
      "title": "ShowcaseApp",
      "type": "object"
    },
    "ShowcaseFigure": {
      "properties": {
        "figure": {
          "title": "Figure",
          "type": "string"
        }
      },
      "required": [
        "figure"
      ],
      "title": "ShowcaseFigure",
      "type": "object"
    },
    "ShowcaseMarkdown": {
      "properties": {
        "markdown": {
          "title": "Markdown",
          "type": "string"
        }
      },
      "required": [
        "markdown"
      ],
      "title": "ShowcaseMarkdown",
      "type": "object"
    },
    "ShowcaseMarkdownFile": {
      "properties": {
        "markdown_file": {
          "title": "Markdown File",
          "type": "string"
        }
      },
      "required": [
        "markdown_file"
      ],
      "title": "ShowcaseMarkdownFile",
      "type": "object"
    },
    "ShowcaseNotebook": {
      "properties": {
        "notebook": {
          "title": "Notebook",
          "type": "string"
        }
      },
      "required": [
        "notebook"
      ],
      "title": "ShowcaseNotebook",
      "type": "object"
    },
    "ShowcasePublication": {
      "properties": {
        "publication": {
          "title": "Publication",
          "type": "string"
        }
      },
      "required": [
        "publication"
      ],
      "title": "ShowcasePublication",
      "type": "object"
    },
    "ShowcaseText": {
      "properties": {
        "text": {
          "title": "Text",
          "type": "string"
        }
      },
      "required": [
        "text"
      ],
      "title": "ShowcaseText",
      "type": "object"
    },
    "ShowcaseYamlFile": {
      "properties": {
        "object_name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Object Name"
        },
        "yaml_file": {
          "title": "Yaml File",
          "type": "string"
        }
      },
      "required": [
        "yaml_file"
      ],
      "title": "ShowcaseYamlFile",
      "type": "object"
    },
    "SlurmEnvironment": {
      "properties": {
        "default_options": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options passed to sbatch by default.",
          "title": "Default Options"
        },
        "default_setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run at the start of every job script.",
          "title": "Default Setup"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "host": {
          "default": "localhost",
          "description": "Host on which to submit jobs, over SSH if not localhost.",
          "title": "Host",
          "type": "string"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Files in the project that 'default_setup' reads, e.g., a setup script it sources. Added as an input to every stage using this environment, so editing one reruns them. Must be inside the project: a stage can't depend on something the repo doesn't carry.",
          "title": "Inputs"
        },
        "kind": {
          "const": "slurm",
          "default": "slurm",
          "title": "Kind",
          "type": "string"
        },
        "max_concurrent_jobs": {
          "anyOf": [
            {
              "minimum": 1,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "How many of this project's jobs may sit in the queue (running or pending) at once. Submissions beyond the limit wait for a slot, so an iterated stage does not flood a shared cluster's queue with every one of its jobs at the same time. Null means no limit.",
          "title": "Max Concurrent Jobs"
        }
      },
      "title": "SlurmEnvironment",
      "type": "object"
    },
    "Software": {
      "properties": {
        "description": {
          "title": "Description",
          "type": "string"
        },
        "path": {
          "title": "Path",
          "type": "string"
        },
        "title": {
          "title": "Title",
          "type": "string"
        }
      },
      "required": [
        "title",
        "path",
        "description"
      ],
      "title": "Software",
      "type": "object"
    },
    "StageIteration": {
      "description": "A model for the ``iterate_over`` key in a stage definition.\n\nIf ``arg_name`` is a list, ``values`` also must be a list of lists with\neach sublist the length of ``arg_name``.",
      "properties": {
        "arg_name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            }
          ],
          "description": "Name(s) of the argument(s) to substitute into the stage's command and paths.",
          "title": "Arg Name"
        },
        "values": {
          "description": "Values over which to iterate.",
          "items": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "string"
              },
              {
                "$ref": "#/$defs/RangeIteration"
              },
              {
                "$ref": "#/$defs/ParameterIteration"
              },
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "number"
                    },
                    {
                      "type": "string"
                    }
                  ]
                },
                "type": "array"
              }
            ]
          },
          "title": "Values",
          "type": "array"
        }
      },
      "required": [
        "arg_name",
        "values"
      ],
      "title": "StageIteration",
      "type": "object"
    },
    "StageSchedulerOptions": {
      "description": "Parameters for running a stage on a job scheduler (SLURM or PBS).\n\nThe environment-level ``default_options`` are applied by ``calkit\nscheduler batch`` at submission time, in the mode ``env_default_options``\nnames: ``replace`` (the default) uses them only when the stage names\nnone of its own, ``merge`` puts them before the stage's, and ``ignore``\nnever applies them.\n\n``setup`` and ``env_default_setup`` were once written here too. They\nbelong to the stage, not to the scheduler: a stage on a ``system``\nenvironment has setup commands and no scheduler at all. They are still\naccepted here and hoisted onto the stage when it loads.",
      "properties": {
        "env_default_options": {
          "default": "replace",
          "description": "How to combine 'options' with the environment's default_options.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Options",
          "type": "string"
        },
        "env_default_setup": {
          "default": "replace",
          "deprecated": true,
          "description": "Deprecated; set 'env_default_setup' on the stage itself, alongside its 'setup'.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "log_path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path at which to write the job log.",
          "title": "Log Path"
        },
        "log_storage": {
          "anyOf": [
            {
              "enum": [
                "git",
                "dvc"
              ],
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "git",
          "description": "Where to store the job log.",
          "title": "Log Storage"
        },
        "options": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options passed to the scheduler at submission.",
          "title": "Options"
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated; set 'setup' on the stage itself. Setup commands are not a scheduler concept, and a stage on a 'system' environment needs them too.",
          "title": "Setup"
        }
      },
      "title": "StageSchedulerOptions",
      "type": "object"
    },
    "StaticHtmlApp": {
      "additionalProperties": false,
      "description": "An app served as static files, with no backend.\n\n``path`` points at the HTML file itself rather than its directory, since\nthe kind names a file type. The containing directory is the serving root,\nso sibling assets are served alongside it, and ``index.html`` is implied\nwhen a directory is served.\n\nThere is no ``url`` field: for apps a hub serves, the URL is derived from\nthe project and the app's key, and a value written here could only go\nstale.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "kind": {
          "const": "static-html",
          "default": "static-html",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "title": "Path",
          "type": "string"
        },
        "stage": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Stage"
        },
        "title": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Title"
        }
      },
      "required": [
        "path"
      ],
      "title": "StaticHtmlApp",
      "type": "object"
    },
    "Subproject": {
      "description": "A smaller project executed as part of this one.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "path": {
          "description": "Path to the subproject directory, relative to this project's root.",
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "title": "Subproject",
      "type": "object"
    },
    "SystemEnvironment": {
      "description": "The machine as it is, with nothing built, installed, or isolated.\n\nAn escape hatch for software Calkit doesn't manage, e.g., a site-wide\nmodule system or a hand-built toolchain. Nothing is pinned by default,\nsince opting out of isolation is the whole point of this kind, so\n``lock`` is how a project says which properties of the machine its\nresults actually depend on.\n\nLocked properties are written to the environment's lock file, which\nstages depend on, so moving to a machine where one of them differs\ninvalidates the cached result rather than silently reusing it.\n\n``requirements`` is the other half, and answers a different question.\nIt says what must be *true* of this machine -- apps that must be\ninstalled, variables that must be set, at least this many CPUs -- and\nis checked before anything runs, on the machine the environment names.\nA requirement that fails stops the run and says how to fix it; a locked\nproperty that changes silently invalidates a cached result. One gates,\nthe other pins, so a property that matters both ways is written in both\nplaces.\n\n``default_setup`` is what has to be *done* on this machine before a\nstage can run: sourcing a site setup script, loading modules, putting a\nhand-built toolchain on the ``PATH``. It runs in the same shell as the\nstage's own command, so a variable it sets or a function it defines is\nin scope for the stage, whether or not it was exported -- only a child\nprocess needs that. This is why it can't be a ``setup`` requirement:\nthose run in a shell of their own and are cached, since they check\nwhether something has been done rather than doing it every time.\n\nIt is not recorded in the environment's lock file. The pipeline\ncompiler merges it with each stage's own ``setup`` and writes the\nresult beside the pipeline, which the stage depends on -- so changing\nit reruns exactly the stages that run it, and not the ones whose\n``env_default_setup`` means they never do.\n\n``host`` names the machine. SSH is how a machine is reached, not a kind\nof environment, so there is no separate ``ssh`` kind: a system env whose\nhost isn't this machine is reached over SSH, and one whose host is this\nmachine runs here, the same way a SLURM env does. The built-in\n``_system`` environment is shorthand for this kind on ``localhost``\nwith nothing locked.\n\n``machine_id`` says *which* machine, where ``host`` only says what it\nanswers to. Names are renamed, resolve differently from different\nnetworks, and are reused; a project that means one particular machine\ncan name it here instead and have that survive all of it. It replaces\nthe name in deciding whether this is that machine, and is checked again\non the far end when it isn't -- so a host that has come to point at a\ndifferent box is reported rather than run on. ``host`` is still what\nreaches it, so both are worth declaring for a machine that isn't this\none. Run ``calkit describe system`` on a machine to read its ID.\n\nDeclaring one says where to run, which is a separate question from\nwhether results depend on the machine: moving a project to a new one\nand updating this need not invalidate everything computed on the old\none. Whether it does is left to ``lock``, where ``machine-id`` is\navailable for projects whose results really are machine-specific.\n\n``wdir`` is the project's workspace on that host -- the directory the\nstage runs in. It defaults to\n``~/.calkit/workspaces/<hub>/<owner>/<name>``, so a project that just\nnames a host lands somewhere predictable rather than having to spell\nout a path that is the same on every machine anyway. Qualified by hub\nand owner because a host is shared, and hidden because transfers check\nout with ``--force``: a path that looks like the user's own checkout is\none whose edits would be silently destroyed.\n\nWhat moves in and out of that workspace is deliberately not declared\nhere. An environment doesn't know which files a stage reads, so a list\nkept alongside it can fall behind the pipeline and quietly run against\nstale inputs; the paths are taken from the stage instead.",
      "properties": {
        "default_setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run in the same shell, before every stage that uses this environment, e.g. 'module load cuda' or a site setup script that exports compiler paths. Merged with each stage's own 'setup' when the pipeline is compiled and written beside it, which the stage depends on, so changing them reruns the stages that actually run them.",
          "title": "Default Setup"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "host": {
          "default": "localhost",
          "description": "Host on which to run. Reached over SSH unless it names this machine.",
          "title": "Host",
          "type": "string"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Files in the project that 'default_setup' reads, e.g., a setup script it sources. Added as an input to every stage using this environment, so editing one reruns them. Must be inside the project: a stage can't depend on something the repo doesn't carry.",
          "title": "Inputs"
        },
        "kind": {
          "const": "system",
          "default": "system",
          "title": "Kind",
          "type": "string"
        },
        "lock": {
          "default": [],
          "description": "Properties of the machine this environment's results depend on. Stages rerun when a locked property changes. Empty means nothing about the machine is pinned.",
          "items": {
            "enum": [
              "os",
              "os-version",
              "platform",
              "machine",
              "processor",
              "hostname",
              "machine-id",
              "cpu-count",
              "memory-gb",
              "python-version",
              "python-implementation",
              "git-version",
              "docker-version",
              "conda-version",
              "mamba-version",
              "uv-version",
              "pixi-version",
              "julia-version",
              "juliaup-version",
              "rscript-version",
              "brew-version"
            ],
            "type": "string"
          },
          "title": "Lock",
          "type": "array"
        },
        "machine_id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Stable identifier of the machine to run on, as reported by 'calkit describe system'. Decides whether this is that machine, in place of matching 'host' by name; 'host' is still how the machine is reached when it isn't this one. Says where to run, not that results depend on the machine; lock 'machine-id' for that.",
          "title": "Machine Id"
        },
        "requirements": {
          "default": [],
          "description": "What must be true of this machine before stages run on it: apps on PATH, environmental variables, setup steps, and constraints on properties like CPU count. Checked on the machine this environment names, which is not necessarily this one.",
          "items": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "$ref": "#/$defs/SystemNumberRequirement"
              },
              {
                "$ref": "#/$defs/SystemValueRequirement"
              },
              {
                "$ref": "#/$defs/SetupRequirement"
              },
              {
                "$ref": "#/$defs/Requirement"
              },
              {
                "additionalProperties": {
                  "anyOf": [
                    {
                      "$ref": "#/$defs/RequirementAttrs"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "type": "object"
              }
            ]
          },
          "title": "Requirements",
          "type": "array"
        },
        "shell": {
          "default": "bash",
          "description": "Shell in which setup commands run, both 'default_setup' and a stage's own 'setup', together with the stage's command. Defaults to bash, since 'source' is a bashism and sourcing a setup script is the usual reason to have setup commands. Ignored when neither this environment nor any stage using it has setup commands. Setting it to anything but 'bash' is recorded in the environment's lock file -- unlike the commands themselves, the shell isn't in the compiled command -- so stages that run setup commands rerun when it changes.",
          "enum": [
            "sh",
            "bash",
            "zsh"
          ],
          "title": "Shell",
          "type": "string"
        },
        "ssh_key": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path to the SSH private key used to reach another host. Left to SSH and its agent by default.",
          "title": "Ssh Key"
        },
        "user": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "User to connect as. Left to SSH by default, which resolves it from ~/.ssh/config or falls back to the current user.",
          "title": "User"
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The project's workspace on the host, in which stages run. A relative path is taken from the connecting user's home directory. Defaults to '.calkit/workspaces/<hub>/<owner>/<name>'.",
          "title": "Wdir"
        }
      },
      "title": "SystemEnvironment",
      "type": "object"
    },
    "SystemNumberRequirement": {
      "description": "A bound on a numeric property of the machine.\n\nA property is not a thing that can be installed, so there is nothing to\nname and nothing to offer to fix: the check either passes on this\nmachine or reports what it found against what was asked for.\n\nAt least one bound must be given. An entry that constrains nothing says\nnothing -- if the intent is 'results depend on this property', that is\nwhat a ``system`` environment's ``lock`` is for.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "kind": {
          "description": "Which numeric property of the machine to constrain.",
          "enum": [
            "cpu-count",
            "memory-gb"
          ],
          "title": "Kind",
          "type": "string"
        },
        "max": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Largest acceptable value, inclusive.",
          "title": "Max"
        },
        "min": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Smallest acceptable value, inclusive.",
          "title": "Min"
        }
      },
      "required": [
        "kind"
      ],
      "title": "SystemNumberRequirement",
      "type": "object"
    },
    "SystemValueRequirement": {
      "description": "A constraint on a string-valued property of the machine.\n\n``equals`` matches exactly, case-insensitively, and a list of values\nmeans any of them will do. ``version_spec`` compares as a version, for\nproperties like ``os-version`` and ``python-version`` where '>=' means\nsomething.\n\nAt least one of the two must be given, for the same reason a numeric\nrequirement needs a bound.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Description"
        },
        "equals": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Value the property must have, matched case-insensitively. A list means any one of them is acceptable.",
          "title": "Equals"
        },
        "kind": {
          "description": "Which property of the machine to constrain.",
          "enum": [
            "os",
            "os-version",
            "platform",
            "machine",
            "processor",
            "hostname",
            "machine-id",
            "python-version",
            "python-implementation"
          ],
          "title": "Kind",
          "type": "string"
        },
        "version_spec": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "PEP 440 version specifier the property must satisfy, e.g. '>=3.11'. For properties that are versions.",
          "title": "Version Spec"
        }
      },
      "required": [
        "kind"
      ],
      "title": "SystemValueRequirement",
      "type": "object"
    },
    "Table": {
      "description": "Tabular data, whether it's the finding itself or how one is shown.\n\nIdentified by path, like the other artifacts, and cited that way.\n\nDeclaring one is optional: evidence says what it points at inline via\n``kind``, so an entry here is only needed when the table is worth a title\nand a description of its own.\n\nDeliberately nothing beyond the shared artifact fields yet. A ``name``,\nfor referring to a table symbolically, and ``columns`` both want to exist\neventually, but neither has anything reading it today, and columns need\nper-column types and units that belong with symbol metadata rather than\nbeing invented separately here. Both are free to add later; a field\nshipped early is not free to remove.",
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A longer description.",
          "title": "Description"
        },
        "path": {
          "description": "Path to the file, relative to the project root.",
          "title": "Path",
          "type": "string"
        },
        "stage": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the pipeline stage that produces this.",
          "title": "Stage"
        },
        "title": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A human-readable title.",
          "title": "Title"
        }
      },
      "required": [
        "path"
      ],
      "title": "Table",
      "type": "object"
    },
    "TableEvidence": {
      "description": "Evidence in the form of a table.",
      "properties": {
        "explanation": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Explanation"
        },
        "git_ref": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Git reference (branch, tag, or commit hash) pointing to the version of the repository where the table can be found.",
          "title": "Git Ref"
        },
        "kind": {
          "const": "table",
          "default": "table",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "title": "TableEvidence",
      "type": "object"
    },
    "UvEnvironment": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "kind": {
          "const": "uv",
          "default": "uv",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "description": "Path to the uv project's pyproject.toml.",
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path"
      ],
      "title": "UvEnvironment",
      "type": "object"
    },
    "UvVenvEnvironment": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "kind": {
          "const": "uv-venv",
          "default": "uv-venv",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "description": "Path to the requirements file, e.g., requirements.txt.",
          "title": "Path",
          "type": "string"
        },
        "prefix": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path at which to create the environment. If unset, this is resolved on the fly, defaulting to .venv next to the spec file, nesting under .calkit/envs/{name}/.venv on conflict.",
          "title": "Prefix"
        },
        "python": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Python version to use when creating the environment.",
          "title": "Python"
        }
      },
      "required": [
        "path"
      ],
      "title": "UvVenvEnvironment",
      "type": "object"
    },
    "ValueEvidence": {
      "description": "Evidence in the form of one value from a results file.\n\nThe value is never copied into ``calkit.yaml``: the pipeline owns it,\nand the entry only points at it. Under its ``name`` it can be templated\ninto the question's prose with Python format syntax, e.g.,\n``\"about {improvement:.1f}x\"``, so a number in an answer is read from\nthe results file when the question is displayed and cannot go stale.",
      "properties": {
        "explanation": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Explanation"
        },
        "git_ref": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Git reference (branch, tag, or commit hash) pointing to the version of the repository where the value can be found.",
          "title": "Git Ref"
        },
        "key": {
          "description": "Key of the value within the results file. A key present at the top level is used as-is; otherwise it is split on dots and walked into nested objects, with integers indexing lists.",
          "title": "Key",
          "type": "string"
        },
        "kind": {
          "const": "value",
          "default": "value",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name under which the value can be templated into the question's text, as in '{name:.2f}'. Defaults to the key. Must be unique within the question.",
          "title": "Name"
        },
        "path": {
          "title": "Path",
          "type": "string"
        }
      },
      "required": [
        "path",
        "key"
      ],
      "title": "ValueEvidence",
      "type": "object"
    },
    "VenvEnvironment": {
      "properties": {
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of the environment.",
          "title": "Description"
        },
        "kind": {
          "const": "venv",
          "default": "venv",
          "title": "Kind",
          "type": "string"
        },
        "path": {
          "description": "Path to the requirements file, e.g., requirements.txt.",
          "title": "Path",
          "type": "string"
        },
        "prefix": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path at which to create the environment. If unset, this is resolved on the fly, defaulting to .venv next to the spec file, nesting under .calkit/envs/{name}/.venv on conflict.",
          "title": "Prefix"
        },
        "python": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Python version to use when creating the environment.",
          "title": "Python"
        }
      },
      "required": [
        "path"
      ],
      "title": "VenvEnvironment",
      "type": "object"
    },
    "WordToPdfStage": {
      "additionalProperties": false,
      "properties": {
        "always_run": {
          "default": false,
          "description": "Run this stage every time the pipeline is run, even if nothing has changed.",
          "title": "Always Run",
          "type": "boolean"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A description of what this stage does.",
          "title": "Description"
        },
        "env_default_setup": {
          "default": "replace",
          "description": "How to combine 'setup' with the environment's 'default_setup'. 'replace' (default) runs the environment's only when the stage names none of its own; 'merge' runs the environment's first, then the stage's; 'ignore' never runs the environment's.",
          "enum": [
            "ignore",
            "replace",
            "merge"
          ],
          "title": "Env Default Setup",
          "type": "string"
        },
        "environment": {
          "default": "_system",
          "title": "Environment",
          "type": "string"
        },
        "frozen": {
          "default": false,
          "description": "Never rerun this stage, treating its outputs as up-to-date.",
          "title": "Frozen",
          "type": "boolean"
        },
        "inputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathInput"
                  },
                  {
                    "$ref": "#/$defs/InputsFromStageOutputs"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage depends on, which trigger a rerun when they change. Normally plain path strings; an object carrying a 'path' is also accepted.",
          "title": "Inputs"
        },
        "iterate_over": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/StageIteration"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Arguments over which to run this stage multiple times.",
          "title": "Iterate Over"
        },
        "kind": {
          "const": "word-to-pdf",
          "default": "word-to-pdf",
          "title": "Kind",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The stage's name, which must match its key if set.",
          "title": "Name"
        },
        "outputs": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/PathOutput"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": [],
          "description": "Paths this stage produces.",
          "title": "Outputs"
        },
        "scheduler": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Options for running this stage on a job scheduler (SLURM or PBS)."
        },
        "setup": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Commands run before this stage's own command, in the same shell as the command, so a variable they set or a function they define is in scope for it, exported or not. Combined with the environment's 'default_setup' as 'env_default_setup' says. Only for environments that have one: 'system', 'slurm', and 'pbs'.",
          "title": "Setup"
        },
        "slurm": {
          "anyOf": [
            {
              "$ref": "#/$defs/StageSchedulerOptions"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated name for 'scheduler'; set 'scheduler' instead."
        },
        "wdir": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Working directory in which to run, relative to the project root. Note that all other paths in the stage are relative to this.",
          "title": "Wdir"
        },
        "word_doc_path": {
          "description": "Path to the Word document to convert.",
          "title": "Word Doc Path",
          "type": "string"
        }
      },
      "required": [
        "word_doc_path"
      ],
      "title": "WordToPdfStage",
      "type": "object"
    },
    "_ImportedFromDescription": {
      "additionalProperties": false,
      "description": "Data whose origin can be stated but not resolved.\n\nSome things arrive by other means --- emailed by a person, provided\nby a company, handed over on a drive. There is no URL, DOI, repo or\nproject to point at, and recording that in words is better than\nrecording nothing. Weaker provenance than the others, deliberately:\nit says where something came from without saying how to get it again,\nso anyone reading it knows they have a name to ask rather than an\naddress to fetch.",
      "properties": {
        "date": {
          "anyOf": [
            {
              "format": "date",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When the data was received.",
          "title": "Date"
        },
        "description": {
          "description": "Where it came from, in words, for an origin that can be stated but not resolved, e.g. 'Emailed by someone@example.com' or 'Provided by Acme, Inc.'",
          "title": "Description",
          "type": "string"
        }
      },
      "required": [
        "description"
      ],
      "title": "_ImportedFromDescription",
      "type": "object"
    },
    "_ImportedFromDoi": {
      "additionalProperties": false,
      "description": "Data published under a DOI, which is a citation, not just a link.\n\nKept apart from a URL so it can be cited and resolved as a DOI rather\nthan being one more address that happens to start with https.",
      "properties": {
        "date": {
          "anyOf": [
            {
              "format": "date",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When the data was downloaded.",
          "title": "Date"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where it came from, in words, for whatever the other fields can't say.",
          "title": "Description"
        },
        "doi": {
          "description": "The DOI, e.g. 10.5281/zenodo.1234567. A https://doi.org/ or doi: prefix is accepted and stripped.",
          "title": "Doi",
          "type": "string"
        }
      },
      "required": [
        "doi"
      ],
      "title": "_ImportedFromDoi",
      "type": "object"
    },
    "_ImportedFromGit": {
      "additionalProperties": false,
      "description": "Data from a Git repo that isn't a Calkit project.\n\nWritten flat, the way a project source is: everything here is already\ninside ``imported_from``, and the source-naming key beside it says\nwhat ``path`` is a path within, so nesting adds a level without\nadding clarity.",
      "properties": {
        "date": {
          "anyOf": [
            {
              "format": "date",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When the data was downloaded.",
          "title": "Date"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where it came from, in words, for whatever the other fields can't say.",
          "title": "Description"
        },
        "git_ref": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Branch, tag, or commit to follow when refreshing this, e.g., 'main'. Optional: an entry that names none is refreshed from the repo's default branch. The commit it resolves to is recorded in .calkit/imports.json, so the entry says both what it tracks and what it got.",
          "title": "Git Ref"
        },
        "git_repo_url": {
          "description": "Clone URL of the repo the data came from.",
          "title": "Git Repo Url",
          "type": "string"
        },
        "git_rev": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated; the commit an import resolved to is recorded in .calkit/imports.json, which is committed alongside it. Still read for entries written before the split, and moved across the next time 'calkit sync import' runs.",
          "title": "Git Rev"
        },
        "path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Path within that repo, if it isn't the whole thing.",
          "title": "Path"
        }
      },
      "required": [
        "git_repo_url"
      ],
      "title": "_ImportedFromGit",
      "type": "object"
    },
    "_ImportedFromProject": {
      "additionalProperties": false,
      "properties": {
        "date": {
          "anyOf": [
            {
              "format": "date",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When the data was downloaded.",
          "title": "Date"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where it came from, in words, for whatever the other fields can't say.",
          "title": "Description"
        },
        "filter_paths": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Filter Paths"
        },
        "git_rev": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "deprecated": true,
          "description": "Deprecated; recorded in .calkit/imports.json instead, with the other things a fetch resolves to.",
          "title": "Git Rev"
        },
        "path": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Path"
        },
        "project": {
          "title": "Project",
          "type": "string"
        }
      },
      "required": [
        "project"
      ],
      "title": "_ImportedFromProject",
      "type": "object"
    },
    "_ImportedFromUrl": {
      "additionalProperties": false,
      "properties": {
        "date": {
          "anyOf": [
            {
              "format": "date",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When the data was downloaded. Optional: without it, the commit that added this entry says when, to within a commit.",
          "title": "Date"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Where it came from, in words, for whatever the other fields can't say.",
          "title": "Description"
        },
        "url": {
          "title": "Url",
          "type": "string"
        }
      },
      "required": [
        "url"
      ],
      "title": "_ImportedFromUrl",
      "type": "object"
    },
    "_Person": {
      "additionalProperties": false,
      "description": "A person credited with producing something in the project.\n\nExtra keys are refused rather than ignored: a mistyped ``oricd``, or a\n``with_ai`` on something that doesn't take one, should say so instead of\nvanishing and leaving the author thinking they recorded it.",
      "properties": {
        "email": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Email address of the person.",
          "title": "Email"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Their name, if worth recording here.",
          "title": "Name"
        },
        "orcid": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Their ORCID, which identifies them globally rather than only within this project. Accepted bare or as a full URL.",
          "title": "Orcid"
        },
        "with_ai": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Generative AI tools this person used, e.g. 'Claude Opus 5'. Recorded against the person rather than the file, so a disclosure can't exist without someone answering for it.",
          "title": "With Ai"
        }
      },
      "title": "_Person",
      "type": "object"
    }
  },
  "$id": "https://docs.calkit.org/schemas/calkit.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "Metadata for a Calkit project, describing its environments, pipeline, and artifacts. See https://docs.calkit.org/calkit-yaml",
  "properties": {
    "$schema": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "URL of the JSON schema describing this file.",
      "title": "$Schema"
    },
    "apps": {
      "additionalProperties": {
        "$ref": "#/$defs/StaticHtmlApp"
      },
      "default": {},
      "description": "The project's apps, keyed by name.",
      "title": "Apps",
      "type": "object"
    },
    "calculations": {
      "additionalProperties": {
        "discriminator": {
          "mapping": {
            "formula": "#/$defs/Formula",
            "linear": "#/$defs/Linear",
            "lookup-table": "#/$defs/LookupTable"
          },
          "propertyName": "kind"
        },
        "oneOf": [
          {
            "$ref": "#/$defs/Formula"
          },
          {
            "$ref": "#/$defs/Linear"
          },
          {
            "$ref": "#/$defs/LookupTable"
          }
        ]
      },
      "default": {},
      "description": "Calculations that can be run with 'calkit calc run'.",
      "title": "Calculations",
      "type": "object"
    },
    "datasets": {
      "default": [],
      "description": "The project's datasets.",
      "items": {
        "$ref": "#/$defs/Dataset"
      },
      "title": "Datasets",
      "type": "array"
    },
    "dependencies": {
      "default": [],
      "description": "Deprecated alias for 'requirements', still honored so existing projects keep working. Set one or the other, not both.",
      "items": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "$ref": "#/$defs/SystemNumberRequirement"
          },
          {
            "$ref": "#/$defs/SystemValueRequirement"
          },
          {
            "$ref": "#/$defs/SetupRequirement"
          },
          {
            "$ref": "#/$defs/Requirement"
          },
          {
            "additionalProperties": {
              "anyOf": [
                {
                  "$ref": "#/$defs/RequirementAttrs"
                },
                {
                  "type": "null"
                }
              ]
            },
            "type": "object"
          }
        ]
      },
      "title": "Dependencies",
      "type": "array"
    },
    "derived_from": {
      "anyOf": [
        {
          "$ref": "#/$defs/DerivedFromProject"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The project this one was created as a copy of."
    },
    "description": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "A short description of the project.",
      "title": "Description"
    },
    "env_vars": {
      "additionalProperties": {
        "type": "string"
      },
      "default": {},
      "description": "Environmental variables set when running project commands.",
      "title": "Env Vars",
      "type": "object"
    },
    "environments": {
      "additionalProperties": {
        "discriminator": {
          "mapping": {
            "conda": "#/$defs/CondaEnvironment",
            "docker": "#/$defs/DockerEnvironment",
            "julia": "#/$defs/JuliaEnvironment",
            "matlab": "#/$defs/MatlabEnvironment",
            "nix": "#/$defs/NixEnvironment",
            "pbs": "#/$defs/PBSEnvironment",
            "pixi": "#/$defs/PixiEnvironment",
            "renv": "#/$defs/REnvironment",
            "slurm": "#/$defs/SlurmEnvironment",
            "system": "#/$defs/SystemEnvironment",
            "uv": "#/$defs/UvEnvironment",
            "uv-venv": "#/$defs/UvVenvEnvironment",
            "venv": "#/$defs/VenvEnvironment"
          },
          "propertyName": "kind"
        },
        "oneOf": [
          {
            "$ref": "#/$defs/CondaEnvironment"
          },
          {
            "$ref": "#/$defs/DockerEnvironment"
          },
          {
            "$ref": "#/$defs/JuliaEnvironment"
          },
          {
            "$ref": "#/$defs/MatlabEnvironment"
          },
          {
            "$ref": "#/$defs/PixiEnvironment"
          },
          {
            "$ref": "#/$defs/REnvironment"
          },
          {
            "$ref": "#/$defs/SlurmEnvironment"
          },
          {
            "$ref": "#/$defs/PBSEnvironment"
          },
          {
            "$ref": "#/$defs/VenvEnvironment"
          },
          {
            "$ref": "#/$defs/UvEnvironment"
          },
          {
            "$ref": "#/$defs/UvVenvEnvironment"
          },
          {
            "$ref": "#/$defs/NixEnvironment"
          },
          {
            "$ref": "#/$defs/SystemEnvironment"
          }
        ]
      },
      "default": {},
      "description": "Environments in which pipeline stages are run, keyed by name.",
      "title": "Environments",
      "type": "object"
    },
    "figures": {
      "default": [],
      "description": "The project's figures.",
      "items": {
        "$ref": "#/$defs/Figure"
      },
      "title": "Figures",
      "type": "array"
    },
    "git_repo_url": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "URL of the project's Git repository.",
      "title": "Git Repo Url"
    },
    "hub": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Base URL of the Calkit Hub on which the project is shared, backed up, and collaborated on, e.g., 'calkit.io'. The scheme can be omitted, in which case https is inferred, or http for a local host. Each project belongs to at most one hub, which makes 'ck://' paths resolvable against a known instance. Projects with no hub set are assumed to belong to 'calkit.io'.",
      "title": "Hub"
    },
    "misc": {
      "default": [],
      "description": "Paths worth attributing that aren't one of the typed artifacts, e.g. an image someone sent over or a file produced with help from a generative AI tool.",
      "items": {
        "$ref": "#/$defs/MiscArtifact"
      },
      "title": "Misc",
      "type": "array"
    },
    "name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The project's name on Calkit, e.g., 'my-project'.",
      "title": "Name"
    },
    "notebooks": {
      "default": [],
      "description": "The project's Jupyter notebooks.",
      "items": {
        "$ref": "#/$defs/Notebook"
      },
      "title": "Notebooks",
      "type": "array"
    },
    "overleaf_sync": {
      "additionalProperties": {
        "$ref": "#/$defs/OverleafSync"
      },
      "default": {},
      "description": "Overleaf sync configuration, keyed by the path of the synced directory.",
      "title": "Overleaf Sync",
      "type": "object"
    },
    "owner": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The account name that owns the project on Calkit.",
      "title": "Owner"
    },
    "parameters": {
      "anyOf": [
        {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "string"
              },
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "number"
                    },
                    {
                      "type": "string"
                    },
                    {
                      "$ref": "#/$defs/RangeIteration"
                    }
                  ]
                },
                "type": "array"
              }
            ]
          },
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Project-level parameters, which can be referenced from pipeline stages.",
      "title": "Parameters"
    },
    "pipeline": {
      "anyOf": [
        {
          "$ref": "#/$defs/Pipeline"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The project's reproducible pipeline."
    },
    "presentations": {
      "default": [],
      "description": "The project's slides and posters.",
      "items": {
        "$ref": "#/$defs/Presentation"
      },
      "title": "Presentations",
      "type": "array"
    },
    "procedures": {
      "additionalProperties": {
        "oneOf": [
          {
            "$ref": "#/$defs/ProcedureFile"
          },
          {
            "$ref": "#/$defs/Procedure"
          }
        ]
      },
      "default": {},
      "description": "Procedures, typically executed by a human, keyed by name. Each is written inline or points at the file holding it.",
      "title": "Procedures",
      "type": "object"
    },
    "publications": {
      "default": [],
      "description": "The project's papers, reports, and proposals.",
      "items": {
        "$ref": "#/$defs/Publication"
      },
      "title": "Publications",
      "type": "array"
    },
    "questions": {
      "default": [],
      "description": "Questions the project seeks to answer.",
      "items": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "$ref": "#/$defs/Question"
          }
        ]
      },
      "title": "Questions",
      "type": "array"
    },
    "references": {
      "default": [],
      "description": "The project's bibliographies.",
      "items": {
        "$ref": "#/$defs/ReferenceCollection"
      },
      "title": "References",
      "type": "array"
    },
    "releases": {
      "additionalProperties": {
        "$ref": "#/$defs/Release"
      },
      "default": {},
      "description": "Published or archived snapshots, keyed by name.",
      "title": "Releases",
      "type": "object"
    },
    "requirements": {
      "default": [],
      "description": "What must be true of the machine before the project runs: applications that must be on PATH, environmental variables, per-machine setup steps, and constraints on machine properties like CPU count. These describe the host, which is the built-in '_system' environment; a 'system' environment declares its own.",
      "items": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "$ref": "#/$defs/SystemNumberRequirement"
          },
          {
            "$ref": "#/$defs/SystemValueRequirement"
          },
          {
            "$ref": "#/$defs/SetupRequirement"
          },
          {
            "$ref": "#/$defs/Requirement"
          },
          {
            "additionalProperties": {
              "anyOf": [
                {
                  "$ref": "#/$defs/RequirementAttrs"
                },
                {
                  "type": "null"
                }
              ]
            },
            "type": "object"
          }
        ]
      },
      "title": "Requirements",
      "type": "array"
    },
    "results": {
      "default": [],
      "description": "The project's findings, each referring to a file, or to part of one.",
      "items": {
        "$ref": "#/$defs/Result"
      },
      "title": "Results",
      "type": "array"
    },
    "showcase": {
      "anyOf": [
        {
          "items": {
            "anyOf": [
              {
                "$ref": "#/$defs/ShowcaseFigure"
              },
              {
                "$ref": "#/$defs/ShowcaseText"
              },
              {
                "$ref": "#/$defs/ShowcaseMarkdown"
              },
              {
                "$ref": "#/$defs/ShowcaseMarkdownFile"
              },
              {
                "$ref": "#/$defs/ShowcaseYamlFile"
              },
              {
                "$ref": "#/$defs/ShowcaseNotebook"
              },
              {
                "$ref": "#/$defs/ShowcasePublication"
              },
              {
                "$ref": "#/$defs/ShowcaseApp"
              }
            ]
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Elements that best represent the project, shown on its project homepage on Calkit.",
      "title": "Showcase"
    },
    "software": {
      "default": [],
      "description": "Software created as part of the project.",
      "items": {
        "$ref": "#/$defs/Software"
      },
      "title": "Software",
      "type": "array"
    },
    "subprojects": {
      "default": [],
      "description": "Smaller projects executed as part of this one.",
      "items": {
        "$ref": "#/$defs/Subproject"
      },
      "title": "Subprojects",
      "type": "array"
    },
    "tables": {
      "default": [],
      "description": "The project's tables. Only needed for tables worth a title of their own; evidence can point at one inline.",
      "items": {
        "$ref": "#/$defs/Table"
      },
      "title": "Tables",
      "type": "array"
    },
    "title": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "A human-readable title for the project.",
      "title": "Title"
    }
  },
  "title": "Calkit project information",
  "type": "object"
}
