{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/githunt-ai/json-schema/githunt-ai-brief-request-schema.json",
  "title": "BriefRequest",
  "x-generated": "2026-10-30",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/githunt-ai-openapi.yaml#/components/schemas/BriefRequest",
  "type": "object",
  "required": [
    "criteria",
    "geography"
  ],
  "properties": {
    "criteria": {
      "type": "object",
      "description": "What the candidate must be. At least one language or skill is needed for evidence to be gathered.",
      "properties": {
        "languages": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "skills": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "role": {
          "type": "string",
          "description": "Role profile to score against, same list as `POST /v1/search`."
        },
        "sectors": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Employer sectors to favour via the employer graph, max 5."
        },
        "domains": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Domain packs to assess core subject-matter work against, max 3. Without a domain every card comes back with domain tier `none`."
        },
        "skillRecency": {
          "type": "array",
          "description": "Hard eligibility filter on evidenced skill recency, same shape as search.",
          "items": {
            "type": "object",
            "properties": {
              "skill": {
                "type": "string"
              },
              "minActiveYears": {
                "type": "number"
              },
              "usedWithinYears": {
                "type": "number"
              }
            }
          }
        }
      }
    },
    "geography": {
      "type": "object",
      "description": "Where to look, and where not to. At least one of `regions` or `locations` is required.",
      "properties": {
        "regions": {
          "type": "array",
          "maxItems": 6,
          "items": {
            "type": "string"
          },
          "description": "Regions to cover, max 6 - more than a single search request may carry. Each expands into countries searched three at a time, so every country gets the ranker's full scoring depth."
        },
        "locations": {
          "type": "array",
          "maxItems": 20,
          "items": {
            "type": "string"
          }
        },
        "excludeLocations": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "excludeUtcOffsets": {
          "type": "object",
          "description": "Inclusive UTC offset band to exclude at the run timestamp, with DST applied. `{min: 0, max: 5}` leaves +5:30 and +5:45 eligible.",
          "properties": {
            "min": {
              "type": "number"
            },
            "max": {
              "type": "number"
            }
          }
        },
        "includeUnlocated": {
          "type": "boolean",
          "description": "Include candidates with no stated location. They can never be delivered, only surfaced as screening leads."
        }
      }
    },
    "deliver": {
      "type": "object",
      "properties": {
        "maxProfiles": {
          "type": "integer",
          "minimum": 1,
          "maximum": 25,
          "default": 10
        },
        "maxScreeningLeads": {
          "type": "integer",
          "minimum": 0,
          "maximum": 50,
          "default": 15
        },
        "evidence": {
          "type": "boolean",
          "default": true,
          "description": "Gather evidence reports for the shortlist. With `false` the run is faster but no profile carries verified commits, so every result is a lead."
        }
      }
    }
  }
}