TfP Docs

VerifierContract schema

Generated from the canonical schema schemas/verifier-contract.schema.json by scripts/generate-schema-docs.mjs — do not edit this page by hand.

Stage 6A contract with approved sealed-input extensions. The immutable acceptance semantics for the Problems that pin it. ProblemRevision.verifier_contract_id pins exactly one. A Contract states what a Submission must provide (submission_requirements), which named reference inputs it needs a ProblemRevision to bind (reference_inputs), what acceptance means (statement_md), the ordered stages by which acceptance is checked (stages), the shape of a result (result_kind, plus score when the result is a number), and the fixtures an implementation must reproduce before it may verify authoritatively (conformance_fixtures). Compatibility rule: if the normative acceptance semantics are unchanged, publish a new VerifierImplementation under the same Contract — even when correcting a non-conforming implementation changes the outcomes it produces — and no ProblemRevision moves. If the normative acceptance semantics change, publish a new Contract, which requires a new ProblemRevision. Contracts are immutable and sequentially versioned within their Verifier. yanked_at stops a Contract being recommended for new ProblemRevisions; existing pins keep resolving and existing VerificationRuns keep their meaning.

Schema version: 0.5.0 · $id: https://tokensforprogress.org/schemas/verifier-contract.schema.json

Fields

id

Type: string · Required: yes · Mutable: no · Pattern: ^vct_[0-9a-z]{10,32}$

Stable opaque identifier — what ProblemRevisions pin and what every VerificationRun records.

Example: "vct_01jf90aa4rrc"

verifier_id

Type: string · Required: yes · Mutable: no · Pattern: ^vfr_[0-9a-z]{10,32}$

The Verifier family this Contract belongs to.

Example: "vfr_01jm4nq8xw1p"

version_number

Type: integer · Required: yes · Mutable: no

TfP's own sequential version within the Verifier, starting at 1. A Verifier's current Contract is derived as the highest non-yanked version_number; there is no stored pointer.

Example: 1

title

Type: string · Required: yes · Mutable: no

Short human-readable name of this exact contract, shown wherever a claim is presented.

Example: "Satisfying assignment for the pinned CNF instance"

statement_md

Type: string · Required: yes · Mutable: no

The authoritative human-readable acceptance semantics: what verified means under this Contract, and what the claim does not cover. This text, not any implementation, defines the claim; an implementation that disagrees with it is non-conforming, and the runs it produced are revoked rather than reinterpreted.

Example: "A result is verified when the submitted assignment file, parsed as SAT-competition v-line format, assigns every variable of the pinned CNF instance and satisfies all 91 clauses. Assignments mentioning variables outside the instance are rejected. This establishes that the instance is satisfiable and that this assignment witnesses it. It does NOT establish that the assignment is unique or minimal."

reference_inputs

Type: array · Required: yes · Mutable: no

Named input slots the Contract needs but does not itself contain. A ProblemRevision binds each slot to exact content-addressed bytes (ProblemRevision.verifier_input_bindings), so one SAT Contract serves many Problems, each binding instance to a different CNF, all comparable under one conformance suite. Conformance fixtures bind the same slots to fixture bytes. Slots are mounted read-only at /input/reference/{key}/ for sandbox stages. A sealed slot's bytes are read only by sandbox stages until the binding revision unseals (Sealed reference inputs; defined, not yet available).

reference_inputs[].key

Type: string · Required: yes · Mutable: — · Pattern: ^[a-z0-9]+(_[a-z0-9]+)*$

Slot name, unique within the Contract.

Example: "instance"

reference_inputs[].required

Type: boolean · Required: yes · Mutable: —

Whether every ProblemRevision pinning this Contract must bind the slot.

Example: true

reference_inputs[].sealed

Type: boolean · Required: no · Mutable: — · Default: false

When true, the revision controls participant access and release. Only explicitly selecting sandbox stages and Problem managers receive the bytes while sealed. Defaults to false.

Example: false

reference_inputs[].media_types

Type: array · Required: yes · Mutable: —

Acceptable media types for the bound bytes; empty accepts any.

Example: ["text/plain"]

reference_inputs[].max_bytes

Type: integer · Required: yes · Mutable: —

