{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://bidvariance.com/docs/bidvariance.project.v1.schema.json",
  "title": "BidVariance project file",
  "description": "Portable, human-readable project format for BidVariance (schema bidvariance.project.v1).",
  "type": "object",
  "required": ["schema", "projectName", "currency", "contractPrice", "targetMargin", "confidenceTarget", "promisedCompletionDate", "tasks", "risks", "settings"],
  "additionalProperties": false,
  "properties": {
    "schema": { "const": "bidvariance.project.v1" },
    "projectName": { "type": "string", "minLength": 1 },
    "currency": { "type": "string", "minLength": 1, "maxLength": 8, "description": "Label only (USD, EUR, GBP, TRY, ...). No exchange rates." },
    "contractPrice": { "type": "number", "exclusiveMinimum": 0 },
    "targetMargin": { "type": "number", "minimum": 0, "maximum": 0.95 },
    "confidenceTarget": { "type": "number", "minimum": 0.5, "maximum": 0.99 },
    "plannedStartDate": { "type": "string", "format": "date" },
    "promisedCompletionDate": { "type": "string", "format": "date" },
    "projectFixedCosts": { "type": "number", "minimum": 0 },
    "overhead": { "type": "number", "minimum": 0 },
    "notes": { "type": "string" },
    "tasks": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "required": ["id", "name", "optimistic", "likely", "pessimistic", "fixedCost", "dailyBurnRate", "deps"],
        "additionalProperties": false,
        "properties": {
          "id": { "type": "string", "minLength": 1 },
          "name": { "type": "string", "minLength": 1 },
          "optimistic": { "type": "number", "minimum": 0, "description": "Days" },
          "likely": { "type": "number", "minimum": 0, "description": "Days" },
          "pessimistic": { "type": "number", "minimum": 0, "description": "Days" },
          "fixedCost": { "type": "number", "minimum": 0 },
          "dailyBurnRate": { "type": "number", "minimum": 0, "description": "Cost per day while the task runs" },
          "deps": { "type": "array", "items": { "type": "string" }, "description": "Task ids this task depends on (Finish-to-Start)" },
          "resourceClass": { "type": "string" },
          "notes": { "type": "string" }
        }
      }
    },
    "risks": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "name", "probability", "costOptimistic", "costLikely", "costPessimistic", "scheduleOptimistic", "scheduleLikely", "schedulePessimistic", "affectedTaskId"],
        "additionalProperties": false,
        "properties": {
          "id": { "type": "string", "minLength": 1 },
          "name": { "type": "string", "minLength": 1 },
          "probability": { "type": "number", "minimum": 0, "maximum": 1 },
          "costOptimistic": { "type": "number", "minimum": 0 },
          "costLikely": { "type": "number", "minimum": 0 },
          "costPessimistic": { "type": "number", "minimum": 0 },
          "scheduleOptimistic": { "type": "number", "minimum": 0, "description": "Days" },
          "scheduleLikely": { "type": "number", "minimum": 0, "description": "Days" },
          "schedulePessimistic": { "type": "number", "minimum": 0, "description": "Days" },
          "affectedTaskId": { "type": "string", "description": "Empty string = project-wide risk" },
          "notes": { "type": "string" }
        }
      }
    },
    "settings": {
      "type": "object",
      "required": ["distribution", "iterations", "seed"],
      "additionalProperties": false,
      "properties": {
        "distribution": { "const": "beta-pert" },
        "iterations": { "type": "integer", "minimum": 1000, "maximum": 200000 },
        "seed": { "type": ["integer", "null"], "minimum": 0, "maximum": 4294967295, "description": "uint32; null = random each run" }
      }
    }
  }
}
