{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://raidcli.dev/schema/v1/raid-defs.schema.json",
    "title": "Raid Schema Definitions",
    "description": "Shared schema definitions for raid",
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "tasks": {
            "type": "array",
            "description": "Tasks to be executed",
            "minItems": 1,
            "items": {
                "type": "object",
                "oneOf": [
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Shell"
                                    },
                                    "cmd": {
                                        "type": "string",
                                        "description": "Command to execute"
                                    },
                                    "shell": {
                                        "type": "string",
                                        "enum": [
                                            "bash",
                                            "sh",
                                            "zsh",
                                            "powershell",
                                            "pwsh",
                                            "ps",
                                            "cmd"
                                        ],
                                        "description": "Shell to use (default: bash)"
                                    },
                                    "literal": {
                                        "type": "boolean",
                                        "description": "Pass the command to the shell without prior env var expansion",
                                        "default": false
                                    },
                                    "path": {
                                        "type": "string",
                                        "description": "Working directory for the command. Defaults to ~ for profile tasks, the repo directory for repo tasks."
                                    }
                                },
                                "required": [
                                    "type",
                                    "cmd"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Script"
                                    },
                                    "path": {
                                        "type": "string",
                                        "description": "Path to the script file"
                                    },
                                    "runner": {
                                        "type": "string",
                                        "enum": [
                                            "bash",
                                            "sh",
                                            "zsh",
                                            "python",
                                            "python2",
                                            "python3",
                                            "node",
                                            "powershell"
                                        ],
                                        "description": "Interpreter to use (optional)"
                                    }
                                },
                                "required": [
                                    "type",
                                    "path"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "HTTP"
                                    },
                                    "url": {
                                        "type": "string",
                                        "description": "URL to download from"
                                    },
                                    "dest": {
                                        "type": "string",
                                        "description": "Local path to write the file to"
                                    }
                                },
                                "required": [
                                    "type",
                                    "url",
                                    "dest"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Wait"
                                    },
                                    "url": {
                                        "type": "string",
                                        "description": "HTTP(S) URL or TCP host:port to poll"
                                    },
                                    "timeout": {
                                        "type": "string",
                                        "description": "Max wait duration (e.g. 30s, 1m). Defaults to 30s."
                                    }
                                },
                                "required": [
                                    "type",
                                    "url"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Template"
                                    },
                                    "src": {
                                        "type": "string",
                                        "description": "Path to the template file. Supports $VAR and ${VAR} substitution."
                                    },
                                    "dest": {
                                        "type": "string",
                                        "description": "Path to write the rendered file to"
                                    }
                                },
                                "required": [
                                    "type",
                                    "src",
                                    "dest"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Group"
                                    },
                                    "ref": {
                                        "type": "string",
                                        "description": "Name of the task group to execute, as defined in the profile's top-level task_groups map"
                                    },
                                    "parallel": {
                                        "type": "boolean",
                                        "description": "Run all tasks in the group concurrently, then wait for all to finish",
                                        "default": false
                                    },
                                    "attempts": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "description": "Retry the group on failure up to this many times"
                                    },
                                    "delay": {
                                        "type": "string",
                                        "description": "Duration to wait between retry attempts (e.g. 1s, 500ms). Default: 1s."
                                    }
                                },
                                "required": [
                                    "type",
                                    "ref"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Git"
                                    },
                                    "op": {
                                        "type": "string",
                                        "enum": [
                                            "pull",
                                            "checkout",
                                            "fetch",
                                            "reset"
                                        ],
                                        "description": "Git operation to perform"
                                    },
                                    "branch": {
                                        "type": "string",
                                        "description": "Target branch (required for checkout, optional for others)"
                                    },
                                    "path": {
                                        "type": "string",
                                        "description": "Path to the git repository. Defaults to the current working directory."
                                    }
                                },
                                "required": [
                                    "type",
                                    "op"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Prompt"
                                    },
                                    "var": {
                                        "type": "string",
                                        "description": "Environment variable name to set with the user's input"
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Message to display to the user"
                                    },
                                    "default": {
                                        "type": "string",
                                        "description": "Default value if the user provides no input"
                                    }
                                },
                                "required": [
                                    "type",
                                    "var"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Confirm"
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Confirmation prompt to display to the user"
                                    }
                                },
                                "required": [
                                    "type"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Set"
                                    },
                                    "var": {
                                        "type": "string",
                                        "description": "Environment variable name to set"
                                    },
                                    "value": {
                                        "type": "string",
                                        "description": "Value to assign. Supports $VAR and ${VAR} substitution."
                                    }
                                },
                                "required": [
                                    "type",
                                    "var",
                                    "value"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    },
                    {
                        "allOf": [
                            {
                                "$ref": "#/$defs/taskCommon"
                            },
                            {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "const": "Print"
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Message to print. Supports $VAR substitution unless literal is true."
                                    },
                                    "color": {
                                        "type": "string",
                                        "enum": [
                                            "red",
                                            "green",
                                            "yellow",
                                            "blue",
                                            "cyan",
                                            "white"
                                        ],
                                        "description": "Optional terminal color for the output"
                                    },
                                    "literal": {
                                        "type": "boolean",
                                        "description": "Skip environment variable expansion in the message",
                                        "default": false
                                    }
                                },
                                "required": [
                                    "type",
                                    "message"
                                ]
                            }
                        ],
                        "unevaluatedProperties": false
                    }
                ]
            }
        },
        "environments": {
            "type": "array",
            "description": "The environments to include in the raid profile",
            "minItems": 1,
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The name of the environment"
                    },
                    "tasks": {
                        "$ref": "#/properties/tasks"
                    },
                    "variables": {
                        "type": "array",
                        "description": "Environment variables to set",
                        "minItems": 1,
                        "items": {
                            "type": "object",
                            "description": "Environment variables to set",
                            "properties": {
                                "name": {
                                    "type": "string",
                                    "description": "The name of the variable"
                                },
                                "value": {
                                    "type": "string",
                                    "description": "The value of the variable"
                                }
                            },
                            "required": [
                                "name",
                                "value"
                            ],
                            "additionalProperties": false
                        }
                    }
                },
                "required": [
                    "name"
                ],
                "additionalProperties": false
            }
        },
        "install": {
            "type": "object",
            "description": "Options for installing the raid profile",
            "properties": {
                "tasks": {
                    "$ref": "#/properties/tasks"
                }
            },
            "additionalProperties": false
        },
        "commands": {
            "type": "array",
            "description": "Custom commands exposed as top-level raid subcommands",
            "minItems": 1,
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Command name used to invoke it via 'raid <name>'"
                    },
                    "usage": {
                        "type": "string",
                        "description": "Short description shown in 'raid --help'"
                    },
                    "args": {
                        "type": "array",
                        "description": "Declared positional arguments. Required args must be supplied; declarations cap the total number of positional args cobra accepts. The supplied value is exported as an env var named after `name` (uppercased) for the duration of the command, available in tasks as $NAME.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "name": {
                                    "type": "string",
                                    "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
                                    "description": "Argument name. Must be a valid env var identifier ([A-Za-z_][A-Za-z0-9_]*). Uppercased to form the variable name."
                                },
                                "usage": {
                                    "type": "string",
                                    "description": "Short description shown in '--help'."
                                },
                                "required": {
                                    "type": "boolean",
                                    "description": "If true the command fails when the positional value is omitted.",
                                    "default": false
                                }
                            },
                            "required": ["name"],
                            "additionalProperties": false
                        }
                    },
                    "flags": {
                        "type": "array",
                        "description": "Declared flags / options. Long form is --<name>; an optional `short` adds a single-character -<x>. Values bind to an env var named after `name` (uppercased) for the duration of the command. Booleans bind as the literal strings 'true' or 'false'.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "name": {
                                    "type": "string",
                                    "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
                                    "description": "Flag name. Must be a valid env var identifier ([A-Za-z_][A-Za-z0-9_]*). The long form is --<name> and the env var is the uppercased name."
                                },
                                "short": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 1,
                                    "description": "Single-character short form, e.g. 'v' to bind -v."
                                },
                                "usage": {
                                    "type": "string",
                                    "description": "Short description shown in '--help'."
                                },
                                "type": {
                                    "type": "string",
                                    "enum": ["string", "bool", "int"],
                                    "description": "Value type. Defaults to 'string' when omitted.",
                                    "default": "string"
                                },
                                "required": {
                                    "type": "boolean",
                                    "description": "If true cobra rejects the invocation when the flag is omitted.",
                                    "default": false
                                },
                                "default": {
                                    "description": "Value used when the flag is omitted. Must match `type` — the conditional `allOf` below enforces this so a string default on an int flag is rejected at config-load time."
                                }
                            },
                            "required": ["name"],
                            "additionalProperties": false,
                            "allOf": [
                                {
                                    "if": {"properties": {"type": {"const": "bool"}}, "required": ["type"]},
                                    "then": {"properties": {"default": {"type": "boolean"}}}
                                },
                                {
                                    "if": {"properties": {"type": {"const": "int"}}, "required": ["type"]},
                                    "then": {"properties": {"default": {"type": "integer"}}}
                                },
                                {
                                    "if": {
                                        "anyOf": [
                                            {"not": {"required": ["type"]}},
                                            {"properties": {"type": {"const": "string"}}, "required": ["type"]}
                                        ]
                                    },
                                    "then": {"properties": {"default": {"type": "string"}}}
                                }
                            ]
                        }
                    },
                    "tasks": {
                        "$ref": "#/properties/tasks"
                    },
                    "options": {
                        "$ref": "#/$defs/taskOptions"
                    },
                    "agent": {
                        "$ref": "#/$defs/commandAgent"
                    },
                    "out": {
                        "type": "object",
                        "description": "Output configuration for the command",
                        "properties": {
                            "stdout": {
                                "type": "boolean",
                                "description": "Show stdout from tasks (default: true when out is omitted)"
                            },
                            "stderr": {
                                "type": "boolean",
                                "description": "Show stderr from tasks (default: true when out is omitted)"
                            },
                            "file": {
                                "type": "string",
                                "description": "Path to additionally write all output to. Supports $VAR expansion."
                            }
                        },
                        "additionalProperties": false
                    }
                },
                "required": [
                    "name",
                    "tasks"
                ],
                "additionalProperties": false
            }
        }
    },
    "$defs": {
        "taskCommon": {
            "type": "object",
            "description": "Shared properties applied to every task type",
            "properties": {
                "name": {
                    "type": "string",
                    "description": "Optional human-readable label for the task, surfaced in logs and agent output"
                },
                "concurrent": {
                    "type": "boolean",
                    "description": "Whether to execute the task concurrently with other tasks"
                },
                "condition": {
                    "type": "object",
                    "description": "All specified fields must be satisfied for the task to run",
                    "properties": {
                        "platform": {
                            "type": "string",
                            "enum": [
                                "darwin",
                                "linux",
                                "windows"
                            ],
                            "description": "Only run on this platform"
                        },
                        "exists": {
                            "type": "string",
                            "description": "Only run if this file or directory exists"
                        },
                        "cmd": {
                            "type": "string",
                            "description": "Only run if this command exits with code 0"
                        }
                    },
                    "additionalProperties": false
                },
                "options": {
                    "$ref": "#/$defs/taskOptions"
                }
            }
        },
        "taskOptions": {
            "type": "object",
            "description": "Shared task / command options. Compose cleanly across task types and on commands; omitting `options` (or any field within) leaves default behavior unchanged. Additional fields will be added in future releases.",
            "properties": {
                "showExeTime": {
                    "type": "boolean",
                    "description": "When true, print a dim line to stderr after the task (or command) completes showing the elapsed time, e.g. `task-name complete in 1.2s`.",
                    "default": false
                },
                "continueOnFailure": {
                    "type": "boolean",
                    "description": "When true, a non-zero exit from this task does not abort the parent command — subsequent tasks still run and the failure is reported as a warning on stderr. The overall command exit code is only affected by non-ignored failures. Useful for cleanup teardown, best-effort lint/format steps, and optional probes. No effect on commands.",
                    "default": false
                }
            },
            "additionalProperties": false
        },
        "commandAgent": {
            "type": "object",
            "description": "Agent-facing safety metadata for a command. MCP clients read this from the `raid://workspace/commands` resource to decide whether to auto-execute or require user confirmation. Absence of the block is equivalent to `{safe: false}` — agents should treat unannotated commands as requiring confirmation.",
            "properties": {
                "safe": {
                    "type": "boolean",
                    "description": "When true, the command is idempotent with no side effects and may be auto-executed by MCP clients. Defaults to false.",
                    "default": false
                },
                "reads": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "Paths or globs the command reads. Informational only — raid does not parse or enforce these. Mirrors Claude Code's permission-model fields."
                },
                "writes": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "Paths or globs the command writes. Informational only — raid does not parse or enforce these."
                },
                "description": {
                    "type": "string",
                    "description": "Agent-facing description. Overrides the command's `usage` field in the MCP workspace resource when set."
                }
            },
            "additionalProperties": false
        },
        "verifyArray": {
            "type": "array",
            "description": "Declarative precondition checks. Each entry runs `tasks:` to assert a dependency or environmental precondition; if any task exits non-zero and `onFail:` is provided, raid runs the remediation once and re-runs `tasks:` exactly once. `raid doctor` runs every verify entry on the active profile and per-repo `raid.yaml` files and surfaces each as a finding (ok / warn / error). Keep checks small and fast: each entry is run on every doctor invocation.",
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Human-readable label surfaced in failure messages and doctor's findings list."
                    },
                    "tasks": {
                        "$ref": "#/properties/tasks"
                    },
                    "onFail": {
                        "$ref": "#/properties/tasks"
                    }
                },
                "required": ["name", "tasks"],
                "additionalProperties": false
            }
        }
    }
}