Maximum size of the bound bytes.

Example: 10485760

reference_inputs[].description

Type: string · Required: yes · Mutable: —

What the slot holds.

Example: "The CNF instance in DIMACS format that the submitted assignment must satisfy."

stages

Type: array · Required: yes · Mutable: no

The ordered plan by which acceptance is checked. Stages run in order, each must pass before the next is attempted, and a run reaches verified only when every stage has passed. Any finite ordered sequence; the three kinds may repeat and appear in any order (sandbox → sandbox → review → sandbox → external is legal). Sequential means only that stage N+1 runs after stage N passes: no parallel stages, no branching, no conditionals. Multiple stages let a Contract distinguish structural validation, expert review, and external acceptance — an ORD deposition is sandbox (valid structure) then review (faithful to the paper) then external (accepted by ORD). Several cheap diagnostic checks belong inside one sandbox implementation, not as extra stages. A run reaching a stage TfP cannot execute finishes inconclusive with the unavailable mechanism recorded.

stages[].key

Type: string · Required: yes · Mutable: — · Pattern: ^[a-z0-9]+(_[a-z0-9]+)*$

Machine-readable stage name, unique within this Contract. VerifierImplementations bind to it and VerificationRun stage results record it.

Example: "assignment_check"

stages[].kind

Type: sandbox | review | external · Required: yes · Mutable: —

Who settles the stage. sandbox: TfP executes a conforming VerifierImplementation in isolation, so a pass means TfP checked it. review: humans and/or agents exercise structured judgment under a ReviewProtocol. external: a system or process outside TfP's sandbox and review engines supplies evidence or an authoritative judgment — an institution's acceptance API, a physical measurement, a future-world outcome. Which of those it is, and how long it takes, belongs in the stage's claim, evidence schema, and rule_owner, not in the kind.

Example: "sandbox"

stages[].title

Type: string · Required: yes · Mutable: —

Human-readable name of this stage, shown in a run's stage list.

Example: "Clause satisfaction check"

stages[].description_md

Type: string · Required: yes · Mutable: —

What this stage establishes on its own, and where relevant what it does not — the claim a partially-completed run is honest about.

Example: "Parses the assignment and evaluates all 91 clauses of the pinned instance. Establishes clause satisfaction only."

stages[].evidence_schema

Type: object \| null · Required: no · Mutable: — · Default: null

For sandbox stages, an optional JSON Schema that /output/evidence/summary.json must satisfy, so evidence is structured and comparable across implementations of the same Contract. For external stages, the schema the returned evidence must satisfy; required when rule_owner is contract. Null for review stages, whose structured outputs are defined by the ReviewProtocol.

Example: null

stages[].review_protocol_id

Type: string \| null · Required: no · Mutable: — · Default: null · Pattern: ^rpt_[0-9a-z]{10,32}$

For review stages: the immutable ReviewProtocol that adjudicates this stage. Its final reducer outcome maps accept → verified, reject → refuted, unresolved → inconclusive. Null for other kinds.

Example: null

stages[].rule_owner

Type: contract | partner | null · Required: no · Mutable: — · Default: null

For external stages only. contract: the external mechanism supplies evidence and TfP applies this Contract's own deterministic acceptance rule to it; the external party's opinion is recorded as a finding, never as the verdict. partner: the claim is explicitly that the named external institution or system accepted, measured, or reported the result, and its judgment is the stage result. Required for external stages; null otherwise. This field is what stops an author-controlled endpoint from manufacturing the claim that TfP independently verified something.

Example: null

stages[].acceptance

Type: object \| null · Required: no · Mutable: — · Default: null

For external stages with rule_owner contract: the deterministic rule TfP applies to the returned evidence (which must satisfy evidence_schema). A closed comparison set, the same discipline as review reducers. Null otherwise.

stages[].external_system

Type: string \| null · Required: no · Mutable: — · Default: null

For external stages: the institution, instrument, or resolution source the claim is about, named so the record reads correctly on its own. Transport and protocol are specified when external stages are implemented; the Contract fixes only who and what.

Example: null

stages[].reference_input_slots

Type: array · Required: no · Mutable: —

