TfP Docs

ReviewAssignment schema

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

Frozen contract (Stage 7A, 2026-09-02; seats and claims 2026-09-02; assistance declaration 2026-09-03). One claim of one seat on one review node of one ReviewProcess by a User (or one TfP-hosted agent issuance), and what came back. The assignment records exactly who judged (the accountable User for a human; the effective provider/model/config TfP executed for a hosted agent), what assistance a human declared (provenance in the reviewer's words, not identity and not an execution record), what context was supplied (SkillVersions, visible prior nodes, stage evidence, what was hidden), and the schema-validated structured response with its rationale, citations, and any declared confidence. Reduce nodes never have assignments. Review work is not a Problem: an assignment is operational work generated because another object needs adjudication.

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

Fields

id

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

Example: "ras_01jq8s5f2jan"

review_process_id

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

node_id

Type: string · Required: yes · Mutable: no · Pattern: ^[a-z][a-z0-9_]{0,39}$

reviewer

Type: object · Required: yes · Mutable: no

Who is accountable for this judgment.

reviewer.kind

Type: human | agent · Required: yes · Mutable: —

reviewer.user_id

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

The accountable User for a human reviewer; null for an agent.

reviewer.agent

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

The exact provider/model/config for an agent reviewer; null for a human.

assistance

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

For a human reviewer who used an agent while forming the judgment: the model and configuration, recorded as provenance. The human remains the accountable reviewer. Null for agent reviewers and for unassisted humans.

assistance.provider

Type: string · Required: yes · Mutable: —

The provider of the agent that assisted, as the reviewer names it. Any string; TfP did not invoke it.

Example: "anthropic"

assistance.model

Type: string · Required: yes · Mutable: —

The model the reviewer says assisted them, as they name it.

Example: "claude-opus-5"

assistance.config

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

Optional self-declared provenance supplied by the accountable reviewer (tools, settings, how the agent was run); TfP did not independently verify these settings and does not require any. Never an execution record.

Example: {"tools":["claude-code"],"effort":"high"}

context

Type: object · Required: yes · Mutable: no

Exactly what was supplied to the reviewer, so a judgment can later be evaluated against what its author could see.

context.skill_version_ids

Type: array · Required: yes · Mutable: —

context.visible_node_ids

Type: array · Required: yes · Mutable: —

context.stage_evidence_included

Type: boolean · Required: yes · Mutable: —

context.hidden

Type: array · Required: yes · Mutable: —

independence_group

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

Reviewers in different groups on the same node cannot see one another's responses before completing. Null when the node is not independent.

status

Type: pending | accepted | completed | declined | expired | invalid · Required: yes · Mutable: yes

accepted (a human claimed the seat; the hold is running) → completed, or declined (the claim was released) or expired (the hold or the node deadline passed). Agent-kind assignments additionally use pending (issued, not yet answered) and invalid (a reply that failed the rubric; retained).

response

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

The structured response, validated against the node's rubric.response_schema. Null until a response arrives. On an invalid assignment, the rejected response as submitted.

rationale_md

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

The reviewer's communicable justification, required when the rubric says so. Not hidden reasoning: TfP does not request, store, or expose chain-of-thought.

citations

Type: array · Required: yes · Mutable: yes · Default: []

Structured evidence pointers, at least rubric.citations.min_items of them on a completed assignment.

citations[].resource_uri

Type: string \| null · Required: yes · Mutable: — · Pattern: ^tfp://

The material cited, by the same tfp:// Resource URI TfP handed the reviewer (an Artifact, a reference input, a Skill file). Preferred; artifact_id is derived from it for Artifacts.

citations[].artifact_id

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

The Artifact cited, when the citation is an Artifact; derived from resource_uri.

citations[].resource

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

A URI or named reference when the evidence is not an Artifact (a reference input slot, a supplied Skill, an external document).

citations[].locator

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

Page, line, section, byte range, or similar.

citations[].quote

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

confidence

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

Overall declared confidence in [0, 1]; required when the rubric says so. Lives here, not inside response, so it reads the same across every protocol.

decline_reason

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

created_at

Type: string · Required: yes · Mutable: no

accepted_at

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

completed_at

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

expired_at

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

invalid_reason

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

For invalid assignments: which rubric requirement the response failed.

hold_until

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

When the claim lapses if no response has been recorded (claimed_at + the protocol's claim_hold_minutes). Null for agent-kind assignments.

Example: "2026-09-05T12:00:00Z"

JSON Schema source

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://tokensforprogress.org/schemas/review-assignment.schema.json",
  "title": "ReviewAssignment",
  "description": "Frozen contract (Stage 7A, 2026-09-02; seats and claims 2026-09-02; assistance declaration 2026-09-03). One claim of one seat on one `review` node of one ReviewProcess by a User (or one TfP-hosted agent issuance), and what came back. The assignment records exactly who judged (the accountable User for a human; the effective provider/model/config TfP executed for a hosted agent), what assistance a human declared (provenance in the reviewer's words, not identity and not an execution record), what context was supplied (SkillVersions, visible prior nodes, stage evidence, what was hidden), and the schema-validated structured response with its rationale, citations, and any declared confidence. Reduce nodes never have assignments. Review work is not a Problem: an assignment is operational work generated because another object needs adjudication.",
  "x-tfp-version": "0.5.0",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "id",
    "review_process_id",
    "node_id",
    "reviewer",
    "assistance",
    "context",
    "independence_group",
    "status",
    "response",
    "rationale_md",
    "citations",
    "confidence",
    "decline_reason",
    "invalid_reason",
    "created_at",
    "accepted_at",
    "completed_at",
    "expired_at",
    "hold_until"
  ],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^ras_[0-9a-z]{10,32}$",
      "x-mutable": false,
      "examples": [
        "ras_01jq8s5f2jan"
      ]
    },
    "review_process_id": {
      "type": "string",
      "pattern": "^rpr_[0-9a-z]{10,32}$",
      "x-mutable": false
    },
    "node_id": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9_]{0,39}$",
      "x-mutable": false
    },
    "reviewer": {
      "type": "object",
      "additionalProperties": false,
      "x-mutable": false,
      "required": [
        "kind",
        "user_id",
        "agent"
      ],
      "description": "Who is accountable for this judgment.",
      "properties": {
        "kind": {
          "type": "string",
          "enum": [
            "human",
            "agent"
          ]
        },
        "user_id": {
          "type": [
            "string",
            "null"
          ],
          "pattern": "^usr_[0-9a-z]{10,32}$",
          "default": null,
          "description": "The accountable User for a human reviewer; null for an agent."
        },
        "agent": {
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": false,
          "required": [
            "provider",
            "model",
            "config"
          ],
          "properties": {
            "provider": {
              "type": "string",
              "minLength": 1,
              "maxLength": 60,
              "description": "Model provider identifier.",
              "examples": [
                "anthropic"
              ]
            },
            "model": {
              "type": "string",
              "minLength": 1,
              "maxLength": 120,
              "description": "Exact model identifier.",
              "examples": [
                "claude-fable-5-1"
              ]
            },
            "config": {
              "type": "object",
              "description": "The effective configuration TfP executed for this hosted agent: the protocol's allowed spec with the provider's defaults resolved at issue time (Anthropic: `effort`, `max_tokens`). Exact, because TfP performed the invocation; what the record says is what ran.",
              "examples": [
                {
                  "effort": "high",
                  "max_tokens": 16000
                }
              ]
            }
          },
          "default": null,
          "description": "The exact provider/model/config for an agent reviewer; null for a human."
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "kind": {
                "const": "human"
              }
            }
          },
          "then": {
            "properties": {
              "user_id": {
                "type": "string"
              },
              "agent": {
                "type": "null"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "kind": {
                "const": "agent"
              }
            }
          },
          "then": {
            "properties": {
              "agent": {
                "type": "object"
              },
              "user_id": {
                "type": "null"
              }
            }
          }
        }
      ]
    },
    "assistance": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "required": [
        "provider",
        "model"
      ],
      "properties": {
        "provider": {
          "type": "string",
          "minLength": 1,
          "maxLength": 60,
          "description": "The provider of the agent that assisted, as the reviewer names it. Any string; TfP did not invoke it.",
          "examples": [
            "anthropic"
          ]
        },
        "model": {
          "type": "string",
          "minLength": 1,
          "maxLength": 120,
          "description": "The model the reviewer says assisted them, as they name it.",
          "examples": [
            "claude-opus-5"
          ]
        },
        "config": {
          "type": [
            "object",
            "null"
          ],
          "default": null,
          "description": "Optional self-declared provenance supplied by the accountable reviewer (tools, settings, how the agent was run); TfP did not independently verify these settings and does not require any. Never an execution record.",
          "examples": [
            {
              "tools": [
                "claude-code"
              ],
              "effort": "high"
            }
          ]
        }
      },
      "default": null,
      "x-mutable": true,
      "description": "For a human reviewer who used an agent while forming the judgment: the model and configuration, recorded as provenance. The human remains the accountable reviewer. Null for agent reviewers and for unassisted humans."
    },
    "context": {
      "type": "object",
      "additionalProperties": false,
      "x-mutable": false,
      "required": [
        "skill_version_ids",
        "visible_node_ids",
        "stage_evidence_included",
        "hidden"
      ],
      "description": "Exactly what was supplied to the reviewer, so a judgment can later be evaluated against what its author could see.",
      "properties": {
        "skill_version_ids": {
          "type": "array",
          "maxItems": 10,
          "items": {
            "type": "string",
            "pattern": "^skv_[0-9a-z]{10,32}$"
          },
          "uniqueItems": true
        },
        "visible_node_ids": {
          "type": "array",
          "maxItems": 20,
          "items": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9_]{0,39}$"
          },
          "uniqueItems": true
        },
        "stage_evidence_included": {
          "type": "boolean"
        },
        "hidden": {
          "type": "array",
          "maxItems": 5,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "enum": [
              "submitter_identity",
              "submitter_organization",
              "prior_scores",
              "attempt_notes"
            ]
          }
        }
      }
    },
    "independence_group": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 40,
      "x-mutable": false,
      "default": null,
      "description": "Reviewers in different groups on the same node cannot see one another's responses before completing. Null when the node is not independent."
    },
    "status": {
      "type": "string",
      "enum": [
        "pending",
        "accepted",
        "completed",
        "declined",
        "expired",
        "invalid"
      ],
      "x-mutable": true,
      "description": "accepted (a human claimed the seat; the hold is running) → completed, or declined (the claim was released) or expired (the hold or the node deadline passed). Agent-kind assignments additionally use pending (issued, not yet answered) and invalid (a reply that failed the rubric; retained)."
    },
    "response": {
      "type": [
        "object",
        "null"
      ],
      "x-mutable": true,
      "default": null,
      "description": "The structured response, validated against the node's rubric.response_schema. Null until a response arrives. On an invalid assignment, the rejected response as submitted."
    },
    "rationale_md": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 50000,
      "x-mutable": true,
      "default": null,
      "description": "The reviewer's communicable justification, required when the rubric says so. Not hidden reasoning: TfP does not request, store, or expose chain-of-thought."
    },
    "citations": {
      "type": "array",
      "maxItems": 100,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "resource_uri",
          "artifact_id",
          "resource",
          "locator",
          "quote"
        ],
        "description": "A structured pointer to evidence supporting a judgment: which Artifact or resource, where in it, and optionally the passage.",
        "properties": {
          "resource_uri": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^tfp://",
            "maxLength": 500,
            "description": "The material cited, by the same tfp:// Resource URI TfP handed the reviewer (an Artifact, a reference input, a Skill file). Preferred; artifact_id is derived from it for Artifacts."
          },
          "artifact_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^art_[0-9a-z]{10,32}$",
            "default": null,
            "description": "The Artifact cited, when the citation is an Artifact; derived from resource_uri."
          },
          "resource": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500,
            "default": null,
            "description": "A URI or named reference when the evidence is not an Artifact (a reference input slot, a supplied Skill, an external document)."
          },
          "locator": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200,
            "default": null,
            "description": "Page, line, section, byte range, or similar."
          },
          "quote": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000,
            "default": null
          }
        }
      },
      "x-mutable": true,
      "default": [],
      "description": "Structured evidence pointers, at least rubric.citations.min_items of them on a completed assignment."
    },
    "confidence": {
      "type": [
        "number",
        "null"
      ],
      "minimum": 0,
      "maximum": 1,
      "x-mutable": true,
      "default": null,
      "description": "Overall declared confidence in [0, 1]; required when the rubric says so. Lives here, not inside response, so it reads the same across every protocol."
    },
    "decline_reason": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 500,
      "x-mutable": true,
      "default": null
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "x-mutable": false
    },
    "accepted_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "x-mutable": true,
      "default": null
    },
    "completed_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "x-mutable": true,
      "default": null
    },
    "expired_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "x-mutable": true,
      "default": null
    },
    "invalid_reason": {
      "type": [
        "string",
        "null"
      ],
      "maxLength": 2000,
      "x-mutable": true,
      "default": null,
      "description": "For invalid assignments: which rubric requirement the response failed."
    },
    "hold_until": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "When the claim lapses if no response has been recorded (claimed_at + the protocol's claim_hold_minutes). Null for agent-kind assignments.",
      "examples": [
        "2026-09-05T12:00:00Z"
      ]
    }
  }
}