{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "extends": {
      "description": "A base config file this one goes on top of, relative to this file: maps merge, this file's keys winning, and a list replaces the base's; relative paths resolve against the file they're in. A base can't extend another",
      "type": "string",
      "minLength": 1
    },
    "windows": {
      "default": [
        {
          "start": "01:00",
          "end": "07:00"
        }
      ],
      "description": "Local hours a scheduled run may start units in; each opening is one run; [] for none",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "days": {
            "description": "Weekdays the window opens on; every day when unset",
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "sun",
                "mon",
                "tue",
                "wed",
                "thu",
                "fri",
                "sat"
              ]
            }
          },
          "start": {
            "type": "string",
            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
            "description": "When a scheduled run starts, local time"
          },
          "end": {
            "type": "string",
            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
            "description": "No unit starts after this"
          }
        },
        "required": [
          "start",
          "end"
        ],
        "additionalProperties": false
      }
    },
    "watch": {
      "description": "awaywork watch, the daemon schedule install keeps running",
      "default": {},
      "type": "object",
      "properties": {
        "every": {
          "default": "5m",
          "description": "How often the daemon polls the sources of run: soon rules; a source's own every can make it less often",
          "type": "string",
          "pattern": "^[1-9]\\d*[mhdw]$"
        },
        "debug": {
          "default": false,
          "description": "Also write each run's full output to the daemon log",
          "type": "boolean"
        }
      },
      "additionalProperties": false
    },
    "limits": {
      "description": "Unit counts and time per run, for every provider",
      "default": {},
      "type": "object",
      "properties": {
        "units": {
          "description": "At most this many units per run",
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        "units_per_repo": {
          "description": "At most this many units per run in one repo",
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        },
        "unit_minutes": {
          "description": "Stop a worker after this many minutes",
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 9007199254740991
        }
      },
      "additionalProperties": false
    },
    "isolation": {
      "default": "none",
      "description": "Who setup, the agent and the checks run as: none, you; user, the awaywork user (Linux, set up as doctor shows); container, a fresh container of the repo's image each; always user on a GitHub-hosted runner and in awaywork's image",
      "type": "string",
      "enum": [
        "none",
        "user",
        "container"
      ]
    },
    "budget": {
      "default": {},
      "type": "object",
      "properties": {
        "reserve": {
          "description": "Never go past 1 - reserve of any window",
          "default": "10%",
          "type": "string",
          "pattern": "^(100|\\d{1,2}(\\.\\d+)?)%$"
        },
        "per_run": {
          "description": "At most this share of the long window per run",
          "type": "string",
          "pattern": "^(100|\\d{1,2}(\\.\\d+)?)%$"
        },
        "session_max": {
          "description": "Stop a worker past this share of the short window",
          "default": "90%",
          "type": "string",
          "pattern": "^(100|\\d{1,2}(\\.\\d+)?)%$"
        },
        "present_session_max": {
          "description": "Stop a worker past this share of the short window in a run started outside every window",
          "default": "40%",
          "type": "string",
          "pattern": "^(100|\\d{1,2}(\\.\\d+)?)%$"
        },
        "fallback": {
          "default": {
            "units": 4,
            "turns": 60
          },
          "type": "object",
          "properties": {
            "units": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Units per run"
            },
            "turns": {
              "default": 60,
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Turns per unit"
            }
          },
          "required": [
            "units"
          ],
          "additionalProperties": false,
          "description": "Caps when the provider's quota can't be read"
        }
      },
      "additionalProperties": false,
      "description": "Quota shares, for every provider"
    },
    "providers": {
      "minItems": 1,
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "string",
            "enum": [
              "claude",
              "codex",
              "cursor"
            ]
          },
          {
            "type": "object",
            "properties": {
              "claude": {
                "description": "claude settings",
                "type": "object",
                "properties": {
                  "settings": {
                    "description": "Settings file for every worker, relative to the config file; passed as --settings",
                    "type": "string",
                    "minLength": 1
                  },
                  "model": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Model passed to the provider's binary; default the binary's"
                  },
                  "config_dir": {
                    "type": "string",
                    "pattern": "^~?\\/",
                    "description": "Folder of the login it runs on, passed as CLAUDE_CONFIG_DIR, e.g. ~/.claude-work; default the environment's; CLAUDE_CODE_OAUTH_TOKEN wins when set; not with isolation: user or container"
                  }
                },
                "additionalProperties": false
              },
              "codex": {
                "description": "codex settings",
                "type": "object",
                "properties": {
                  "config": {
                    "description": "Config values for every worker, e.g. { model_reasoning_effort: high }; passed as -c",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean"
                      ]
                    }
                  },
                  "model": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Model passed to the provider's binary; default the binary's"
                  },
                  "config_dir": {
                    "type": "string",
                    "pattern": "^~?\\/",
                    "description": "Folder of the login it runs on, passed as CODEX_HOME, e.g. ~/.codex-work; default the environment's"
                  }
                },
                "additionalProperties": false
              },
              "cursor": {
                "description": "cursor settings",
                "type": "object",
                "properties": {
                  "model": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Model passed to the provider's binary; default the binary's"
                  }
                },
                "additionalProperties": false
              }
            },
            "additionalProperties": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Shell command that works the clone; the prompt is in the file named by AWAYWORK_PROMPT. Its output goes to worker.log"
                },
                "probe": {
                  "description": "Shell command printing the quota as JSON, { windows: [{ name, span, used, resetsAt, minutes? }] }, with a long window to pace against; runs in the config file's folder once per plan or run, after each unit, and in doctor. Unset, the fallback caps apply",
                  "type": "string",
                  "minLength": 1
                },
                "secrets": {
                  "default": [],
                  "description": "Env vars the command reads; withheld from other workers, listed in Actions",
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Z_][A-Z0-9_]*$"
                  }
                },
                "skills_dir": {
                  "default": ".agents/skills",
                  "description": "Where the CLI finds skills in the clone",
                  "type": "string",
                  "minLength": 1
                }
              },
              "required": [
                "command"
              ],
              "additionalProperties": false,
              "description": "A custom provider: any agent CLI, run by a command"
            }
          }
        ]
      },
      "description": "Providers to use, a name or a map to override; order = routing preference"
    },
    "forge": {
      "description": "Where the repos live: github or bitbucket, or github as a map of its settings, e.g. { github: { host: github.acme.com } }",
      "default": "github",
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "github",
            "bitbucket"
          ]
        },
        {
          "type": "object",
          "properties": {
            "github": {
              "description": "GitHub, through gh",
              "type": "object",
              "properties": {
                "host": {
                  "description": "GitHub Enterprise host, e.g. github.acme.com; github.com by default",
                  "type": "string",
                  "pattern": "^[^/\\s]+$"
                },
                "user": {
                  "description": "The gh account awaywork acts as, e.g. octocat: its `gh auth token` becomes GH_TOKEN (GH_ENTERPRISE_TOKEN with a host) for everything awaywork does on GitHub; default gh's active account. A token already in the environment wins",
                  "type": "string",
                  "pattern": "^[A-Za-z0-9-]+$"
                }
              },
              "additionalProperties": false
            }
          },
          "required": [
            "github"
          ],
          "additionalProperties": false
        }
      ]
    },
    "sources": {
      "description": "Where work comes from: built-in sources or your own commands; at least one",
      "type": "object",
      "properties": {
        "github": {
          "type": "object",
          "properties": {
            "search": {
              "description": "Extra GitHub search qualifiers, each ANDed with is:open archived:false (and with is:closed when a rule reads finished items), e.g. label:awaywork or mentions:@me; items they find are neither mine nor review-requested",
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            },
            "context": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Shell command run per item before the worker, in the config file's folder; AWAYWORK_ITEM_KEY, _ITEM_URL and _ITEM_FILE (the item as JSON) are in its env. Files it writes to $AWAYWORK_CONTEXT_DIR reach the worker in the item's `extra/` folder"
                },
                "secrets": {
                  "default": [],
                  "description": "Env vars the command needs; withheld from workers, listed in Actions",
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Z_][A-Z0-9_]*$"
                  }
                }
              },
              "required": [
                "command"
              ],
              "additionalProperties": false,
              "description": "Fetches more context for an item, with secrets kept out of the agent's environment"
            },
            "every": {
              "description": "How often awaywork watch polls this source for run: soon rules, when that is less often than watch.every",
              "type": "string",
              "pattern": "^[1-9]\\d*[mhdw]$"
            }
          },
          "additionalProperties": false,
          "description": "My PRs, PRs awaiting my review and issues assigned to me, in the repos the top-level repos lists, plus any extra searches"
        },
        "asana": {
          "type": "object",
          "properties": {
            "workspace": {
              "type": "string",
              "description": "Workspace gid"
            },
            "projects": {
              "description": "Only tasks in these project gids",
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "repo_map": {
              "description": "Project gid -> owner/repo where its tasks' code lives",
              "type": "object",
              "propertyNames": {
                "type": "string"
              },
              "additionalProperties": {
                "type": "string",
                "pattern": "^[\\w.-]+\\/[\\w.-]+$"
              }
            },
            "token_env": {
              "default": "ASANA_TOKEN",
              "description": "Env var holding the Asana token",
              "type": "string"
            },
            "context": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Shell command run per item before the worker, in the config file's folder; AWAYWORK_ITEM_KEY, _ITEM_URL and _ITEM_FILE (the item as JSON) are in its env. Files it writes to $AWAYWORK_CONTEXT_DIR reach the worker in the item's `extra/` folder"
                },
                "secrets": {
                  "default": [],
                  "description": "Env vars the command needs; withheld from workers, listed in Actions",
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Z_][A-Z0-9_]*$"
                  }
                }
              },
              "required": [
                "command"
              ],
              "additionalProperties": false,
              "description": "Fetches more context for an item, with secrets kept out of the agent's environment"
            },
            "every": {
              "description": "How often awaywork watch polls this source for run: soon rules, when that is less often than watch.every",
              "type": "string",
              "pattern": "^[1-9]\\d*[mhdw]$"
            },
            "link": {
              "description": "Line awaywork writes into its PR bodies, and finds in yours, to link an item; {key}, {id} and {url} are the item's; default `{url}`",
              "type": "string"
            }
          },
          "required": [
            "workspace"
          ],
          "additionalProperties": false,
          "description": "My incomplete Asana tasks"
        },
        "linear": {
          "type": "object",
          "properties": {
            "repo_map": {
              "description": "Team key -> owner/repo where its issues' code lives",
              "type": "object",
              "propertyNames": {
                "type": "string"
              },
              "additionalProperties": {
                "type": "string",
                "pattern": "^[\\w.-]+\\/[\\w.-]+$"
              }
            },
            "token_env": {
              "default": "LINEAR_API_KEY",
              "description": "Env var holding the Linear personal API key",
              "type": "string"
            },
            "context": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Shell command run per item before the worker, in the config file's folder; AWAYWORK_ITEM_KEY, _ITEM_URL and _ITEM_FILE (the item as JSON) are in its env. Files it writes to $AWAYWORK_CONTEXT_DIR reach the worker in the item's `extra/` folder"
                },
                "secrets": {
                  "default": [],
                  "description": "Env vars the command needs; withheld from workers, listed in Actions",
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Z_][A-Z0-9_]*$"
                  }
                }
              },
              "required": [
                "command"
              ],
              "additionalProperties": false,
              "description": "Fetches more context for an item, with secrets kept out of the agent's environment"
            },
            "every": {
              "description": "How often awaywork watch polls this source for run: soon rules, when that is less often than watch.every",
              "type": "string",
              "pattern": "^[1-9]\\d*[mhdw]$"
            },
            "link": {
              "description": "Line awaywork writes into its PR bodies, and finds in yours, to link an item; {key}, {id} and {url} are the item's; default `Part of {key}`",
              "type": "string"
            }
          },
          "additionalProperties": false,
          "description": "My open Linear issues"
        },
        "jira": {
          "type": "object",
          "properties": {
            "site": {
              "type": "string",
              "pattern": "^[\\w-]+(\\.[\\w-]+)+$",
              "description": "Jira Cloud site host, e.g. acme.atlassian.net"
            },
            "email": {
              "type": "string",
              "description": "Atlassian account email the API token belongs to"
            },
            "cloud_id": {
              "description": "Site cloud id: set for a scoped token, which calls api.atlassian.com",
              "type": "string"
            },
            "jql": {
              "description": "JQL condition ANDed with my unresolved issues",
              "type": "string"
            },
            "repo_map": {
              "description": "Project key -> owner/repo where its issues' code lives",
              "type": "object",
              "propertyNames": {
                "type": "string"
              },
              "additionalProperties": {
                "type": "string",
                "pattern": "^[\\w.-]+\\/[\\w.-]+$"
              }
            },
            "token_env": {
              "default": "JIRA_API_TOKEN",
              "description": "Env var holding the Atlassian API token",
              "type": "string"
            },
            "context": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Shell command run per item before the worker, in the config file's folder; AWAYWORK_ITEM_KEY, _ITEM_URL and _ITEM_FILE (the item as JSON) are in its env. Files it writes to $AWAYWORK_CONTEXT_DIR reach the worker in the item's `extra/` folder"
                },
                "secrets": {
                  "default": [],
                  "description": "Env vars the command needs; withheld from workers, listed in Actions",
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Z_][A-Z0-9_]*$"
                  }
                }
              },
              "required": [
                "command"
              ],
              "additionalProperties": false,
              "description": "Fetches more context for an item, with secrets kept out of the agent's environment"
            },
            "every": {
              "description": "How often awaywork watch polls this source for run: soon rules, when that is less often than watch.every",
              "type": "string",
              "pattern": "^[1-9]\\d*[mhdw]$"
            },
            "link": {
              "description": "Line awaywork writes into its PR bodies, and finds in yours, to link an item; {key}, {id} and {url} are the item's; default none",
              "type": "string"
            }
          },
          "required": [
            "site",
            "email"
          ],
          "additionalProperties": false,
          "description": "My unresolved Jira Cloud issues"
        },
        "routines": {
          "type": "object",
          "properties": {
            "context": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Shell command run per item before the worker, in the config file's folder; AWAYWORK_ITEM_KEY, _ITEM_URL and _ITEM_FILE (the item as JSON) are in its env. Files it writes to $AWAYWORK_CONTEXT_DIR reach the worker in the item's `extra/` folder"
                },
                "secrets": {
                  "default": [],
                  "description": "Env vars the command needs; withheld from workers, listed in Actions",
                  "type": "array",
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Z_][A-Z0-9_]*$"
                  }
                }
              },
              "required": [
                "command"
              ],
              "additionalProperties": false,
              "description": "Fetches more context for an item, with secrets kept out of the agent's environment"
            },
            "every": {
              "description": "How often awaywork watch polls this source for run: soon rules, when that is less often than watch.every",
              "type": "string",
              "pattern": "^[1-9]\\d*[mhdw]$"
            }
          },
          "additionalProperties": {
            "type": "object",
            "properties": {
              "days": {
                "description": "Weekdays it comes due on; every day when unset",
                "minItems": 1,
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "sun",
                    "mon",
                    "tue",
                    "wed",
                    "thu",
                    "fri",
                    "sat"
                  ]
                }
              },
              "at": {
                "description": "When it comes due, local time: one time or a list",
                "anyOf": [
                  {
                    "type": "string",
                    "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                  },
                  {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                    }
                  }
                ]
              },
              "repo": {
                "type": "string",
                "pattern": "^[^/\\s]+\\/[^/\\s]+$",
                "description": "The repo its work happens in, owner/name"
              },
              "title": {
                "type": "string",
                "minLength": 1,
                "description": "The item's title"
              },
              "description": {
                "default": "",
                "description": "The item's description, what the worker reads",
                "type": "string"
              }
            },
            "required": [
              "at",
              "repo",
              "title"
            ],
            "additionalProperties": false,
            "description": "A routine: an item that comes due on the clock"
          },
          "description": "Routines by name, each an item that comes due on the clock, like a weekly triage"
        }
      },
      "additionalProperties": {
        "type": "object",
        "properties": {
          "command": {
            "type": "string",
            "minLength": 1,
            "description": "Shell command printing the items as a JSON array; runs in the config file's folder"
          },
          "fields": {
            "default": [],
            "description": "Item fields rules may match on",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "secrets": {
            "default": [],
            "description": "Env vars the command reads; the GitHub Actions workflow passes them in",
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[A-Z_][A-Z0-9_]*$"
            }
          },
          "setup": {
            "description": "Runs in the config file's folder before awaywork on GitHub Actions, and at build in awaywork's container image",
            "type": "string"
          },
          "link": {
            "type": "string",
            "description": "Line awaywork writes into its PR bodies, and finds in yours, to link an item; {key}, {id} and {url} are the item's"
          },
          "every": {
            "description": "How often awaywork watch polls this source for run: soon rules, when that is less often than watch.every",
            "type": "string",
            "pattern": "^[1-9]\\d*[mhdw]$"
          },
          "write": {
            "description": "Shell command that comments on or moves one of your items, run like `command`; it reads the write as JSON on stdin, e.g. {\"op\":\"move\",\"item\":\"ENG-2101\",\"id\":\"10012\",\"to\":\"QA\"}, and may print the item's updated times as {\"before\":\"…\",\"after\":\"…\"}. Without it, on_done writes nothing to this source",
            "type": "string",
            "minLength": 1
          },
          "thread": {
            "description": "A thread host: a rule's `thread` may name this source, whose `write` then also answers {\"op\":\"open\",\"item\":\"<card key>\",\"title\":\"…\",\"body\":\"…\"} with {\"key\":\"…\",\"url\":\"…\"}, and `command` lists the threads it opened as items, their comments the replies",
            "type": "boolean"
          }
        },
        "required": [
          "command"
        ],
        "additionalProperties": false,
        "description": "A custom source: any command that prints your open items as JSON"
      }
    },
    "branch": {
      "default": "away/{key}",
      "description": "Branch name template; {key} or {title} is required, {type} is the conventional-commit type",
      "type": "string"
    },
    "repos": {
      "description": "The repos awaywork works in: each key an owner/name or a * glob such as acme/*, with its settings or nothing. A repo takes the settings of every key naming it, globs in the order written and its own key last, a later one winning; an item in a repo no key names is skipped",
      "default": {},
      "type": "object",
      "propertyNames": {
        "type": "string",
        "pattern": "^[^/\\s]+\\/[^/\\s]+$"
      },
      "additionalProperties": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "branch": {
                "description": "Branch name template for this repo",
                "type": "string"
              },
              "setup": {
                "description": "Setup command, run in the clone before the worker; a failure skips the unit",
                "type": "string"
              },
              "secrets": {
                "default": [],
                "description": "Env vars setup needs; withheld from workers, listed in Actions",
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                }
              },
              "verify": {
                "description": "Command run in the clone after the worker, before publishing; a failure goes in the PR body or report, and the work is still published",
                "type": "string"
              },
              "gates": {
                "description": "Gates for this repo's units, on top of the top-level ones; a name both have fires on either's changed, command or skill",
                "default": {},
                "type": "object",
                "propertyNames": {
                  "type": "string",
                  "pattern": "^[\\w-]+$"
                },
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "changed": {
                      "description": "Git globs from the repo root; fires when the chain's commits change a matching path; not on a plan or report rule's gate, which has no commits",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      ]
                    },
                    "command": {
                      "description": "A shell command awaywork runs in the clone, outside the model, naming its script by its path from the repo root; it diffs from AWAYWORK_FROM, the commit the chain started from, unset on a plan or report, and reads AWAYWORK_OUT_DIR, a read-only copy of what the steps left in .away/out; a non-zero exit fires, with its stdout as the line; so does one that can't run or times out, and, without running, one where a file it names differs from the one the chain started with",
                      "type": "string",
                      "minLength": 1
                    },
                    "skill": {
                      "description": "A skill, yours or built in, that a model runs on the chain's commits and a read-only copy of what the steps left in .away/out, a plan's or report's out files alone, after the other gates, routed like the rule's steps; it fires when it writes the verdict fires, its report lines on the card; so does a run that fails or changes the clone, whose changes awaywork drops",
                      "type": "string",
                      "minLength": 1
                    },
                    "instructions": {
                      "description": "Instruction files a skill gate's judge reads, relative to the config file; never the repo's, and never the rule's",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      ]
                    }
                  },
                  "additionalProperties": false
                }
              },
              "test": {
                "description": "Targeted test command, given to the worker in its prompt",
                "type": "string"
              },
              "instructions": {
                "description": "Instruction file for units in this repo",
                "type": "string"
              },
              "image": {
                "description": "Docker image setup, the agent and the checks run in under isolation: container; it ships the agent CLIs the repo's rules use and its toolchain",
                "type": "string",
                "minLength": 1
              }
            },
            "additionalProperties": false
          },
          {
            "type": "null"
          }
        ]
      }
    },
    "gates": {
      "description": "Checks on every slice that publishes commits, run before it's published; one that fires opens a deliver: pr PR as a draft and puts its line in a decision card on top of the PR body",
      "default": {},
      "type": "object",
      "propertyNames": {
        "type": "string",
        "pattern": "^[\\w-]+$"
      },
      "additionalProperties": {
        "type": "object",
        "properties": {
          "changed": {
            "description": "Git globs from the repo root; fires when the chain's commits change a matching path; not on a plan or report rule's gate, which has no commits",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "command": {
            "description": "A shell command awaywork runs in the clone, outside the model, naming its script by its path from the repo root; it diffs from AWAYWORK_FROM, the commit the chain started from, unset on a plan or report, and reads AWAYWORK_OUT_DIR, a read-only copy of what the steps left in .away/out; a non-zero exit fires, with its stdout as the line; so does one that can't run or times out, and, without running, one where a file it names differs from the one the chain started with",
            "type": "string",
            "minLength": 1
          },
          "skill": {
            "description": "A skill, yours or built in, that a model runs on the chain's commits and a read-only copy of what the steps left in .away/out, a plan's or report's out files alone, after the other gates, routed like the rule's steps; it fires when it writes the verdict fires, its report lines on the card; so does a run that fails or changes the clone, whose changes awaywork drops",
            "type": "string",
            "minLength": 1
          },
          "instructions": {
            "description": "Instruction files a skill gate's judge reads, relative to the config file; never the repo's, and never the rule's",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          }
        },
        "additionalProperties": false
      }
    },
    "instructions": {
      "description": "Instruction files added to every unit",
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      ]
    },
    "skills": {
      "default": [],
      "description": "Extra skills available to every unit; also looked up in the repo's .claude/skills, .agents/skills and .cursor/skills",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "mcp": {
      "default": {},
      "description": "MCP servers a rule or step names in its mcp",
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {
        "type": "object",
        "properties": {
          "command": {
            "description": "Command that starts a stdio server",
            "type": "string",
            "minLength": 1
          },
          "args": {
            "description": "The command's arguments",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "env": {
            "description": "The server's env vars, besides its secrets; plain values",
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            }
          },
          "url": {
            "description": "URL of an HTTP server",
            "type": "string",
            "format": "uri"
          },
          "headers": {
            "description": "HTTP headers; a value may be ${NAME}, or Bearer ${NAME} for Authorization",
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            }
          },
          "secrets": {
            "default": [],
            "description": "Env vars the server reads, in its env under their own names or in headers; given only to units whose rule names it, listed in Actions",
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            }
          },
          "tools": {
            "description": "Tools the worker may call; default all the server's",
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[\\w-]+$"
            }
          }
        },
        "additionalProperties": false
      }
    },
    "queue": {
      "description": "Rules mapping items to skills; without any, nothing runs",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "skill": {
            "type": "string",
            "minLength": 1,
            "description": "The skill that does the work"
          },
          "source": {
            "description": "Match only items from this source",
            "type": "string",
            "minLength": 1
          },
          "where": {
            "default": {},
            "description": "Item facts to match: type or a source field; a list means any of, {not} negates, {gt,gte,lt,lte} compare numbers, {older_than,newer_than} compare dates to now, {matches} tests text against a case-insensitive regex, any: [{...}] holds when one entry does; title, description, approved, state (open, merged, closed) and closed (when it finished) are on every source; a where, or an any entry under one, that never names state matches open items only",
            "$ref": "#/$defs/__schema0"
          },
          "provider": {
            "description": "Providers for this rule, in order; default the providers order",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "model": {
            "description": "Model per provider for this rule, e.g. { claude: sonnet } or { claude: [sonnet, opus] }; default the provider's",
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "description": "Model passed to the provider's binary; default the binary's"
                },
                {
                  "minItems": 2,
                  "maxItems": 2,
                  "type": "array",
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Model passed to the provider's binary; default the binary's"
                  }
                }
              ],
              "description": "A model, or two: a step that fails on the first runs once more on the second"
            }
          },
          "skills": {
            "default": [],
            "description": "Extra skills available to the worker; also looked up in the repo's .claude/skills, .agents/skills and .cursor/skills",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "mcp": {
            "description": "MCP servers the worker gets, by their name under the top-level mcp",
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "instructions": {
            "description": "Instruction files added for this rule",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "with": {
            "description": "Parameters for the skill, listed in its prompt; a skill's metadata says which it reads",
            "type": "object",
            "propertyNames": {
              "type": "string",
              "minLength": 1
            },
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            }
          },
          "deliver": {
            "description": "Where the chain's commits go: one draft PR (default), one PR ready for review (a draft when a step fails or the run ends before one runs, a step asks questions with ask in its status file, verify fails, a loop's until never held, or a gate fires), or a push onto your own PR's branch; report makes no step commit, and a chain without commits reports; pending_review reports too, and leaves the last report on the PR it reviews as your pending review, seen by no one until you submit it; plan reports too, and posts the report with the plan.yml a step wrote as one comment on the item, which waits for your reply: approve as its first line approves it, anything else re-plans",
            "type": "string",
            "enum": [
              "draft_pr",
              "pr",
              "report",
              "push",
              "pending_review",
              "plan"
            ]
          },
          "wait": {
            "description": "deliver: plan or report: the post waits for your reply on the item, approve as its first line letting the next stage take it, anything else running the step again; default true for plan, false for report; a gate of the rule's own that fires makes it wait anyway",
            "type": "boolean"
          },
          "gates": {
            "description": "Gates of the rule's own, under names no top-level or repo gate has. On a rule that opens a PR or pushes they run with those, and one that fires does what theirs does; on deliver: plan or report, where those never run, they run on what the step left, without changed, and one that fires puts its line on the post and makes it wait, a planned rule's task holding its card's other tasks until you answer; not on pending_review",
            "type": "object",
            "propertyNames": {
              "type": "string",
              "pattern": "^[\\w-]+$"
            },
            "additionalProperties": {
              "type": "object",
              "properties": {
                "changed": {
                  "description": "Git globs from the repo root; fires when the chain's commits change a matching path; not on a plan or report rule's gate, which has no commits",
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  ]
                },
                "command": {
                  "description": "A shell command awaywork runs in the clone, outside the model, naming its script by its path from the repo root; it diffs from AWAYWORK_FROM, the commit the chain started from, unset on a plan or report, and reads AWAYWORK_OUT_DIR, a read-only copy of what the steps left in .away/out; a non-zero exit fires, with its stdout as the line; so does one that can't run or times out, and, without running, one where a file it names differs from the one the chain started with",
                  "type": "string",
                  "minLength": 1
                },
                "skill": {
                  "description": "A skill, yours or built in, that a model runs on the chain's commits and a read-only copy of what the steps left in .away/out, a plan's or report's out files alone, after the other gates, routed like the rule's steps; it fires when it writes the verdict fires, its report lines on the card; so does a run that fails or changes the clone, whose changes awaywork drops",
                  "type": "string",
                  "minLength": 1
                },
                "instructions": {
                  "description": "Instruction files a skill gate's judge reads, relative to the config file; never the repo's, and never the rule's",
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  ]
                }
              },
              "additionalProperties": false
            }
          },
          "post": {
            "description": "deliver: plan, or a report that posts: summary posts the step's .away/out/summary.md, awaywork's facts and a pinned link per file it put in the store; full posts the report inline, plan and contract included; default summary with a store, else full",
            "type": "string",
            "enum": [
              "summary",
              "full"
            ]
          },
          "thread": {
            "description": "Where its posts go and their replies are read: item (default), the item itself; github, an issue awaywork opens as the item's thread in its repo, assigned to you; or a custom source with thread: true, whose write opens one; for a tracker that can't take them; from then on all of the item's posts go there, its plan's tasks' too, and it closes once its source says the item is done",
            "type": "string",
            "minLength": 1
          },
          "branch": {
            "description": "Branch name template for this rule",
            "type": "string"
          },
          "order": {
            "description": "Which item goes first: oldest, newest or last updated; default the source order",
            "type": "string",
            "enum": [
              "oldest",
              "newest",
              "updated"
            ]
          },
          "quota": {
            "description": "Run this rule's unit only when the quota holds; otherwise skip it",
            "type": "object",
            "properties": {
              "runs_until_reset": {
                "description": "Holds when at most this many window openings are left before the provider's long window resets; 1 is the last window",
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              },
              "headroom": {
                "description": "Holds when at least this share of the long window is left under this run's ceiling",
                "type": "string",
                "pattern": "^(100|\\d{1,2}(\\.\\d+)?)%$"
              }
            },
            "additionalProperties": false
          },
          "plan_tasks": {
            "description": "deliver: plan: at most this many tasks in its plan; default 8",
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991
          },
          "units": {
            "description": "At most this many units per run from this rule; a chain counts once",
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991
          },
          "then": {
            "description": "Steps run in turn after this rule's unit, in its clone; the chain publishes once, when it ends; a {loop} repeats its steps",
            "anyOf": [
              {
                "anyOf": [
                  {
                    "type": "string",
                    "minLength": 1
                  },
                  {
                    "type": "object",
                    "properties": {
                      "skill": {
                        "type": "string",
                        "minLength": 1,
                        "description": "The skill that does the work"
                      },
                      "provider": {
                        "description": "Providers for this step, in order; default the rule's, [] the providers order",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "model": {
                        "description": "Model per provider for this step; default the rule's",
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {
                          "anyOf": [
                            {
                              "type": "string",
                              "minLength": 1,
                              "description": "Model passed to the provider's binary; default the binary's"
                            },
                            {
                              "minItems": 2,
                              "maxItems": 2,
                              "type": "array",
                              "items": {
                                "type": "string",
                                "minLength": 1,
                                "description": "Model passed to the provider's binary; default the binary's"
                              }
                            }
                          ],
                          "description": "A model, or two: a step that fails on the first runs once more on the second"
                        }
                      },
                      "skills": {
                        "description": "Extra skills available to the worker; default the rule's, [] none",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "mcp": {
                        "description": "MCP servers the worker gets, by their name under the top-level mcp; default the rule's, [] none",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "instructions": {
                        "description": "Instruction files added for this step; default the rule's, [] none",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "with": {
                        "description": "Parameters for the skill, listed in its prompt; a skill's metadata says which it reads",
                        "type": "object",
                        "propertyNames": {
                          "type": "string",
                          "minLength": 1
                        },
                        "additionalProperties": {
                          "type": [
                            "string",
                            "number",
                            "boolean"
                          ]
                        }
                      },
                      "when": {
                        "description": "Run this step only when every key holds; otherwise skip it",
                        "type": "object",
                        "properties": {
                          "verdict": {
                            "description": "The latest verdict in the chain; a list means any of, {not} negates",
                            "anyOf": [
                              {
                                "anyOf": [
                                  {
                                    "type": "string",
                                    "pattern": "^[a-z][a-z_-]*$"
                                  },
                                  {
                                    "minItems": 1,
                                    "type": "array",
                                    "items": {
                                      "type": "string",
                                      "pattern": "^[a-z][a-z_-]*$"
                                    }
                                  }
                                ]
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "not": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "pattern": "^[a-z][a-z_-]*$"
                                      },
                                      {
                                        "minItems": 1,
                                        "type": "array",
                                        "items": {
                                          "type": "string",
                                          "pattern": "^[a-z][a-z_-]*$"
                                        }
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "not"
                                ],
                                "additionalProperties": false,
                                "description": "Matches every verdict but these"
                              }
                            ]
                          },
                          "command": {
                            "description": "A shell command awaywork runs in the clone, outside the model; exit 0 holds",
                            "type": "string",
                            "minLength": 1
                          },
                          "changed": {
                            "description": "Git globs from the repo root; holds when the chain's commits change a matching path, against where the chain started",
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            ]
                          }
                        },
                        "additionalProperties": false
                      }
                    },
                    "required": [
                      "skill"
                    ],
                    "additionalProperties": false
                  }
                ],
                "description": "A skill name, or a map with skill, provider, model, skills, mcp and instructions (unset, the rule's), with and when"
              },
              {
                "type": "object",
                "properties": {
                  "loop": {
                    "description": "Steps run in turn every round, in the chain's clone",
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "type": "string",
                            "minLength": 1
                          },
                          {
                            "type": "object",
                            "properties": {
                              "skill": {
                                "type": "string",
                                "minLength": 1,
                                "description": "The skill that does the work"
                              },
                              "provider": {
                                "description": "Providers for this step, in order; default the rule's, [] the providers order",
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                ]
                              },
                              "model": {
                                "description": "Model per provider for this step; default the rule's",
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "minLength": 1,
                                      "description": "Model passed to the provider's binary; default the binary's"
                                    },
                                    {
                                      "minItems": 2,
                                      "maxItems": 2,
                                      "type": "array",
                                      "items": {
                                        "type": "string",
                                        "minLength": 1,
                                        "description": "Model passed to the provider's binary; default the binary's"
                                      }
                                    }
                                  ],
                                  "description": "A model, or two: a step that fails on the first runs once more on the second"
                                }
                              },
                              "skills": {
                                "description": "Extra skills available to the worker; default the rule's, [] none",
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "mcp": {
                                "description": "MCP servers the worker gets, by their name under the top-level mcp; default the rule's, [] none",
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "instructions": {
                                "description": "Instruction files added for this step; default the rule's, [] none",
                                "anyOf": [
                                  {
                                    "type": "string"
                                  },
                                  {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                ]
                              },
                              "with": {
                                "description": "Parameters for the skill, listed in its prompt; a skill's metadata says which it reads",
                                "type": "object",
                                "propertyNames": {
                                  "type": "string",
                                  "minLength": 1
                                },
                                "additionalProperties": {
                                  "type": [
                                    "string",
                                    "number",
                                    "boolean"
                                  ]
                                }
                              },
                              "when": {
                                "description": "Run this step only when every key holds; otherwise skip it",
                                "type": "object",
                                "properties": {
                                  "verdict": {
                                    "description": "The latest verdict in the chain; a list means any of, {not} negates",
                                    "anyOf": [
                                      {
                                        "anyOf": [
                                          {
                                            "type": "string",
                                            "pattern": "^[a-z][a-z_-]*$"
                                          },
                                          {
                                            "minItems": 1,
                                            "type": "array",
                                            "items": {
                                              "type": "string",
                                              "pattern": "^[a-z][a-z_-]*$"
                                            }
                                          }
                                        ]
                                      },
                                      {
                                        "type": "object",
                                        "properties": {
                                          "not": {
                                            "anyOf": [
                                              {
                                                "type": "string",
                                                "pattern": "^[a-z][a-z_-]*$"
                                              },
                                              {
                                                "minItems": 1,
                                                "type": "array",
                                                "items": {
                                                  "type": "string",
                                                  "pattern": "^[a-z][a-z_-]*$"
                                                }
                                              }
                                            ]
                                          }
                                        },
                                        "required": [
                                          "not"
                                        ],
                                        "additionalProperties": false,
                                        "description": "Matches every verdict but these"
                                      }
                                    ]
                                  },
                                  "command": {
                                    "description": "A shell command awaywork runs in the clone, outside the model; exit 0 holds",
                                    "type": "string",
                                    "minLength": 1
                                  },
                                  "changed": {
                                    "description": "Git globs from the repo root; holds when the chain's commits change a matching path, against where the chain started",
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        }
                                      }
                                    ]
                                  }
                                },
                                "additionalProperties": false
                              }
                            },
                            "required": [
                              "skill"
                            ],
                            "additionalProperties": false
                          }
                        ],
                        "description": "A skill name, or a map with skill, provider, model, skills, mcp and instructions (unset, the rule's), with and when"
                      },
                      {
                        "minItems": 1,
                        "type": "array",
                        "items": {
                          "anyOf": [
                            {
                              "type": "string",
                              "minLength": 1
                            },
                            {
                              "type": "object",
                              "properties": {
                                "skill": {
                                  "type": "string",
                                  "minLength": 1,
                                  "description": "The skill that does the work"
                                },
                                "provider": {
                                  "description": "Providers for this step, in order; default the rule's, [] the providers order",
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    }
                                  ]
                                },
                                "model": {
                                  "description": "Model per provider for this step; default the rule's",
                                  "type": "object",
                                  "propertyNames": {
                                    "type": "string"
                                  },
                                  "additionalProperties": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "minLength": 1,
                                        "description": "Model passed to the provider's binary; default the binary's"
                                      },
                                      {
                                        "minItems": 2,
                                        "maxItems": 2,
                                        "type": "array",
                                        "items": {
                                          "type": "string",
                                          "minLength": 1,
                                          "description": "Model passed to the provider's binary; default the binary's"
                                        }
                                      }
                                    ],
                                    "description": "A model, or two: a step that fails on the first runs once more on the second"
                                  }
                                },
                                "skills": {
                                  "description": "Extra skills available to the worker; default the rule's, [] none",
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                },
                                "mcp": {
                                  "description": "MCP servers the worker gets, by their name under the top-level mcp; default the rule's, [] none",
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                },
                                "instructions": {
                                  "description": "Instruction files added for this step; default the rule's, [] none",
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    }
                                  ]
                                },
                                "with": {
                                  "description": "Parameters for the skill, listed in its prompt; a skill's metadata says which it reads",
                                  "type": "object",
                                  "propertyNames": {
                                    "type": "string",
                                    "minLength": 1
                                  },
                                  "additionalProperties": {
                                    "type": [
                                      "string",
                                      "number",
                                      "boolean"
                                    ]
                                  }
                                },
                                "when": {
                                  "description": "Run this step only when every key holds; otherwise skip it",
                                  "type": "object",
                                  "properties": {
                                    "verdict": {
                                      "description": "The latest verdict in the chain; a list means any of, {not} negates",
                                      "anyOf": [
                                        {
                                          "anyOf": [
                                            {
                                              "type": "string",
                                              "pattern": "^[a-z][a-z_-]*$"
                                            },
                                            {
                                              "minItems": 1,
                                              "type": "array",
                                              "items": {
                                                "type": "string",
                                                "pattern": "^[a-z][a-z_-]*$"
                                              }
                                            }
                                          ]
                                        },
                                        {
                                          "type": "object",
                                          "properties": {
                                            "not": {
                                              "anyOf": [
                                                {
                                                  "type": "string",
                                                  "pattern": "^[a-z][a-z_-]*$"
                                                },
                                                {
                                                  "minItems": 1,
                                                  "type": "array",
                                                  "items": {
                                                    "type": "string",
                                                    "pattern": "^[a-z][a-z_-]*$"
                                                  }
                                                }
                                              ]
                                            }
                                          },
                                          "required": [
                                            "not"
                                          ],
                                          "additionalProperties": false,
                                          "description": "Matches every verdict but these"
                                        }
                                      ]
                                    },
                                    "command": {
                                      "description": "A shell command awaywork runs in the clone, outside the model; exit 0 holds",
                                      "type": "string",
                                      "minLength": 1
                                    },
                                    "changed": {
                                      "description": "Git globs from the repo root; holds when the chain's commits change a matching path, against where the chain started",
                                      "anyOf": [
                                        {
                                          "type": "string"
                                        },
                                        {
                                          "type": "array",
                                          "items": {
                                            "type": "string"
                                          }
                                        }
                                      ]
                                    }
                                  },
                                  "additionalProperties": false
                                }
                              },
                              "required": [
                                "skill"
                              ],
                              "additionalProperties": false
                            }
                          ],
                          "description": "A skill name, or a map with skill, provider, model, skills, mcp and instructions (unset, the rule's), with and when"
                        }
                      }
                    ]
                  },
                  "until": {
                    "type": "object",
                    "properties": {
                      "verdict": {
                        "description": "The latest verdict a loop step wrote; a list means any of, {not} negates",
                        "anyOf": [
                          {
                            "anyOf": [
                              {
                                "type": "string",
                                "pattern": "^[a-z][a-z_-]*$"
                              },
                              {
                                "minItems": 1,
                                "type": "array",
                                "items": {
                                  "type": "string",
                                  "pattern": "^[a-z][a-z_-]*$"
                                }
                              }
                            ]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "not": {
                                "anyOf": [
                                  {
                                    "type": "string",
                                    "pattern": "^[a-z][a-z_-]*$"
                                  },
                                  {
                                    "minItems": 1,
                                    "type": "array",
                                    "items": {
                                      "type": "string",
                                      "pattern": "^[a-z][a-z_-]*$"
                                    }
                                  }
                                ]
                              }
                            },
                            "required": [
                              "not"
                            ],
                            "additionalProperties": false,
                            "description": "Matches every verdict but these"
                          }
                        ]
                      },
                      "command": {
                        "description": "A shell command awaywork runs in the clone, outside the model; exit 0 holds",
                        "type": "string",
                        "minLength": 1
                      }
                    },
                    "additionalProperties": false,
                    "description": "Ends the loop as soon as it holds; checked after every step"
                  },
                  "max": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5,
                    "description": "At most this many rounds, up to 5"
                  }
                },
                "required": [
                  "loop",
                  "until",
                  "max"
                ],
                "additionalProperties": false,
                "description": "Steps repeated until a condition holds"
              },
              {
                "minItems": 1,
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1
                        },
                        {
                          "type": "object",
                          "properties": {
                            "skill": {
                              "type": "string",
                              "minLength": 1,
                              "description": "The skill that does the work"
                            },
                            "provider": {
                              "description": "Providers for this step, in order; default the rule's, [] the providers order",
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                }
                              ]
                            },
                            "model": {
                              "description": "Model per provider for this step; default the rule's",
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {
                                "anyOf": [
                                  {
                                    "type": "string",
                                    "minLength": 1,
                                    "description": "Model passed to the provider's binary; default the binary's"
                                  },
                                  {
                                    "minItems": 2,
                                    "maxItems": 2,
                                    "type": "array",
                                    "items": {
                                      "type": "string",
                                      "minLength": 1,
                                      "description": "Model passed to the provider's binary; default the binary's"
                                    }
                                  }
                                ],
                                "description": "A model, or two: a step that fails on the first runs once more on the second"
                              }
                            },
                            "skills": {
                              "description": "Extra skills available to the worker; default the rule's, [] none",
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "mcp": {
                              "description": "MCP servers the worker gets, by their name under the top-level mcp; default the rule's, [] none",
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "instructions": {
                              "description": "Instruction files added for this step; default the rule's, [] none",
                              "anyOf": [
                                {
                                  "type": "string"
                                },
                                {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  }
                                }
                              ]
                            },
                            "with": {
                              "description": "Parameters for the skill, listed in its prompt; a skill's metadata says which it reads",
                              "type": "object",
                              "propertyNames": {
                                "type": "string",
                                "minLength": 1
                              },
                              "additionalProperties": {
                                "type": [
                                  "string",
                                  "number",
                                  "boolean"
                                ]
                              }
                            },
                            "when": {
                              "description": "Run this step only when every key holds; otherwise skip it",
                              "type": "object",
                              "properties": {
                                "verdict": {
                                  "description": "The latest verdict in the chain; a list means any of, {not} negates",
                                  "anyOf": [
                                    {
                                      "anyOf": [
                                        {
                                          "type": "string",
                                          "pattern": "^[a-z][a-z_-]*$"
                                        },
                                        {
                                          "minItems": 1,
                                          "type": "array",
                                          "items": {
                                            "type": "string",
                                            "pattern": "^[a-z][a-z_-]*$"
                                          }
                                        }
                                      ]
                                    },
                                    {
                                      "type": "object",
                                      "properties": {
                                        "not": {
                                          "anyOf": [
                                            {
                                              "type": "string",
                                              "pattern": "^[a-z][a-z_-]*$"
                                            },
                                            {
                                              "minItems": 1,
                                              "type": "array",
                                              "items": {
                                                "type": "string",
                                                "pattern": "^[a-z][a-z_-]*$"
                                              }
                                            }
                                          ]
                                        }
                                      },
                                      "required": [
                                        "not"
                                      ],
                                      "additionalProperties": false,
                                      "description": "Matches every verdict but these"
                                    }
                                  ]
                                },
                                "command": {
                                  "description": "A shell command awaywork runs in the clone, outside the model; exit 0 holds",
                                  "type": "string",
                                  "minLength": 1
                                },
                                "changed": {
                                  "description": "Git globs from the repo root; holds when the chain's commits change a matching path, against where the chain started",
                                  "anyOf": [
                                    {
                                      "type": "string"
                                    },
                                    {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    }
                                  ]
                                }
                              },
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "skill"
                          ],
                          "additionalProperties": false
                        }
                      ],
                      "description": "A skill name, or a map with skill, provider, model, skills, mcp and instructions (unset, the rule's), with and when"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "loop": {
                          "description": "Steps run in turn every round, in the chain's clone",
                          "anyOf": [
                            {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "minLength": 1
                                },
                                {
                                  "type": "object",
                                  "properties": {
                                    "skill": {
                                      "type": "string",
                                      "minLength": 1,
                                      "description": "The skill that does the work"
                                    },
                                    "provider": {
                                      "description": "Providers for this step, in order; default the rule's, [] the providers order",
                                      "anyOf": [
                                        {
                                          "type": "string"
                                        },
                                        {
                                          "type": "array",
                                          "items": {
                                            "type": "string"
                                          }
                                        }
                                      ]
                                    },
                                    "model": {
                                      "description": "Model per provider for this step; default the rule's",
                                      "type": "object",
                                      "propertyNames": {
                                        "type": "string"
                                      },
                                      "additionalProperties": {
                                        "anyOf": [
                                          {
                                            "type": "string",
                                            "minLength": 1,
                                            "description": "Model passed to the provider's binary; default the binary's"
                                          },
                                          {
                                            "minItems": 2,
                                            "maxItems": 2,
                                            "type": "array",
                                            "items": {
                                              "type": "string",
                                              "minLength": 1,
                                              "description": "Model passed to the provider's binary; default the binary's"
                                            }
                                          }
                                        ],
                                        "description": "A model, or two: a step that fails on the first runs once more on the second"
                                      }
                                    },
                                    "skills": {
                                      "description": "Extra skills available to the worker; default the rule's, [] none",
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    },
                                    "mcp": {
                                      "description": "MCP servers the worker gets, by their name under the top-level mcp; default the rule's, [] none",
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    },
                                    "instructions": {
                                      "description": "Instruction files added for this step; default the rule's, [] none",
                                      "anyOf": [
                                        {
                                          "type": "string"
                                        },
                                        {
                                          "type": "array",
                                          "items": {
                                            "type": "string"
                                          }
                                        }
                                      ]
                                    },
                                    "with": {
                                      "description": "Parameters for the skill, listed in its prompt; a skill's metadata says which it reads",
                                      "type": "object",
                                      "propertyNames": {
                                        "type": "string",
                                        "minLength": 1
                                      },
                                      "additionalProperties": {
                                        "type": [
                                          "string",
                                          "number",
                                          "boolean"
                                        ]
                                      }
                                    },
                                    "when": {
                                      "description": "Run this step only when every key holds; otherwise skip it",
                                      "type": "object",
                                      "properties": {
                                        "verdict": {
                                          "description": "The latest verdict in the chain; a list means any of, {not} negates",
                                          "anyOf": [
                                            {
                                              "anyOf": [
                                                {
                                                  "type": "string",
                                                  "pattern": "^[a-z][a-z_-]*$"
                                                },
                                                {
                                                  "minItems": 1,
                                                  "type": "array",
                                                  "items": {
                                                    "type": "string",
                                                    "pattern": "^[a-z][a-z_-]*$"
                                                  }
                                                }
                                              ]
                                            },
                                            {
                                              "type": "object",
                                              "properties": {
                                                "not": {
                                                  "anyOf": [
                                                    {
                                                      "type": "string",
                                                      "pattern": "^[a-z][a-z_-]*$"
                                                    },
                                                    {
                                                      "minItems": 1,
                                                      "type": "array",
                                                      "items": {
                                                        "type": "string",
                                                        "pattern": "^[a-z][a-z_-]*$"
                                                      }
                                                    }
                                                  ]
                                                }
                                              },
                                              "required": [
                                                "not"
                                              ],
                                              "additionalProperties": false,
                                              "description": "Matches every verdict but these"
                                            }
                                          ]
                                        },
                                        "command": {
                                          "description": "A shell command awaywork runs in the clone, outside the model; exit 0 holds",
                                          "type": "string",
                                          "minLength": 1
                                        },
                                        "changed": {
                                          "description": "Git globs from the repo root; holds when the chain's commits change a matching path, against where the chain started",
                                          "anyOf": [
                                            {
                                              "type": "string"
                                            },
                                            {
                                              "type": "array",
                                              "items": {
                                                "type": "string"
                                              }
                                            }
                                          ]
                                        }
                                      },
                                      "additionalProperties": false
                                    }
                                  },
                                  "required": [
                                    "skill"
                                  ],
                                  "additionalProperties": false
                                }
                              ],
                              "description": "A skill name, or a map with skill, provider, model, skills, mcp and instructions (unset, the rule's), with and when"
                            },
                            {
                              "minItems": 1,
                              "type": "array",
                              "items": {
                                "anyOf": [
                                  {
                                    "type": "string",
                                    "minLength": 1
                                  },
                                  {
                                    "type": "object",
                                    "properties": {
                                      "skill": {
                                        "type": "string",
                                        "minLength": 1,
                                        "description": "The skill that does the work"
                                      },
                                      "provider": {
                                        "description": "Providers for this step, in order; default the rule's, [] the providers order",
                                        "anyOf": [
                                          {
                                            "type": "string"
                                          },
                                          {
                                            "type": "array",
                                            "items": {
                                              "type": "string"
                                            }
                                          }
                                        ]
                                      },
                                      "model": {
                                        "description": "Model per provider for this step; default the rule's",
                                        "type": "object",
                                        "propertyNames": {
                                          "type": "string"
                                        },
                                        "additionalProperties": {
                                          "anyOf": [
                                            {
                                              "type": "string",
                                              "minLength": 1,
                                              "description": "Model passed to the provider's binary; default the binary's"
                                            },
                                            {
                                              "minItems": 2,
                                              "maxItems": 2,
                                              "type": "array",
                                              "items": {
                                                "type": "string",
                                                "minLength": 1,
                                                "description": "Model passed to the provider's binary; default the binary's"
                                              }
                                            }
                                          ],
                                          "description": "A model, or two: a step that fails on the first runs once more on the second"
                                        }
                                      },
                                      "skills": {
                                        "description": "Extra skills available to the worker; default the rule's, [] none",
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        }
                                      },
                                      "mcp": {
                                        "description": "MCP servers the worker gets, by their name under the top-level mcp; default the rule's, [] none",
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        }
                                      },
                                      "instructions": {
                                        "description": "Instruction files added for this step; default the rule's, [] none",
                                        "anyOf": [
                                          {
                                            "type": "string"
                                          },
                                          {
                                            "type": "array",
                                            "items": {
                                              "type": "string"
                                            }
                                          }
                                        ]
                                      },
                                      "with": {
                                        "description": "Parameters for the skill, listed in its prompt; a skill's metadata says which it reads",
                                        "type": "object",
                                        "propertyNames": {
                                          "type": "string",
                                          "minLength": 1
                                        },
                                        "additionalProperties": {
                                          "type": [
                                            "string",
                                            "number",
                                            "boolean"
                                          ]
                                        }
                                      },
                                      "when": {
                                        "description": "Run this step only when every key holds; otherwise skip it",
                                        "type": "object",
                                        "properties": {
                                          "verdict": {
                                            "description": "The latest verdict in the chain; a list means any of, {not} negates",
                                            "anyOf": [
                                              {
                                                "anyOf": [
                                                  {
                                                    "type": "string",
                                                    "pattern": "^[a-z][a-z_-]*$"
                                                  },
                                                  {
                                                    "minItems": 1,
                                                    "type": "array",
                                                    "items": {
                                                      "type": "string",
                                                      "pattern": "^[a-z][a-z_-]*$"
                                                    }
                                                  }
                                                ]
                                              },
                                              {
                                                "type": "object",
                                                "properties": {
                                                  "not": {
                                                    "anyOf": [
                                                      {
                                                        "type": "string",
                                                        "pattern": "^[a-z][a-z_-]*$"
                                                      },
                                                      {
                                                        "minItems": 1,
                                                        "type": "array",
                                                        "items": {
                                                          "type": "string",
                                                          "pattern": "^[a-z][a-z_-]*$"
                                                        }
                                                      }
                                                    ]
                                                  }
                                                },
                                                "required": [
                                                  "not"
                                                ],
                                                "additionalProperties": false,
                                                "description": "Matches every verdict but these"
                                              }
                                            ]
                                          },
                                          "command": {
                                            "description": "A shell command awaywork runs in the clone, outside the model; exit 0 holds",
                                            "type": "string",
                                            "minLength": 1
                                          },
                                          "changed": {
                                            "description": "Git globs from the repo root; holds when the chain's commits change a matching path, against where the chain started",
                                            "anyOf": [
                                              {
                                                "type": "string"
                                              },
                                              {
                                                "type": "array",
                                                "items": {
                                                  "type": "string"
                                                }
                                              }
                                            ]
                                          }
                                        },
                                        "additionalProperties": false
                                      }
                                    },
                                    "required": [
                                      "skill"
                                    ],
                                    "additionalProperties": false
                                  }
                                ],
                                "description": "A skill name, or a map with skill, provider, model, skills, mcp and instructions (unset, the rule's), with and when"
                              }
                            }
                          ]
                        },
                        "until": {
                          "type": "object",
                          "properties": {
                            "verdict": {
                              "description": "The latest verdict a loop step wrote; a list means any of, {not} negates",
                              "anyOf": [
                                {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "pattern": "^[a-z][a-z_-]*$"
                                    },
                                    {
                                      "minItems": 1,
                                      "type": "array",
                                      "items": {
                                        "type": "string",
                                        "pattern": "^[a-z][a-z_-]*$"
                                      }
                                    }
                                  ]
                                },
                                {
                                  "type": "object",
                                  "properties": {
                                    "not": {
                                      "anyOf": [
                                        {
                                          "type": "string",
                                          "pattern": "^[a-z][a-z_-]*$"
                                        },
                                        {
                                          "minItems": 1,
                                          "type": "array",
                                          "items": {
                                            "type": "string",
                                            "pattern": "^[a-z][a-z_-]*$"
                                          }
                                        }
                                      ]
                                    }
                                  },
                                  "required": [
                                    "not"
                                  ],
                                  "additionalProperties": false,
                                  "description": "Matches every verdict but these"
                                }
                              ]
                            },
                            "command": {
                              "description": "A shell command awaywork runs in the clone, outside the model; exit 0 holds",
                              "type": "string",
                              "minLength": 1
                            }
                          },
                          "additionalProperties": false,
                          "description": "Ends the loop as soon as it holds; checked after every step"
                        },
                        "max": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 5,
                          "description": "At most this many rounds, up to 5"
                        }
                      },
                      "required": [
                        "loop",
                        "until",
                        "max"
                      ],
                      "additionalProperties": false,
                      "description": "Steps repeated until a condition holds"
                    }
                  ]
                }
              }
            ]
          },
          "on_done": {
            "description": "Written to the unit's items that are yours once its chain finished and published; a write that fails is only reported",
            "type": "object",
            "properties": {
              "move": {
                "type": "string",
                "minLength": 1,
                "description": "Where the item goes, in its tracker's words: a Jira status, a Linear state, an Asana section, a GitHub label to add"
              },
              "comment": {
                "description": "result posts the unit's result as awaywork's comment, before any move: a report rule's report, else a link to what it published",
                "type": "string",
                "const": "result"
              }
            },
            "additionalProperties": false
          },
          "run": {
            "description": "When its units start: window (default), in the next window run; soon, as soon as awaywork watch sees one due (a new item, or one changed since its last attempt), polling every watch.every",
            "type": "string",
            "enum": [
              "soon",
              "window"
            ]
          }
        },
        "required": [
          "skill"
        ],
        "additionalProperties": false,
        "description": "First matching rule wins; top = highest priority"
      }
    },
    "notify": {
      "description": "Runs after each step of a finished unit and with the morning report when a run ends; a failure is only logged",
      "type": "object",
      "properties": {
        "command": {
          "type": "string",
          "minLength": 1,
          "description": "Shell command; AWAYWORK_EVENT (unit or run) and AWAYWORK_RUN_ID are in its env, plus AWAYWORK_REPORT for a run, and _UNIT, _SKILL, _STATUS, _ITEM_URL, _ITEM_KEY and _SOURCE (one line per item), _REPO and, when there is one, _VERDICT, _PR_URL, _REPORT or _OUT_DIR for a unit"
        },
        "secrets": {
          "default": [],
          "description": "Env vars the command needs; withheld from workers, listed in Actions",
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          }
        }
      },
      "required": [
        "command"
      ],
      "additionalProperties": false
    },
    "store": {
      "description": "Where awaywork puts the files a post pins, plan.yml, reports and whatever else a step leaves in .away/out/, so a unit on any machine reads them back",
      "type": "object",
      "properties": {
        "command": {
          "type": "string",
          "minLength": 1,
          "description": "Shell command run like a custom source's, once per file: it reads {\"op\":\"put\",\"item\",\"unit\",\"path\",\"kind\"} on stdin and prints {\"url\":\"…\"}, or {\"skip\":true} to keep the file out of the store, or reads {\"op\":\"get\",\"url\"} and prints the file's bytes"
        },
        "secrets": {
          "default": [],
          "description": "Env vars the command reads; withheld from workers, listed in Actions",
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[A-Z_][A-Z0-9_]*$"
          }
        },
        "get": {
          "default": true,
          "description": "false: the command only puts, and awaywork reads a file back with a plain HTTP GET of its URL",
          "type": "boolean"
        },
        "read": {
          "description": "What comes back into a unit's context when it reads its item's thread",
          "default": {},
          "type": "object",
          "properties": {
            "max_mb": {
              "default": 10,
              "description": "At most this many MB of a unit's files come back; the rest stay links",
              "type": "number",
              "exclusiveMinimum": 0
            },
            "files": {
              "default": [],
              "description": "Globs of the file names that come back, e.g. [\"*.md\", \"*.yml\"]; default every file",
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          "additionalProperties": false
        }
      },
      "required": [
        "command"
      ],
      "additionalProperties": false
    },
    "keep_runs": {
      "default": "30d",
      "description": "How long run dirs stay; older ones go when awaywork run or watch starts and daily while watch runs, except those holding an item's latest report",
      "type": "string",
      "pattern": "^\\d+[mhdw]$"
    }
  },
  "required": [
    "providers",
    "sources"
  ],
  "additionalProperties": false,
  "$defs": {
    "__schema0": {
      "type": "object",
      "properties": {
        "any": {
          "description": "Matches when at least one of these conditions does; each is a where of its own",
          "minItems": 1,
          "type": "array",
          "items": {
            "$ref": "#/$defs/__schema0"
          }
        }
      },
      "additionalProperties": {
        "anyOf": [
          {
            "anyOf": [
              {
                "type": [
                  "string",
                  "number",
                  "boolean"
                ]
              },
              {
                "minItems": 1,
                "type": "array",
                "items": {
                  "type": [
                    "string",
                    "number",
                    "boolean"
                  ]
                }
              }
            ]
          },
          {
            "type": "object",
            "properties": {
              "not": {
                "anyOf": [
                  {
                    "type": [
                      "string",
                      "number",
                      "boolean"
                    ]
                  },
                  {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": [
                        "string",
                        "number",
                        "boolean"
                      ]
                    }
                  }
                ]
              }
            },
            "required": [
              "not"
            ],
            "additionalProperties": false,
            "description": "Matches items whose field has none of these values"
          },
          {
            "type": "object",
            "properties": {
              "gt": {
                "description": "Greater than",
                "type": "number"
              },
              "gte": {
                "description": "Greater than or equal to",
                "type": "number"
              },
              "lt": {
                "description": "Less than",
                "type": "number"
              },
              "lte": {
                "description": "Less than or equal to",
                "type": "number"
              }
            },
            "additionalProperties": false,
            "description": "Matches items whose number field passes every comparison"
          },
          {
            "type": "object",
            "properties": {
              "older_than": {
                "description": "Longer ago than this span",
                "type": "string",
                "pattern": "^\\d+[mhdw]$"
              },
              "newer_than": {
                "description": "More recent than this span",
                "type": "string",
                "pattern": "^\\d+[mhdw]$"
              }
            },
            "additionalProperties": false,
            "description": "Matches items whose date field is this long before now, e.g. { older_than: 3d }"
          },
          {
            "type": "object",
            "properties": {
              "matches": {
                "type": "string",
                "description": "A regular expression, case-insensitive"
              }
            },
            "required": [
              "matches"
            ],
            "additionalProperties": false,
            "description": "Matches items whose text field contains a match, e.g. `{ matches: '^\\[bug\\]' }`"
          }
        ]
      }
    }
  }
}