Sandbox-only selection of reference slot keys. Required on every sandbox stage when any Contract slot is sealed; [] selects none. Omission on an unsealed legacy Contract selects all slots. Unknown keys are invalid.

stages[].result_kind

Type: pass_fail | score · Required: no · Mutable: —

Sandbox-only result kind, defaulting to the Contract result_kind. Public validation may be pass_fail before a scoring stage. A pass_fail Contract cannot contain score stages; a score Contract needs at least one. The last successful score stage supplies the final run score after the whole plan succeeds.

submission_requirements

Type: object · Required: yes · Mutable: no

What a Submission must provide to be verifiable under this Contract. A Submission that does not satisfy these requirements is not invalid; it is not verifiable, and a run against it resolves inconclusive with the reason recorded, never refuted.

submission_requirements.accepts_text_only

Type: boolean · Required: yes · Mutable: —

Whether the Submission's summary_md alone can carry a verifiable result (true for contracts whose answer is a value; false when the result is necessarily a file).

Example: false

submission_requirements.answer_format_md

Type: string \| null · Required: no · Mutable: — · Default: null

When text is accepted, how the answer must appear in summary_md, precisely enough to parse. Null when text is not accepted.

Example: null

submission_requirements.required_artifacts

Type: array · Required: yes · Mutable: —

Named roles the Submission's referenced Artifacts must fill. Roles, not filenames: mapping is by the Submission's artifact_ids order, so a Contract never dictates what a participant calls a file.

result_kind

Type: pass_fail | score · Required: yes · Mutable: no

pass_fail: the claim holds or it does not (SOLVE and DISCOVERY). score: verification also establishes a measured number on a stated scale (BENCHMARK). A scored run still carries a pass/fail result; a score is only meaningful when the Submission satisfied the Contract.

Example: "pass_fail"

score

Type: object \| null · Required: yes · Mutable: no · Default: null

The scale, required when result_kind is score and null otherwise. Declared on the Contract so runs on the same Contract are comparable.

score.unit

Type: string · Required: yes · Mutable: —

Unit of the reported number.

Example: "accuracy"

score.direction

Type: higher_is_better | lower_is_better · Required: yes · Mutable: —

Which direction is better on this scale.

Example: "higher_is_better"

score.description

Type: string · Required: yes · Mutable: —

Exactly how the number is computed, including the evaluation set.

Example: "Fraction of the 500 held-out instances solved within the per-instance limit."

conformance_fixtures

Type: array · Required: yes · Mutable: no

Known inputs with known expected outcomes, published as part of the Contract. A VerifierImplementation may execute authoritative verification only after reproducing every fixture for the sandbox stage it binds to; the outcome is recorded on the implementation (VerifierImplementation.conformance). Only sandbox stages carry fixtures. A sandbox stage must carry fixtures sufficient to test its declared success and failure semantics, and should include an inconclusive fixture where the stage can distinguish malformed or unverifiable input from substantive failure. Fixtures bind the same reference_inputs slots a ProblemRevision binds, so the conformance suite exercises the real interface. Fixture bytes are stored by TfP with the Contract.

conformance_fixtures[].key

Type: string · Required: yes · Mutable: — · Pattern: ^[a-z0-9]+(_[a-z0-9]+)*$

Machine-readable fixture name, unique within this Contract.

Example: "valid_assignment"

conformance_fixtures[].stage_key

Type: string · Required: yes · Mutable: — · Pattern: ^[a-z0-9]+(_[a-z0-9]+)*$

The sandbox stage this fixture exercises.

Example: "assignment_check"

conformance_fixtures[].description

Type: string · Required: yes · Mutable: —

What case this fixture pins down, and why it is worth pinning.

Example: "A correct satisfying assignment; the baseline positive case."

conformance_fixtures[].inputs

Type: object · Required: yes · Mutable: —

The fixture's stand-in for a Submission, in the same shape a real one is presented in.

conformance_fixtures[].expected_result

Type: verified | refuted | inconclusive · Required: yes · Mutable: —

The outcome a conforming implementation must produce for this fixture. error is not expectable: it reports a failure of TfP's machinery.

Example: "verified"

conformance_fixtures[].expected_score

Type: number \| null · Required: yes · Mutable: — · Default: null

