{
  "$type": "com.atproto.lexicon.schema",
  "defs": {
    "creditEntry": {
      "properties": {
        "credits": {
          "description": "Voice credits spent on this proposal (integer, whole credits).",
          "maximum": 100,
          "minimum": 0,
          "type": "integer"
        },
        "proposal": {
          "description": "AT-URI of the proposal (org.hypercerts.claim.activity), or a \"title:<title>\" fallback key.",
          "type": "string"
        },
        "proposalTitle": {
          "description": "Display title at cast time.",
          "maxLength": 500,
          "type": "string"
        }
      },
      "required": [
        "proposal",
        "credits"
      ],
      "type": "object"
    },
    "creditsBallot": {
      "description": "Quadratic Voting ballot: voice credits spent per proposal. Effective votes are the square root of credits; a sim spends at most 100 credits per run.",
      "properties": {
        "credits": {
          "items": {
            "ref": "#creditEntry",
            "type": "ref"
          },
          "maxLength": 100,
          "type": "array"
        },
        "reasoning": {
          "description": "The sim's in-character reasoning for this spread.",
          "maxGraphemes": 5000,
          "maxLength": 10000,
          "type": "string"
        }
      },
      "required": [
        "credits"
      ],
      "type": "object"
    },
    "main": {
      "description": "One sim's elicited ballot in a funding-mechanism run (S-Process, Quadratic Voting, …). Ballots are the public, replayable elicitation layer of a run: anyone can recompute the outcome by feeding a run's ballots through the mechanism's deterministic aggregator. The `payload` union carries the mechanism-specific ballot shape; new mechanisms extend the union without breaking existing readers. Written by the run initiator; the sim that cast the ballot is attributed via `simUri`. Fixed-point convention: fields ending in `Milli` store real numbers ×1000 (lexicons have no float type).",
      "key": "tid",
      "record": {
        "properties": {
          "createdAt": {
            "format": "datetime",
            "type": "string"
          },
          "gatheringUri": {
            "description": "Scope identifier: usually the AT-URI of an org.simocracy.gathering record; a sentinel string for built-in scopes (e.g. \"ftc-sf:tower\").",
            "type": "string"
          },
          "mechanism": {
            "description": "Versioned mechanism id that elicited this ballot, e.g. \"s-process@1\" or \"quadratic-voting@1\".",
            "maxLength": 64,
            "type": "string"
          },
          "payload": {
            "description": "Mechanism-specific ballot content.",
            "refs": [
              "#mvfBallot",
              "#creditsBallot"
            ],
            "type": "union"
          },
          "round": {
            "description": "Deliberation round this ballot was cast in (0-based). Omitted for single-round runs.",
            "minimum": 0,
            "type": "integer"
          },
          "run": {
            "description": "Run identifier this ballot belongs to. Matches the run's org.simocracy.history `hearingId` and the published decision's `runId`.",
            "maxLength": 64,
            "type": "string"
          },
          "simName": {
            "description": "Display name of the sim at cast time (denormalised for cheap rendering).",
            "maxLength": 200,
            "type": "string"
          },
          "simUri": {
            "description": "AT-URI of the org.simocracy.sim that cast this ballot.",
            "type": "string"
          }
        },
        "required": [
          "run",
          "mechanism",
          "gatheringUri",
          "simUri",
          "payload",
          "createdAt"
        ],
        "type": "object"
      },
      "type": "record"
    },
    "mvfBallot": {
      "description": "S-Process ballot: one marginal-value function per proposal.",
      "properties": {
        "evaluations": {
          "items": {
            "ref": "#mvfEvaluation",
            "type": "ref"
          },
          "maxLength": 100,
          "type": "array"
        },
        "outsideOptionMilli": {
          "description": "Marginal value of keeping a dollar for future rounds, ×1000 (fixed-point: 500 = 0.5).",
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "evaluations"
      ],
      "type": "object"
    },
    "mvfEvaluation": {
      "properties": {
        "mvf": {
          "description": "Piecewise-linear marginal value function, points sorted ascending by dollars.",
          "items": {
            "ref": "#mvfPoint",
            "type": "ref"
          },
          "maxLength": 20,
          "type": "array"
        },
        "proposal": {
          "description": "AT-URI of the evaluated proposal (org.hypercerts.claim.activity), or a \"title:<title>\" fallback key when the URI could not be resolved.",
          "type": "string"
        },
        "proposalTitle": {
          "description": "Display title at cast time.",
          "maxLength": 500,
          "type": "string"
        },
        "reasoning": {
          "description": "The sim's in-character reasoning for this curve.",
          "maxGraphemes": 5000,
          "maxLength": 10000,
          "type": "string"
        }
      },
      "required": [
        "proposal",
        "mvf"
      ],
      "type": "object"
    },
    "mvfPoint": {
      "properties": {
        "dollars": {
          "description": "Funding level in whole USD.",
          "minimum": 0,
          "type": "integer"
        },
        "marginalValueMilli": {
          "description": "Value-per-dollar of the next dollar at this funding level, ×1000 (fixed-point: 1500 = 1.5).",
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "dollars",
        "marginalValueMilli"
      ],
      "type": "object"
    }
  },
  "id": "org.simocracy.ballot",
  "lexicon": 1
}