The number a conforming implementation must produce, for score Contracts with an expected_result of verified. Null otherwise.

Example: null

created_by_user_id

Type: string · Required: yes · Mutable: no · Pattern: ^usr_[0-9a-z]{10,32}$

The User who published this Contract version.

Example: "usr_01jf90aa4rrc"

created_at

Type: string · Required: yes · Mutable: no

RFC 3339 UTC timestamp of publication.

Example: "2026-09-05T09:10:00Z"

yanked_at

Type: string \| null · Required: yes · Mutable: yes · Default: null

Write-once withdrawal from recommendation. A yanked Contract is not offered for new ProblemRevisions; existing pins keep resolving and every VerificationRun made under it keeps its meaning. Yanking is not a statement that past claims were wrong — retracting a claim is revocation, recorded per-run.

Example: null

JSON Schema source

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://tokensforprogress.org/schemas/verifier-contract.schema.json",
  "title": "VerifierContract",
  "description": "Stage 6A contract with approved sealed-input extensions. The immutable acceptance semantics for the Problems that pin it. ProblemRevision.verifier_contract_id pins exactly one. A Contract states what a Submission must provide (submission_requirements), which named reference inputs it needs a ProblemRevision to bind (reference_inputs), what acceptance means (statement_md), the ordered stages by which acceptance is checked (stages), the shape of a result (result_kind, plus score when the result is a number), and the fixtures an implementation must reproduce before it may verify authoritatively (conformance_fixtures). Compatibility rule: if the normative acceptance semantics are unchanged, publish a new VerifierImplementation under the same Contract — even when correcting a non-conforming implementation changes the outcomes it produces — and no ProblemRevision moves. If the normative acceptance semantics change, publish a new Contract, which requires a new ProblemRevision. Contracts are immutable and sequentially versioned within their Verifier. yanked_at stops a Contract being recommended for new ProblemRevisions; existing pins keep resolving and existing VerificationRuns keep their meaning.",
  "x-tfp-version": "0.5.0",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "id",
    "verifier_id",
    "version_number",
    "title",
    "statement_md",
    "reference_inputs",
    "stages",
    "submission_requirements",
    "result_kind",
    "score",
    "conformance_fixtures",
    "created_by_user_id",
    "created_at",
    "yanked_at"
  ],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^vct_[0-9a-z]{10,32}$",
      "x-mutable": false,
      "description": "Stable opaque identifier — what ProblemRevisions pin and what every VerificationRun records.",
      "examples": [
        "vct_01jf90aa4rrc"
      ]
    },
    "verifier_id": {
      "type": "string",
      "pattern": "^vfr_[0-9a-z]{10,32}$",
      "x-mutable": false,
      "description": "The Verifier family this Contract belongs to.",
      "examples": [
        "vfr_01jm4nq8xw1p"
      ]
    },
    "version_number": {
      "type": "integer",
      "minimum": 1,
      "x-mutable": false,
      "description": "TfP's own sequential version within the Verifier, starting at 1. A Verifier's current Contract is derived as the highest non-yanked version_number; there is no stored pointer.",
      "examples": [
        1
      ]
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "x-mutable": false,
      "description": "Short human-readable name of this exact contract, shown wherever a claim is presented.",
      "examples": [
        "Satisfying assignment for the pinned CNF instance"
      ]
    },
    "statement_md": {
      "type": "string",
      "minLength": 1,
      "maxLength": 20000,
      "x-mutable": false,
      "description": "The authoritative human-readable acceptance semantics: what `verified` means under this Contract, and what the claim does not cover. This text, not any implementation, defines the claim; an implementation that disagrees with it is non-conforming, and the runs it produced are revoked rather than reinterpreted.",
      "examples": [
        "A result is verified when the submitted assignment file, parsed as SAT-competition v-line format, assigns every variable of the pinned CNF instance and satisfies all 91 clauses. Assignments mentioning variables outside the instance are rejected. This establishes that the instance is satisfiable and that this assignment witnesses it. It does NOT establish that the assignment is unique or minimal."
      ]
    },
    "reference_inputs": {
      "type": "array",
      "maxItems": 10,
      "x-mutable": false,
      "description": "Named input slots the Contract needs but does not itself contain. A ProblemRevision binds each slot to exact content-addressed bytes (ProblemRevision.verifier_input_bindings), so one SAT Contract serves many Problems, each binding `instance` to a different CNF, all comparable under one conformance suite. Conformance fixtures bind the same slots to fixture bytes. Slots are mounted read-only at /input/reference/{key}/ for sandbox stages. A sealed slot's bytes are read only by sandbox stages until the binding revision unseals (Sealed reference inputs; defined, not yet available).",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "key",
          "required",
          "media_types",
          "max_bytes",
          "description"
        ],
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "maxLength": 40,
            "description": "Slot name, unique within the Contract.",
            "examples": [
              "instance"
            ]
          },
          "required": {
            "type": "boolean",
            "description": "Whether every ProblemRevision pinning this Contract must bind the slot.",
            "examples": [
              true
            ]
          },
          "sealed": {
            "type": "boolean",
            "default": false,
            "description": "When true, the revision controls participant access and release. Only explicitly selecting sandbox stages and Problem managers receive the bytes while sealed. Defaults to false.",
            "examples": [
              false,
              true
            ]
          },
          "media_types": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 120
            },
            "uniqueItems": true,
            "description": "Acceptable media types for the bound bytes; empty accepts any.",
            "examples": [
              [
                "text/plain"
              ]
            ]
          },
          "max_bytes": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum size of the bound bytes.",
            "examples": [
              10485760
            ]
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500,
            "description": "What the slot holds.",
            "examples": [
              "The CNF instance in DIMACS format that the submitted assignment must satisfy."
            ]
          }
        }
      }
    },
    "stages": {
      "type": "array",
      "minItems": 1,
      "x-mutable": false,
      "description": "The ordered plan by which acceptance is checked. Stages run in order, each must pass before the next is attempted, and a run reaches `verified` only when every stage has passed. Any finite ordered sequence; the three kinds may repeat and appear in any order (sandbox → sandbox → review → sandbox → external is legal). Sequential means only that stage N+1 runs after stage N passes: no parallel stages, no branching, no conditionals. Multiple stages let a Contract distinguish structural validation, expert review, and external acceptance — an ORD deposition is sandbox (valid structure) then review (faithful to the paper) then external (accepted by ORD). Several cheap diagnostic checks belong inside one sandbox implementation, not as extra stages. A run reaching a stage TfP cannot execute finishes `inconclusive` with the unavailable mechanism recorded.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "key",
          "kind",
          "title",
          "description_md"
        ],
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "maxLength": 40,
            "description": "Machine-readable stage name, unique within this Contract. VerifierImplementations bind to it and VerificationRun stage results record it.",
            "examples": [
              "assignment_check"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "sandbox",
              "review",
              "external"
            ],
            "description": "Who settles the stage. `sandbox`: TfP executes a conforming VerifierImplementation in isolation, so a pass means TfP checked it. `review`: humans and/or agents exercise structured judgment under a ReviewProtocol. `external`: a system or process outside TfP's sandbox and review engines supplies evidence or an authoritative judgment — an institution's acceptance API, a physical measurement, a future-world outcome. Which of those it is, and how long it takes, belongs in the stage's claim, evidence schema, and rule_owner, not in the kind.",
            "examples": [
              "sandbox"
            ]
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Human-readable name of this stage, shown in a run's stage list.",
            "examples": [
              "Clause satisfaction check"
            ]
          },
          "description_md": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10000,
            "description": "What this stage establishes on its own, and where relevant what it does not — the claim a partially-completed run is honest about.",
            "examples": [
              "Parses the assignment and evaluates all 91 clauses of the pinned instance. Establishes clause satisfaction only."
            ]
          },
          "evidence_schema": {
            "type": [
              "object",
              "null"
            ],
            "default": null,
            "description": "For `sandbox` stages, an optional JSON Schema that /output/evidence/summary.json must satisfy, so evidence is structured and comparable across implementations of the same Contract. For `external` stages, the schema the returned evidence must satisfy; required when rule_owner is `contract`. Null for `review` stages, whose structured outputs are defined by the ReviewProtocol.",
            "examples": [
              null
            ]
          },
          "review_protocol_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^rpt_[0-9a-z]{10,32}$",
            "default": null,
            "description": "For `review` stages: the immutable ReviewProtocol that adjudicates this stage. Its final reducer outcome maps accept → verified, reject → refuted, unresolved → inconclusive. Null for other kinds.",
            "examples": [
              null
            ]
          },
          "rule_owner": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "contract",
              "partner",
              null
            ],
            "default": null,
            "description": "For `external` stages only. `contract`: the external mechanism supplies evidence and TfP applies this Contract's own deterministic acceptance rule to it; the external party's opinion is recorded as a finding, never as the verdict. `partner`: the claim is explicitly that the named external institution or system accepted, measured, or reported the result, and its judgment is the stage result. Required for external stages; null otherwise. This field is what stops an author-controlled endpoint from manufacturing the claim that TfP independently verified something.",
            "examples": [
              null
            ]
          },
          "acceptance": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": false,
            "default": null,
            "required": [
              "field",
              "op",
              "value"
            ],
            "description": "For `external` stages with rule_owner `contract`: the deterministic rule TfP applies to the returned evidence (which must satisfy evidence_schema). A closed comparison set, the same discipline as review reducers. Null otherwise.",
            "properties": {
              "field": {
                "type": "string",
                "minLength": 1,
                "maxLength": 120,
                "description": "JSON pointer-style path into the evidence summary.",
                "examples": [
                  "target_phase_fraction"
                ]
              },
              "op": {
                "type": "string",
                "enum": [
                  "eq",
                  "gte",
                  "lte",
                  "in"
                ],
                "description": "Comparison.",
                "examples": [
                  "gte"
                ]
              },
              "value": {
                "description": "Comparand: a scalar for eq/gte/lte, an array for in.",
                "examples": [
                  0.5
                ]
              }
            }
          },
          "external_system": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200,
            "default": null,
            "description": "For `external` stages: the institution, instrument, or resolution source the claim is about, named so the record reads correctly on its own. Transport and protocol are specified when external stages are implemented; the Contract fixes only who and what.",
            "examples": [
              null
            ]
          },
          "reference_input_slots": {
            "type": "array",
            "maxItems": 10,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
              "maxLength": 40
            },
            "description": "Sandbox-only selection of reference slot keys. Required on every sandbox stage when any Contract slot is sealed; [] selects none. Omission on an unsealed legacy Contract selects all slots. Unknown keys are invalid."
          },
          "result_kind": {
            "type": "string",
            "enum": [
              "pass_fail",
              "score"
            ],
            "description": "Sandbox-only result kind, defaulting to the Contract result_kind. Public validation may be pass_fail before a scoring stage. A pass_fail Contract cannot contain score stages; a score Contract needs at least one. The last successful score stage supplies the final run score after the whole plan succeeds."
          }
        },
        "allOf": [
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "review"
                }
              }
            },
            "then": {
              "properties": {
                "review_protocol_id": {
                  "type": "string"
                }
              },
              "required": [
                "review_protocol_id"
              ]
            }
          },
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "external"
                }
              }
            },
            "then": {
              "properties": {
                "rule_owner": {
                  "type": "string"
                },
                "external_system": {
                  "type": "string"
                }
              },
              "required": [
                "rule_owner",
                "external_system"
              ]
            }
          },
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "external"
                },
                "rule_owner": {
                  "const": "contract"
                }
              },
              "required": [
                "rule_owner"
              ]
            },
            "then": {
              "properties": {
                "acceptance": {
                  "type": "object"
                },
                "evidence_schema": {
                  "type": "object"
                }
              },
              "required": [
                "acceptance",
                "evidence_schema"
              ]
            }
          },
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "sandbox"
                }
              }
            },
            "then": {
              "properties": {
                "review_protocol_id": {
                  "type": "null"
                },
                "rule_owner": {
                  "type": "null"
                },
                "acceptance": {
                  "type": "null"
                },
                "external_system": {
                  "type": "null"
                }
              }
            }
          }
        ]
      }
    },
    "submission_requirements": {
      "type": "object",
      "additionalProperties": false,
      "x-mutable": false,
      "required": [
        "accepts_text_only",
        "required_artifacts"
      ],
      "description": "What a Submission must provide to be verifiable under this Contract. A Submission that does not satisfy these requirements is not invalid; it is not verifiable, and a run against it resolves `inconclusive` with the reason recorded, never `refuted`.",
      "properties": {
        "accepts_text_only": {
          "type": "boolean",
          "description": "Whether the Submission's summary_md alone can carry a verifiable result (true for contracts whose answer is a value; false when the result is necessarily a file).",
          "examples": [
            false
          ]
        },
        "answer_format_md": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 4000,
          "default": null,
          "description": "When text is accepted, how the answer must appear in summary_md, precisely enough to parse. Null when text is not accepted.",
          "examples": [
            null
          ]
        },
        "required_artifacts": {
          "type": "array",
          "maxItems": 10,
          "description": "Named roles the Submission's referenced Artifacts must fill. Roles, not filenames: mapping is by the Submission's artifact_ids order, so a Contract never dictates what a participant calls a file.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "role",
              "description",
              "media_types",
              "max_bytes"
            ],
            "properties": {
              "role": {
                "type": "string",
                "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
                "maxLength": 40,
                "description": "Machine-readable role name, unique within this Contract.",
                "examples": [
                  "assignment"
                ]
              },
              "description": {
                "type": "string",
                "minLength": 1,
                "maxLength": 500,
                "description": "What this artifact must contain.",
                "examples": [
                  "A satisfying assignment in SAT-competition v-line format."
                ]
              },
              "media_types": {
                "type": "array",
                "maxItems": 10,
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 120
                },
                "uniqueItems": true,
                "description": "Acceptable declared media types; empty accepts any. media_type is participant-declared and stored canonicalized, so an implementation must validate content rather than trust the label.",
                "examples": [
                  [
                    "text/plain"
                  ]
                ]
              },
              "max_bytes": {
                "type": "integer",
                "minimum": 1,
                "description": "Maximum size accepted for this role.",
                "examples": [
                  1048576
                ]
              }
            }
          }
        }
      }
    },
    "result_kind": {
      "type": "string",
      "enum": [
        "pass_fail",
        "score"
      ],
      "x-mutable": false,
      "description": "`pass_fail`: the claim holds or it does not (SOLVE and DISCOVERY). `score`: verification also establishes a measured number on a stated scale (BENCHMARK). A scored run still carries a pass/fail result; a score is only meaningful when the Submission satisfied the Contract.",
      "examples": [
        "pass_fail"
      ]
    },
    "score": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "x-mutable": false,
      "default": null,
      "required": [
        "unit",
        "direction",
        "description"
      ],
      "description": "The scale, required when result_kind is `score` and null otherwise. Declared on the Contract so runs on the same Contract are comparable.",
      "properties": {
        "unit": {
          "type": "string",
          "minLength": 1,
          "maxLength": 60,
          "description": "Unit of the reported number.",
          "examples": [
            "accuracy"
          ]
        },
        "direction": {
          "type": "string",
          "enum": [
            "higher_is_better",
            "lower_is_better"
          ],
          "description": "Which direction is better on this scale.",
          "examples": [
            "higher_is_better"
          ]
        },
        "description": {
          "type": "string",
          "minLength": 1,
          "maxLength": 2000,
          "description": "Exactly how the number is computed, including the evaluation set.",
          "examples": [
            "Fraction of the 500 held-out instances solved within the per-instance limit."
          ]
        }
      }
    },
    "conformance_fixtures": {
      "type": "array",
      "maxItems": 100,
      "x-mutable": false,
      "description": "Known inputs with known expected outcomes, published as part of the Contract. A VerifierImplementation may execute authoritative verification only after reproducing every fixture for the sandbox stage it binds to; the outcome is recorded on the implementation (VerifierImplementation.conformance). Only `sandbox` stages carry fixtures. A sandbox stage must carry fixtures sufficient to test its declared success and failure semantics, and should include an `inconclusive` fixture where the stage can distinguish malformed or unverifiable input from substantive failure. Fixtures bind the same reference_inputs slots a ProblemRevision binds, so the conformance suite exercises the real interface. Fixture bytes are stored by TfP with the Contract.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "key",
          "stage_key",
          "description",
          "inputs",
          "expected_result",
          "expected_score"
        ],
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "maxLength": 60,
            "description": "Machine-readable fixture name, unique within this Contract.",
            "examples": [
              "valid_assignment"
            ]
          },
          "stage_key": {
            "type": "string",
            "pattern": "^[a-z0-9]+(_[a-z0-9]+)*$",
            "maxLength": 40,
            "description": "The `sandbox` stage this fixture exercises.",
            "examples": [
              "assignment_check"
            ]
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1000,
            "description": "What case this fixture pins down, and why it is worth pinning.",
            "examples": [
              "A correct satisfying assignment; the baseline positive case."
            ]
          },
          "inputs": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "reference",
              "artifacts",
              "summary_text"
            ],
            "description": "The fixture's stand-in for a Submission, in the same shape a real one is presented in.",
            "properties": {
              "reference": {
                "type": "object",
                "description": "Fixture bytes bound to the Contract's reference_inputs slots, keyed by slot key. Every required slot must be bound.",
                "additionalProperties": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "filename",
                    "content_hash",
                    "size_bytes"
                  ],
                  "properties": {
                    "filename": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 255,
                      "examples": [
                        "small.cnf"
                      ]
                    },
                    "content_hash": {
                      "type": "string",
                      "pattern": "^sha256:[0-9a-f]{64}$"
                    },
                    "size_bytes": {
                      "type": "integer",
                      "minimum": 0
                    }
                  }
                }
              },
              "artifacts": {
                "type": "array",
                "maxItems": 10,
                "description": "Fixture files by Contract role, stored with the Contract and identified by hash.",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "role",
                    "filename",
                    "content_hash",
                    "size_bytes"
                  ],
                  "properties": {
                    "role": {
                      "type": "string",
                      "maxLength": 40,
                      "description": "Contract role this file fills.",
                      "examples": [
                        "assignment"
                      ]
                    },
                    "filename": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 255,
                      "description": "Display name of the fixture file.",
                      "examples": [
                        "valid.txt"
                      ]
                    },
                    "content_hash": {
                      "type": "string",
                      "pattern": "^sha256:[0-9a-f]{64}$",
                      "description": "Hash of the stored fixture bytes.",
                      "examples": [
                        "sha256:3f786850e387550fdab836ed7e6dc881de23001b3f786850e387550fdab836ed"
                      ]
                    },
                    "size_bytes": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Size of the stored fixture bytes.",
                      "examples": [
                        512
                      ]
                    }
                  }
                }
              },
              "summary_text": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 10000,
                "default": null,
                "description": "Stand-in for the Submission's summary_md, for Contracts that accept a text answer. Null otherwise.",
                "examples": [
                  null
                ]
              }
            }
          },
          "expected_result": {
            "type": "string",
            "enum": [
              "verified",
              "refuted",
              "inconclusive"
            ],
            "description": "The outcome a conforming implementation must produce for this fixture. `error` is not expectable: it reports a failure of TfP's machinery.",
            "examples": [
              "verified"
            ]
          },
          "expected_score": {
            "type": [
              "number",
              "null"
            ],
            "default": null,
            "description": "The number a conforming implementation must produce, for `score` Contracts with an expected_result of `verified`. Null otherwise.",
            "examples": [
              null
            ]
          }
        }
      }
    },
    "created_by_user_id": {
      "type": "string",
      "pattern": "^usr_[0-9a-z]{10,32}$",
      "x-mutable": false,
      "description": "The User who published this Contract version.",
      "examples": [
        "usr_01jf90aa4rrc"
      ]
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "x-mutable": false,
      "description": "RFC 3339 UTC timestamp of publication.",
      "examples": [
        "2026-09-05T09:10:00Z"
      ]
    },
    "yanked_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "x-mutable": true,
      "default": null,
      "description": "Write-once withdrawal from recommendation. A yanked Contract is not offered for new ProblemRevisions; existing pins keep resolving and every VerificationRun made under it keeps its meaning. Yanking is not a statement that past claims were wrong — retracting a claim is revocation, recorded per-run.",
      "examples": [
        null
      ]
    }
  }
}